@vellumai/assistant 0.4.26 → 0.4.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +2 -2
- package/AGENTS.md +5 -0
- package/ARCHITECTURE.md +169 -69
- package/Dockerfile +1 -1
- package/README.md +111 -112
- package/bun.lock +0 -3
- package/docs/architecture/integrations.md +0 -1
- package/docs/architecture/memory.md +100 -63
- package/docs/error-handling.md +71 -0
- package/docs/runbook-trusted-contacts.md +10 -9
- package/docs/trusted-contact-access.md +48 -46
- package/package.json +3 -3
- package/scripts/compare-benchmarks.sh +12 -5
- package/scripts/ipc/check-swift-decoder-drift.ts +3 -0
- package/scripts/test.sh +89 -5
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +46 -0
- package/src/__tests__/access-request-decision.test.ts +0 -1
- package/src/__tests__/account-registry.test.ts +1 -1
- package/src/__tests__/actor-token-service.test.ts +36 -23
- package/src/__tests__/agent-loop-thinking.test.ts +29 -13
- package/src/__tests__/agent-loop.test.ts +2 -1
- package/src/__tests__/app-builder-tool-scripts.test.ts +1 -1
- package/src/__tests__/approval-routes-http.test.ts +2 -2
- package/src/__tests__/asset-materialize-tool.test.ts +7 -7
- package/src/__tests__/asset-search-tool.test.ts +7 -7
- package/src/__tests__/browser-fill-credential.test.ts +1 -1
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +217 -0
- package/src/__tests__/call-controller.test.ts +99 -69
- package/src/__tests__/call-start-guardian-guard.test.ts +1 -1
- package/src/__tests__/channel-approval-routes.test.ts +113 -70
- package/src/__tests__/channel-guardian.test.ts +173 -282
- package/src/__tests__/channel-readiness-service.test.ts +6 -2
- package/src/__tests__/channel-reply-delivery.test.ts +2 -2
- package/src/__tests__/channel-retry-sweep.test.ts +14 -14
- package/src/__tests__/checker.test.ts +12 -31
- package/src/__tests__/claude-code-tool-profiles.test.ts +1 -1
- package/src/__tests__/commit-message-enrichment-service.test.ts +67 -59
- package/src/__tests__/compaction.benchmark.test.ts +6 -2
- package/src/__tests__/computer-use-tools.test.ts +1 -1
- package/src/__tests__/config-schema.test.ts +66 -7
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -29
- package/src/__tests__/contacts-tools.test.ts +63 -2
- package/src/__tests__/context-overflow-approval.test.ts +141 -0
- package/src/__tests__/context-overflow-policy.test.ts +171 -0
- package/src/__tests__/context-overflow-reducer.test.ts +533 -0
- package/src/__tests__/context-window-manager.test.ts +97 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +38 -46
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +214 -10
- package/src/__tests__/conversation-routes.test.ts +4 -7
- package/src/__tests__/credential-broker-browser-fill.test.ts +13 -2
- package/src/__tests__/credential-security-e2e.test.ts +1 -1
- package/src/__tests__/credential-security-invariants.test.ts +1 -1
- package/src/__tests__/credential-vault-unit.test.ts +1 -1
- package/src/__tests__/credential-vault.test.ts +11 -8
- package/src/__tests__/daemon-lifecycle.test.ts +2 -2
- package/src/__tests__/daemon-server-session-init.test.ts +6 -6
- package/src/__tests__/delete-managed-skill-tool.test.ts +1 -1
- package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -2
- package/src/__tests__/emit-signal-routing-intent.test.ts +4 -0
- package/src/__tests__/encrypted-store.test.ts +10 -7
- package/src/__tests__/ephemeral-permissions.test.ts +3 -3
- package/src/__tests__/file-edit-tool.test.ts +1 -1
- package/src/__tests__/file-read-tool.test.ts +1 -1
- package/src/__tests__/file-write-tool.test.ts +1 -1
- package/src/__tests__/fixtures/credential-security-fixtures.ts +87 -64
- package/src/__tests__/fixtures/media-reuse-fixtures.ts +37 -31
- package/src/__tests__/fixtures/mock-signup-server.ts +171 -115
- package/src/__tests__/fixtures/proxy-fixtures.ts +39 -39
- package/src/__tests__/followup-tools.test.ts +1 -1
- package/src/__tests__/gateway-only-guard.test.ts +3 -0
- package/src/__tests__/guardian-actions-endpoint.test.ts +543 -1
- package/src/__tests__/guardian-control-plane-policy.test.ts +15 -15
- package/src/__tests__/guardian-dispatch.test.ts +79 -1
- package/src/__tests__/guardian-grant-minting.test.ts +14 -14
- package/src/__tests__/guardian-outbound-http.test.ts +1 -2
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -41
- package/src/__tests__/guardian-routing-invariants.test.ts +2 -5
- package/src/__tests__/guardian-routing-state.test.ts +36 -52
- package/src/__tests__/guardian-verification-intent-routing.test.ts +4 -6
- package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +2 -2
- package/src/__tests__/handle-user-message-secret-resume.test.ts +39 -1
- package/src/__tests__/handlers-cu-observation-blob.test.ts +21 -10
- package/src/__tests__/handlers-telegram-config.test.ts +14 -14
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +23 -2
- package/src/__tests__/headless-browser-interactions.test.ts +1 -1
- package/src/__tests__/headless-browser-navigate.test.ts +1 -1
- package/src/__tests__/headless-browser-read-tools.test.ts +1 -1
- package/src/__tests__/headless-browser-snapshot.test.ts +1 -1
- package/src/__tests__/heartbeat-service.test.ts +45 -2
- package/src/__tests__/host-file-edit-tool.test.ts +1 -1
- package/src/__tests__/host-file-read-tool.test.ts +1 -1
- package/src/__tests__/host-file-write-tool.test.ts +1 -1
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/inbound-invite-redemption.test.ts +16 -18
- package/src/__tests__/ingress-reconcile.test.ts +2 -2
- package/src/__tests__/ingress-routes-http.test.ts +2 -1
- package/src/__tests__/integrations-cli.test.ts +256 -0
- package/src/__tests__/intent-routing.test.ts +4 -5
- package/src/__tests__/invite-redemption-service.test.ts +4 -3
- package/src/__tests__/ipc-snapshot.test.ts +28 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +1 -1
- package/src/__tests__/mcp-cli.test.ts +136 -57
- package/src/__tests__/mcp-client-auth.test.ts +95 -0
- package/src/__tests__/media-generate-image.test.ts +2 -2
- package/src/__tests__/media-reuse-story.e2e.test.ts +8 -8
- package/src/__tests__/memory-regressions.test.ts +6 -6
- package/src/__tests__/messaging-send-tool.test.ts +1 -1
- package/src/__tests__/migration-cross-version-compatibility.test.ts +1855 -0
- package/src/__tests__/migration-export-http.test.ts +540 -0
- package/src/__tests__/migration-import-commit-http.test.ts +823 -0
- package/src/__tests__/migration-import-preflight-http.test.ts +755 -0
- package/src/__tests__/migration-parity-persistence.test.ts +1854 -0
- package/src/__tests__/migration-transport.test.ts +904 -0
- package/src/__tests__/migration-validate-http.test.ts +698 -0
- package/src/__tests__/migration-wizard.test.ts +1289 -0
- package/src/__tests__/non-member-access-request.test.ts +17 -17
- package/src/__tests__/notification-decision-strategy.test.ts +110 -2
- package/src/__tests__/notification-deep-link.test.ts +18 -0
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/oauth2-gateway-transport.test.ts +1 -1
- package/src/__tests__/playbook-execution.test.ts +1 -1
- package/src/__tests__/playbook-tools.test.ts +1 -1
- package/src/__tests__/provider-streaming.benchmark.test.ts +3 -1
- package/src/__tests__/proxy-approval-callback.test.ts +1 -1
- package/src/__tests__/qdrant-manager.test.ts +40 -11
- package/src/__tests__/rebind-secrets-screen.test.ts +839 -0
- package/src/__tests__/recording-handler.test.ts +2 -2
- package/src/__tests__/recording-intent-handler.test.ts +3 -3
- package/src/__tests__/recording-state-machine.test.ts +2 -2
- package/src/__tests__/relay-server.test.ts +506 -227
- package/src/__tests__/reminder-store.test.ts +8 -0
- package/src/__tests__/reminder.test.ts +8 -0
- package/src/__tests__/{resolve-guardian-trust-class.test.ts → resolve-trust-class.test.ts} +11 -17
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +1 -1
- package/src/__tests__/schedule-tools.test.ts +1 -1
- package/src/__tests__/script-proxy-certs.test.ts +1 -1
- package/src/__tests__/script-proxy-connect-tunnel.test.ts +2 -3
- package/src/__tests__/script-proxy-decision-trace.test.ts +2 -2
- package/src/__tests__/script-proxy-http-forwarder.test.ts +1 -1
- package/src/__tests__/script-proxy-injection-runtime.test.ts +5 -5
- package/src/__tests__/script-proxy-mitm-handler.test.ts +4 -4
- package/src/__tests__/script-proxy-policy-runtime.test.ts +2 -2
- package/src/__tests__/script-proxy-policy.test.ts +2 -2
- package/src/__tests__/script-proxy-session-manager.test.ts +4 -7
- package/src/__tests__/script-proxy-session-runtime.test.ts +1 -6
- package/src/__tests__/secret-onetime-send.test.ts +4 -4
- package/src/__tests__/secret-scanner-executor.test.ts +2 -2
- package/src/__tests__/send-endpoint-busy.test.ts +11 -9
- package/src/__tests__/send-notification-tool.test.ts +2 -2
- package/src/__tests__/session-abort-tool-results.test.ts +17 -2
- package/src/__tests__/session-agent-loop.test.ts +456 -35
- package/src/__tests__/session-confirmation-signals.test.ts +3 -2
- package/src/__tests__/session-conflict-gate.test.ts +20 -3
- package/src/__tests__/session-init.benchmark.test.ts +2 -2
- package/src/__tests__/session-load-history-repair.test.ts +7 -7
- package/src/__tests__/session-pre-run-repair.test.ts +17 -2
- package/src/__tests__/session-profile-injection.test.ts +20 -3
- package/src/__tests__/session-provider-retry-repair.test.ts +86 -6
- package/src/__tests__/session-queue.test.ts +33 -18
- package/src/__tests__/session-runtime-assembly.test.ts +147 -1
- package/src/__tests__/session-runtime-workspace.test.ts +40 -0
- package/src/__tests__/session-slash-known.test.ts +21 -3
- package/src/__tests__/session-slash-queue.test.ts +17 -2
- package/src/__tests__/session-slash-unknown.test.ts +17 -2
- package/src/__tests__/session-surfaces-deselection.test.ts +208 -0
- package/src/__tests__/session-workspace-cache-state.test.ts +2 -2
- package/src/__tests__/session-workspace-injection.test.ts +17 -2
- package/src/__tests__/session-workspace-tool-tracking.test.ts +17 -2
- package/src/__tests__/shell-credential-ref.test.ts +1 -1
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -1
- package/src/__tests__/skill-load-tool.test.ts +1 -1
- package/src/__tests__/skill-script-runner-host.test.ts +1 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -1
- package/src/__tests__/skill-script-runner.test.ts +1 -1
- package/src/__tests__/skill-tool-factory.test.ts +1 -1
- package/src/__tests__/slack-skill.test.ts +3 -2
- package/src/__tests__/subagent-tools.test.ts +3 -3
- package/src/__tests__/swarm-recursion.test.ts +1 -1
- package/src/__tests__/swarm-session-integration.test.ts +1 -1
- package/src/__tests__/swarm-tool.test.ts +1 -1
- package/src/__tests__/task-management-tools.test.ts +1 -1
- package/src/__tests__/task-tools.test.ts +1 -1
- package/src/__tests__/terminal-tools.test.ts +1 -1
- package/src/__tests__/test-support/browser-skill-harness.ts +39 -27
- package/src/__tests__/test-support/computer-use-skill-harness.ts +14 -14
- package/src/__tests__/tool-approval-handler.test.ts +15 -15
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -1
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
- package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +23 -182
- package/src/__tests__/tool-grant-request-escalation.test.ts +11 -11
- package/src/__tests__/tool-permission-simulate-handler.test.ts +4 -4
- package/src/__tests__/transfer-progress-screen.test.ts +1180 -0
- package/src/__tests__/trust-context-guards.test.ts +25 -29
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +23 -21
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +37 -40
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +29 -25
- package/src/__tests__/trusted-contact-multichannel.test.ts +25 -24
- package/src/__tests__/trusted-contact-verification.test.ts +63 -77
- package/src/__tests__/turn-commit.test.ts +18 -18
- package/src/__tests__/twilio-provider.test.ts +7 -7
- package/src/__tests__/validation-results-screen.test.ts +1107 -0
- package/src/__tests__/view-image-tool.test.ts +1 -1
- package/src/__tests__/voice-invite-redemption.test.ts +3 -2
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +12 -12
- package/src/__tests__/voice-session-bridge.test.ts +24 -24
- package/src/agent/attachments.ts +3 -1
- package/src/agent/loop.ts +13 -13
- package/src/agent/message-types.ts +13 -7
- package/src/amazon/cart.ts +59 -32
- package/src/amazon/checkout.ts +25 -14
- package/src/amazon/client.ts +68 -48
- package/src/amazon/product-details.ts +3 -3
- package/src/amazon/request-extractor.ts +46 -31
- package/src/amazon/search.ts +6 -4
- package/src/amazon/session.ts +33 -24
- package/src/approvals/AGENTS.md +26 -0
- package/src/approvals/approval-primitive.ts +87 -64
- package/src/approvals/guardian-decision-primitive.ts +172 -81
- package/src/approvals/guardian-request-resolvers.ts +262 -155
- package/src/autonomy/autonomy-resolver.ts +7 -5
- package/src/autonomy/autonomy-store.ts +34 -19
- package/src/autonomy/disposition-mapper.ts +5 -5
- package/src/autonomy/index.ts +6 -6
- package/src/autonomy/types.ts +7 -3
- package/src/browser-extension-relay/client.ts +50 -19
- package/src/browser-extension-relay/protocol.ts +11 -11
- package/src/browser-extension-relay/server.ts +45 -20
- package/src/bundler/app-bundler.ts +75 -50
- package/src/bundler/bundle-scanner.ts +145 -41
- package/src/bundler/bundle-signer.ts +16 -14
- package/src/bundler/signature-verifier.ts +36 -33
- package/src/calls/call-constants.ts +10 -3
- package/src/calls/call-controller.ts +473 -214
- package/src/calls/call-conversation-messages.ts +25 -15
- package/src/calls/call-domain.ts +401 -148
- package/src/calls/call-pointer-message-composer.ts +26 -21
- package/src/calls/call-pointer-messages.ts +52 -28
- package/src/calls/call-recovery.ts +53 -37
- package/src/calls/call-state-machine.ts +37 -7
- package/src/calls/call-state.ts +35 -13
- package/src/calls/call-store.ts +165 -77
- package/src/calls/elevenlabs-client.ts +39 -20
- package/src/calls/guardian-action-sweep.ts +42 -24
- package/src/calls/guardian-dispatch.ts +79 -56
- package/src/calls/guardian-question-copy.ts +28 -23
- package/src/calls/relay-server.ts +1121 -532
- package/src/calls/speaker-identification.ts +21 -15
- package/src/calls/twilio-config.ts +34 -17
- package/src/calls/twilio-provider.ts +108 -55
- package/src/calls/twilio-rest.ts +212 -100
- package/src/calls/twilio-routes.ts +165 -92
- package/src/calls/types.ts +55 -7
- package/src/calls/voice-quality.ts +6 -4
- package/src/calls/voice-session-bridge.ts +181 -133
- package/src/channels/config.ts +17 -13
- package/src/channels/types.ts +38 -10
- package/src/cli/amazon.ts +333 -227
- package/src/cli/config-commands.ts +236 -146
- package/src/cli/core-commands.ts +403 -329
- package/src/cli/email-guardrails.ts +38 -19
- package/src/cli/email.ts +207 -153
- package/src/cli/influencer.ts +58 -56
- package/src/cli/integrations.ts +362 -0
- package/src/cli/ipc-client.ts +24 -19
- package/src/cli/map.ts +176 -129
- package/src/cli/mcp.ts +260 -152
- package/src/cli/sequence.ts +165 -107
- package/src/cli/twitter.ts +302 -218
- package/src/cli.ts +418 -279
- package/src/commands/cc-command-registry.ts +52 -27
- package/src/config/agent-schema.ts +217 -134
- package/src/config/assistant-feature-flags.ts +23 -18
- package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +19 -0
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +7 -4
- package/src/config/bundled-skills/app-builder/tools/app-delete.ts +6 -3
- package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +7 -4
- package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +6 -3
- package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +6 -3
- package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +7 -4
- package/src/config/bundled-skills/app-builder/tools/app-list.ts +6 -3
- package/src/config/bundled-skills/app-builder/tools/app-query.ts +6 -3
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +6 -3
- package/src/config/bundled-skills/browser/tools/browser-click.ts +5 -2
- package/src/config/bundled-skills/browser/tools/browser-close.ts +5 -2
- package/src/config/bundled-skills/browser/tools/browser-extract.ts +5 -2
- package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +5 -2
- package/src/config/bundled-skills/browser/tools/browser-hover.ts +5 -2
- package/src/config/bundled-skills/browser/tools/browser-navigate.ts +5 -2
- package/src/config/bundled-skills/browser/tools/browser-press-key.ts +5 -2
- package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +5 -2
- package/src/config/bundled-skills/browser/tools/browser-scroll.ts +5 -2
- package/src/config/bundled-skills/browser/tools/browser-select-option.ts +5 -2
- package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +5 -2
- package/src/config/bundled-skills/browser/tools/browser-type.ts +5 -2
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +13 -6
- package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +5 -2
- package/src/config/bundled-skills/claude-code/TOOLS.json +4 -0
- package/src/config/bundled-skills/claude-code/tools/claude-code.ts +5 -2
- package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
- package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +6 -3
- package/src/config/bundled-skills/computer-use/tools/computer-use-done.ts +6 -3
- package/src/config/bundled-skills/computer-use/tools/computer-use-double-click.ts +10 -3
- package/src/config/bundled-skills/computer-use/tools/computer-use-drag.ts +6 -3
- package/src/config/bundled-skills/computer-use/tools/computer-use-key.ts +6 -3
- package/src/config/bundled-skills/computer-use/tools/computer-use-open-app.ts +6 -3
- package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +10 -3
- package/src/config/bundled-skills/computer-use/tools/computer-use-respond.ts +6 -3
- package/src/config/bundled-skills/computer-use/tools/computer-use-right-click.ts +10 -3
- package/src/config/bundled-skills/computer-use/tools/computer-use-run-applescript.ts +10 -3
- package/src/config/bundled-skills/computer-use/tools/computer-use-scroll.ts +6 -3
- package/src/config/bundled-skills/computer-use/tools/computer-use-type-text.ts +6 -3
- package/src/config/bundled-skills/computer-use/tools/computer-use-wait.ts +6 -3
- package/src/config/bundled-skills/configure-settings/SKILL.md +28 -14
- package/src/config/bundled-skills/contacts/SKILL.md +446 -15
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +99 -20
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +74 -17
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +89 -26
- package/src/config/bundled-skills/document/tools/document-create.ts +5 -2
- package/src/config/bundled-skills/document/tools/document-update.ts +5 -2
- package/src/config/bundled-skills/doordash/doordash-cli.ts +17 -7
- package/src/config/bundled-skills/email-setup/SKILL.md +9 -9
- package/src/config/bundled-skills/followups/tools/followup-create.ts +5 -2
- package/src/config/bundled-skills/followups/tools/followup-list.ts +5 -2
- package/src/config/bundled-skills/followups/tools/followup-resolve.ts +5 -2
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +44 -32
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +11 -5
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +13 -7
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +11 -5
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +13 -7
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +28 -12
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +6 -4
- package/src/config/bundled-skills/google-calendar/types.ts +3 -3
- package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +46 -24
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +36 -19
- package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +60 -35
- package/src/config/bundled-skills/mcp-setup/SKILL.md +75 -0
- package/src/config/bundled-skills/media-processing/SKILL.md +55 -15
- package/src/config/bundled-skills/media-processing/TOOLS.json +20 -2
- package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +12 -10
- package/src/config/bundled-skills/media-processing/__tests__/cost-tracker.test.ts +34 -19
- package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +82 -66
- package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +148 -0
- package/src/config/bundled-skills/media-processing/services/concurrency-pool.ts +1 -1
- package/src/config/bundled-skills/media-processing/services/cost-tracker.ts +8 -3
- package/src/config/bundled-skills/media-processing/services/gemini-map.ts +117 -53
- package/src/config/bundled-skills/media-processing/services/gemini-video.ts +273 -0
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +185 -97
- package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +32 -27
- package/src/config/bundled-skills/media-processing/services/reduce.ts +101 -24
- package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +121 -55
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +58 -24
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +177 -91
- package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +98 -70
- package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +59 -19
- package/src/config/bundled-skills/media-processing/tools/media-status.ts +26 -10
- package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +29 -14
- package/src/config/bundled-skills/messaging/SKILL.md +7 -5
- package/src/config/bundled-skills/messaging/TOOLS.json +7 -7
- package/src/config/bundled-skills/messaging/tools/gmail-archive-by-query.ts +31 -13
- package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +16 -10
- package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +18 -9
- package/src/config/bundled-skills/messaging/tools/gmail-download-attachment.ts +23 -16
- package/src/config/bundled-skills/messaging/tools/gmail-draft.ts +28 -12
- package/src/config/bundled-skills/messaging/tools/gmail-filters.ts +41 -21
- package/src/config/bundled-skills/messaging/tools/gmail-follow-up.ts +44 -23
- package/src/config/bundled-skills/messaging/tools/gmail-forward.ts +73 -33
- package/src/config/bundled-skills/messaging/tools/gmail-label.ts +15 -9
- package/src/config/bundled-skills/messaging/tools/gmail-list-attachments.ts +22 -14
- package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +99 -50
- package/src/config/bundled-skills/messaging/tools/gmail-send-draft.ts +14 -8
- package/src/config/bundled-skills/messaging/tools/gmail-send-with-attachments.ts +63 -44
- package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +90 -46
- package/src/config/bundled-skills/messaging/tools/gmail-summarize-thread.ts +43 -22
- package/src/config/bundled-skills/messaging/tools/gmail-trash.ts +15 -9
- package/src/config/bundled-skills/messaging/tools/gmail-triage.ts +51 -22
- package/src/config/bundled-skills/messaging/tools/gmail-unsubscribe.ts +62 -26
- package/src/config/bundled-skills/messaging/tools/gmail-vacation.ts +34 -19
- package/src/config/bundled-skills/messaging/tools/google-contacts.ts +32 -16
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +10 -4
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +91 -47
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +21 -9
- package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +9 -3
- package/src/config/bundled-skills/messaging/tools/messaging-draft.ts +30 -17
- package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +10 -4
- package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +14 -6
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +16 -5
- package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +63 -36
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +10 -4
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +30 -12
- package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +48 -29
- package/src/config/bundled-skills/messaging/tools/scan-result-store.ts +20 -6
- package/src/config/bundled-skills/messaging/tools/send-notification.ts +1 -1
- package/src/config/bundled-skills/messaging/tools/sequence-analytics.ts +59 -22
- package/src/config/bundled-skills/messaging/tools/sequence-cancel.ts +13 -7
- package/src/config/bundled-skills/messaging/tools/sequence-create.ts +27 -12
- package/src/config/bundled-skills/messaging/tools/sequence-delete.ts +14 -6
- package/src/config/bundled-skills/messaging/tools/sequence-enroll.ts +30 -11
- package/src/config/bundled-skills/messaging/tools/sequence-enrollment-list.ts +16 -8
- package/src/config/bundled-skills/messaging/tools/sequence-get.ts +31 -13
- package/src/config/bundled-skills/messaging/tools/sequence-import.ts +38 -22
- package/src/config/bundled-skills/messaging/tools/sequence-list.ts +16 -7
- package/src/config/bundled-skills/messaging/tools/sequence-pause.ts +29 -10
- package/src/config/bundled-skills/messaging/tools/sequence-resume.ts +16 -8
- package/src/config/bundled-skills/messaging/tools/sequence-update.ts +35 -16
- package/src/config/bundled-skills/messaging/tools/shared.ts +26 -12
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +69 -34
- package/src/config/bundled-skills/notifications/tools/shared.ts +1 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +46 -48
- package/src/config/bundled-skills/phone-calls/tools/call-end.ts +1 -1
- package/src/config/bundled-skills/phone-calls/tools/call-start.ts +1 -1
- package/src/config/bundled-skills/phone-calls/tools/call-status.ts +1 -1
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +91 -51
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +30 -16
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +66 -27
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +89 -42
- package/src/config/bundled-skills/public-ingress/SKILL.md +26 -19
- package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +5 -2
- package/src/config/bundled-skills/reminder/tools/reminder-create.ts +5 -2
- package/src/config/bundled-skills/reminder/tools/reminder-list.ts +5 -2
- package/src/config/bundled-skills/schedule/tools/schedule-create.ts +5 -2
- package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +5 -2
- package/src/config/bundled-skills/schedule/tools/schedule-list.ts +5 -2
- package/src/config/bundled-skills/schedule/tools/schedule-update.ts +5 -2
- package/src/config/bundled-skills/screen-recording/SKILL.md +11 -3
- package/src/config/bundled-skills/self-upgrade/SKILL.md +9 -8
- package/src/config/bundled-skills/slack/TOOLS.json +33 -15
- package/src/config/bundled-skills/slack/tools/shared.ts +7 -5
- package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +11 -5
- package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +11 -5
- package/src/config/bundled-skills/slack/tools/slack-configure-channels.ts +46 -16
- package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +11 -5
- package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +28 -0
- package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +12 -6
- package/src/config/bundled-skills/sms-setup/SKILL.md +5 -8
- package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +5 -2
- package/src/config/bundled-skills/subagent/tools/subagent-message.ts +5 -2
- package/src/config/bundled-skills/subagent/tools/subagent-read.ts +5 -2
- package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +5 -2
- package/src/config/bundled-skills/subagent/tools/subagent-status.ts +5 -2
- package/src/config/bundled-skills/tasks/tools/task-delete.ts +5 -2
- package/src/config/bundled-skills/tasks/tools/task-list-add.ts +5 -2
- package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +5 -2
- package/src/config/bundled-skills/tasks/tools/task-list-show.ts +5 -2
- package/src/config/bundled-skills/tasks/tools/task-list-update.ts +5 -2
- package/src/config/bundled-skills/tasks/tools/task-list.ts +5 -2
- package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +5 -2
- package/src/config/bundled-skills/tasks/tools/task-run.ts +5 -2
- package/src/config/bundled-skills/tasks/tools/task-save.ts +5 -2
- package/src/config/bundled-skills/telegram-setup/SKILL.md +7 -8
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +232 -127
- package/src/config/bundled-skills/twilio-setup/SKILL.md +7 -12
- package/src/config/bundled-skills/twitter/SKILL.md +19 -2
- package/src/config/bundled-skills/voice-setup/SKILL.md +5 -5
- package/src/config/bundled-skills/watcher/tools/watcher-create.ts +5 -2
- package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +5 -2
- package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +5 -2
- package/src/config/bundled-skills/watcher/tools/watcher-list.ts +5 -2
- package/src/config/bundled-skills/watcher/tools/watcher-update.ts +5 -2
- package/src/config/bundled-skills/weather/tools/get-weather.ts +5 -2
- package/src/config/calls-schema.ts +108 -63
- package/src/config/computer-use-prompt.ts +7 -7
- package/src/config/core-schema.ts +239 -155
- package/src/config/defaults.ts +2 -2
- package/src/config/elevenlabs-schema.ts +15 -15
- package/src/config/env-registry.ts +33 -33
- package/src/config/feature-flag-registry.json +31 -7
- package/src/config/loader.ts +118 -58
- package/src/config/mcp-schema.ts +29 -15
- package/src/config/memory-schema.ts +434 -229
- package/src/config/notifications-schema.ts +4 -4
- package/src/config/sandbox-schema.ts +2 -2
- package/src/config/schema.ts +12 -2
- package/src/config/skill-state.ts +27 -15
- package/src/config/skills-schema.ts +72 -23
- package/src/config/skills.ts +303 -143
- package/src/config/system-prompt.ts +25 -6
- package/src/config/types.ts +1 -1
- package/src/config/update-bulletin-format.ts +3 -3
- package/src/config/update-bulletin-state.ts +15 -6
- package/src/config/update-bulletin-template-path.ts +8 -4
- package/src/config/update-bulletin.ts +33 -14
- package/src/config/user-reference.ts +8 -8
- package/src/contacts/contact-events.ts +21 -0
- package/src/contacts/contact-store.ts +622 -100
- package/src/contacts/contacts-write.ts +287 -0
- package/src/contacts/index.ts +13 -4
- package/src/contacts/startup-migration.ts +21 -0
- package/src/contacts/types.ts +47 -2
- package/src/context/token-estimator.ts +54 -31
- package/src/context/tool-result-truncation.ts +41 -7
- package/src/context/window-manager.ts +225 -120
- package/src/daemon/approval-generators.ts +83 -55
- package/src/daemon/approved-devices-store.ts +33 -20
- package/src/daemon/assistant-attachments.ts +134 -98
- package/src/daemon/auth-manager.ts +17 -15
- package/src/daemon/classifier.ts +117 -46
- package/src/daemon/computer-use-session.ts +316 -187
- package/src/daemon/config-watcher.ts +91 -44
- package/src/daemon/connection-policy.ts +18 -10
- package/src/daemon/context-overflow-approval.ts +48 -0
- package/src/daemon/context-overflow-policy.ts +50 -0
- package/src/daemon/context-overflow-reducer.ts +300 -0
- package/src/daemon/daemon-control.ts +79 -51
- package/src/daemon/date-context.ts +119 -69
- package/src/daemon/dictation-profile-store.ts +94 -48
- package/src/daemon/dictation-text-processing.ts +33 -12
- package/src/daemon/doordash-steps.ts +92 -49
- package/src/daemon/guardian-action-generators.ts +62 -46
- package/src/daemon/guardian-verification-intent.ts +31 -18
- package/src/daemon/handlers/apps.ts +257 -111
- package/src/daemon/handlers/avatar.ts +20 -15
- package/src/daemon/handlers/computer-use.ts +82 -39
- package/src/daemon/handlers/config-channels.ts +146 -69
- package/src/daemon/handlers/config-heartbeat.ts +114 -59
- package/src/daemon/handlers/config-inbox.ts +277 -106
- package/src/daemon/handlers/config-ingress.ts +127 -55
- package/src/daemon/handlers/config-integrations.ts +145 -88
- package/src/daemon/handlers/config-model.ts +58 -22
- package/src/daemon/handlers/config-platform.ts +40 -16
- package/src/daemon/handlers/config-scheduling.ts +109 -48
- package/src/daemon/handlers/config-slack-channel.ts +67 -35
- package/src/daemon/handlers/config-slack.ts +21 -20
- package/src/daemon/handlers/config-telegram.ts +100 -70
- package/src/daemon/handlers/config-tools.ts +103 -55
- package/src/daemon/handlers/config-trust.ts +50 -20
- package/src/daemon/handlers/config.ts +72 -24
- package/src/daemon/handlers/contacts.ts +163 -0
- package/src/daemon/handlers/diagnostics.ts +90 -48
- package/src/daemon/handlers/documents.ts +74 -46
- package/src/daemon/handlers/guardian-actions.ts +118 -71
- package/src/daemon/handlers/home-base.ts +19 -16
- package/src/daemon/handlers/identity.ts +65 -45
- package/src/daemon/handlers/index.ts +78 -54
- package/src/daemon/handlers/misc.ts +664 -234
- package/src/daemon/handlers/navigate-settings.ts +14 -11
- package/src/daemon/handlers/oauth-connect.ts +48 -35
- package/src/daemon/handlers/open-bundle-handler.ts +31 -24
- package/src/daemon/handlers/pairing.ts +51 -25
- package/src/daemon/handlers/publish.ts +55 -33
- package/src/daemon/handlers/recording.ts +378 -162
- package/src/daemon/handlers/sessions.ts +923 -423
- package/src/daemon/handlers/shared.ts +202 -117
- package/src/daemon/handlers/signing.ts +25 -6
- package/src/daemon/handlers/subagents.ts +117 -56
- package/src/daemon/handlers/twitter-auth.ts +70 -49
- package/src/daemon/handlers/work-items.ts +264 -112
- package/src/daemon/handlers/workspace-files.ts +27 -20
- package/src/daemon/handlers.ts +2 -2
- package/src/daemon/history-repair.ts +16 -15
- package/src/daemon/identity-helpers.ts +4 -4
- package/src/daemon/install-cli-launchers.ts +33 -22
- package/src/daemon/ipc-blob-store.ts +38 -24
- package/src/daemon/ipc-contract/apps.ts +61 -49
- package/src/daemon/ipc-contract/computer-use.ts +47 -37
- package/src/daemon/ipc-contract/contacts.ts +69 -0
- package/src/daemon/ipc-contract/diagnostics.ts +14 -14
- package/src/daemon/ipc-contract/documents.ts +8 -8
- package/src/daemon/ipc-contract/guardian-actions.ts +4 -4
- package/src/daemon/ipc-contract/inbox.ts +16 -16
- package/src/daemon/ipc-contract/integrations.ts +57 -44
- package/src/daemon/ipc-contract/memory.ts +3 -5
- package/src/daemon/ipc-contract/messages.ts +95 -69
- package/src/daemon/ipc-contract/notifications.ts +10 -6
- package/src/daemon/ipc-contract/pairing.ts +8 -8
- package/src/daemon/ipc-contract/schedules.ts +20 -20
- package/src/daemon/ipc-contract/sessions.ts +88 -57
- package/src/daemon/ipc-contract/settings.ts +12 -7
- package/src/daemon/ipc-contract/shared.ts +9 -7
- package/src/daemon/ipc-contract/skills.ts +46 -26
- package/src/daemon/ipc-contract/subagents.ts +9 -9
- package/src/daemon/ipc-contract/trust.ts +11 -11
- package/src/daemon/ipc-contract/work-items.ts +33 -28
- package/src/daemon/ipc-contract/workspace.ts +28 -21
- package/src/daemon/ipc-contract-inventory.json +8 -0
- package/src/daemon/ipc-contract-inventory.ts +29 -26
- package/src/daemon/ipc-contract.ts +111 -44
- package/src/daemon/ipc-handler.ts +27 -19
- package/src/daemon/ipc-protocol.ts +22 -12
- package/src/daemon/ipc-validate.ts +91 -46
- package/src/daemon/lifecycle.ts +25 -1
- package/src/daemon/main.ts +10 -8
- package/src/daemon/media-visibility-policy.ts +3 -1
- package/src/daemon/pairing-store.ts +72 -40
- package/src/daemon/providers-setup.ts +35 -25
- package/src/daemon/recording-executor.ts +37 -30
- package/src/daemon/recording-intent-fallback.ts +58 -28
- package/src/daemon/recording-intent.ts +71 -61
- package/src/daemon/ride-shotgun-handler.ts +201 -121
- package/src/daemon/seed-files.ts +28 -17
- package/src/daemon/server.ts +23 -14
- package/src/daemon/session-agent-loop-handlers.ts +261 -135
- package/src/daemon/session-agent-loop.ts +795 -253
- package/src/daemon/session-attachments.ts +104 -39
- package/src/daemon/session-conflict-gate.ts +72 -28
- package/src/daemon/session-dynamic-profile.ts +36 -22
- package/src/daemon/session-error.ts +50 -45
- package/src/daemon/session-evictor.ts +17 -10
- package/src/daemon/session-history.ts +201 -89
- package/src/daemon/session-lifecycle.ts +79 -42
- package/src/daemon/session-media-retry.ts +89 -41
- package/src/daemon/session-memory.ts +77 -55
- package/src/daemon/session-messaging.ts +261 -111
- package/src/daemon/session-notifiers.ts +57 -45
- package/src/daemon/session-process.ts +370 -154
- package/src/daemon/session-queue-manager.ts +30 -13
- package/src/daemon/session-runtime-assembly.ts +61 -15
- package/src/daemon/session-skill-tools.ts +84 -36
- package/src/daemon/session-slash.ts +178 -113
- package/src/daemon/session-surfaces.ts +498 -211
- package/src/daemon/session-tool-setup.ts +22 -17
- package/src/daemon/session-usage.ts +26 -13
- package/src/daemon/session-workspace.ts +7 -4
- package/src/daemon/session.ts +18 -19
- package/src/daemon/shutdown-handlers.ts +36 -33
- package/src/daemon/tls-certs.ts +90 -57
- package/src/daemon/tool-side-effects.ts +97 -65
- package/src/daemon/trace-emitter.ts +8 -7
- package/src/daemon/video-thumbnail.ts +55 -25
- package/src/daemon/watch-handler.ts +164 -86
- package/src/email/provider.ts +1 -1
- package/src/email/providers/agentmail.ts +87 -45
- package/src/email/providers/index.ts +19 -14
- package/src/email/service.ts +52 -24
- package/src/email/types.ts +2 -2
- package/src/errors.ts +1 -1
- package/src/events/bus.ts +30 -10
- package/src/events/domain-events.ts +19 -13
- package/src/events/index.ts +6 -6
- package/src/events/tool-audit-listener.ts +34 -20
- package/src/events/tool-domain-event-publisher.ts +22 -20
- package/src/events/tool-metrics-listener.ts +26 -21
- package/src/events/tool-notification-listener.ts +5 -5
- package/src/events/tool-profiling-listener.ts +33 -23
- package/src/events/tool-trace-listener.ts +70 -46
- package/src/export/formatter.ts +38 -32
- package/src/followups/followup-store.ts +43 -36
- package/src/followups/index.ts +2 -2
- package/src/followups/types.ts +1 -1
- package/src/gallery/default-gallery.ts +37 -34
- package/src/gallery/gallery-manifest.ts +9 -9
- package/src/heartbeat/heartbeat-service.ts +59 -37
- package/src/home-base/app-link-store.ts +14 -12
- package/src/home-base/bootstrap.ts +14 -8
- package/src/home-base/prebuilt/seed.ts +35 -26
- package/src/home-base/prebuilt-home-base-updater.ts +14 -8
- package/src/hooks/cli.ts +56 -43
- package/src/hooks/config.ts +27 -14
- package/src/hooks/discovery.ts +53 -33
- package/src/hooks/manager.ts +50 -26
- package/src/hooks/runner.ts +35 -29
- package/src/hooks/templates.ts +38 -15
- package/src/hooks/types.ts +13 -13
- package/src/inbound/platform-callback-registration.ts +21 -15
- package/src/inbound/public-ingress-urls.ts +9 -6
- package/src/index.ts +20 -19
- package/src/influencer/client.ts +269 -108
- package/src/instrument.ts +3 -1
- package/src/logfire.ts +64 -39
- package/src/mcp/client.ts +107 -55
- package/src/mcp/manager.ts +45 -18
- package/src/mcp/mcp-oauth-provider.ts +114 -62
- package/src/media/gemini-image-service.ts +28 -21
- package/src/memory/account-store.ts +16 -9
- package/src/memory/admin.ts +87 -57
- package/src/memory/app-git-service.ts +77 -47
- package/src/memory/app-store.ts +151 -77
- package/src/memory/attachments-store.ts +123 -53
- package/src/memory/canonical-guardian-store.ts +190 -48
- package/src/memory/channel-delivery-store.ts +5 -5
- package/src/memory/channel-guardian-store.ts +31 -16
- package/src/memory/checkpoints.ts +14 -7
- package/src/memory/clarification-resolver.ts +219 -104
- package/src/memory/conflict-intent.ts +74 -23
- package/src/memory/conflict-policy.ts +20 -7
- package/src/memory/conflict-store.ts +144 -94
- package/src/memory/contradiction-checker.ts +257 -132
- package/src/memory/conversation-attention-store.ts +72 -32
- package/src/memory/conversation-bootstrap.ts +28 -0
- package/src/memory/conversation-crud.ts +12 -5
- package/src/memory/conversation-display-order-migration.ts +7 -7
- package/src/memory/conversation-key-store.ts +18 -13
- package/src/memory/conversation-queries.ts +130 -52
- package/src/memory/conversation-store.ts +43 -26
- package/src/memory/conversation-title-service.ts +89 -66
- package/src/memory/db-init.ts +90 -2
- package/src/memory/db.ts +10 -3
- package/src/memory/delivery-channels.ts +12 -6
- package/src/memory/delivery-crud.ts +26 -12
- package/src/memory/delivery-status.ts +19 -16
- package/src/memory/embedding-backend.ts +205 -77
- package/src/memory/embedding-gemini.ts +23 -10
- package/src/memory/embedding-local.ts +89 -44
- package/src/memory/embedding-ollama.ts +25 -13
- package/src/memory/embedding-openai.ts +20 -11
- package/src/memory/embedding-runtime-manager.ts +163 -90
- package/src/memory/entity-extractor.ts +185 -123
- package/src/memory/external-conversation-store.ts +30 -12
- package/src/memory/fingerprint.ts +2 -2
- package/src/memory/fts-reconciler.ts +57 -28
- package/src/memory/guardian-action-store.ts +162 -100
- package/src/memory/guardian-approvals.ts +63 -129
- package/src/memory/guardian-rate-limits.ts +20 -9
- package/src/memory/guardian-verification.ts +82 -35
- package/src/memory/indexer.ts +96 -55
- package/src/memory/ingress-invite-store.ts +28 -169
- package/src/memory/items-extractor.ts +313 -157
- package/src/memory/job-handlers/backfill.ts +116 -63
- package/src/memory/job-handlers/cleanup.ts +64 -41
- package/src/memory/job-handlers/conflict.ts +90 -49
- package/src/memory/job-handlers/embedding.ts +32 -17
- package/src/memory/job-handlers/extraction.ts +58 -33
- package/src/memory/job-handlers/index-maintenance.ts +31 -17
- package/src/memory/job-handlers/media-processing.ts +65 -24
- package/src/memory/job-handlers/summarization.ts +186 -128
- package/src/memory/job-utils.ts +100 -57
- package/src/memory/jobs-store.ts +235 -142
- package/src/memory/jobs-worker.ts +167 -83
- package/src/memory/llm-request-log-store.ts +13 -11
- package/src/memory/llm-usage-store.ts +35 -26
- package/src/memory/media-store.ts +151 -44
- package/src/memory/message-content.ts +28 -18
- package/src/memory/migrations/001-job-deferrals.ts +11 -5
- package/src/memory/migrations/002-tool-invocations-fk.ts +14 -6
- package/src/memory/migrations/003-memory-fts-backfill.ts +11 -5
- package/src/memory/migrations/004-entity-relation-dedup.ts +17 -11
- package/src/memory/migrations/005-fingerprint-scope-unique.ts +36 -21
- package/src/memory/migrations/006-scope-salted-fingerprints.ts +35 -20
- package/src/memory/migrations/007-assistant-id-to-self.ts +40 -27
- package/src/memory/migrations/008-remove-assistant-id-columns.ts +58 -36
- package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +36 -22
- package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +21 -11
- package/src/memory/migrations/011-call-sessions-provider-sid-dedup.ts +30 -15
- package/src/memory/migrations/012-call-sessions-add-initiated-from.ts +4 -2
- package/src/memory/migrations/013-guardian-action-tables.ts +29 -11
- package/src/memory/migrations/014-backfill-inbox-thread-state.ts +35 -21
- package/src/memory/migrations/015-drop-active-search-index.ts +17 -11
- package/src/memory/migrations/016-memory-segments-indexes.ts +7 -3
- package/src/memory/migrations/017-memory-items-indexes.ts +4 -2
- package/src/memory/migrations/018-remaining-table-indexes.ts +13 -5
- package/src/memory/migrations/019-notification-tables-schema-migration.ts +34 -20
- package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +87 -53
- package/src/memory/migrations/021-conversation-status-indexes.ts +7 -3
- package/src/memory/migrations/022-add-origin-interface.ts +4 -2
- package/src/memory/migrations/023-memory-item-sources-indexes.ts +4 -2
- package/src/memory/migrations/024-embedding-vector-blob.ts +34 -18
- package/src/memory/migrations/025-messages-fts-backfill.ts +11 -5
- package/src/memory/migrations/026-guardian-verification-sessions.ts +80 -14
- package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +42 -26
- package/src/memory/migrations/027-notification-delivery-pairing-columns.ts +22 -8
- package/src/memory/migrations/027a-guardian-bootstrap-token.ts +11 -3
- package/src/memory/migrations/028-call-session-mode.ts +13 -3
- package/src/memory/migrations/028-notification-delivery-client-ack.ts +22 -8
- package/src/memory/migrations/029-channel-inbound-delivered-segments.ts +7 -3
- package/src/memory/migrations/030-guardian-action-followup.ts +46 -8
- package/src/memory/migrations/030-guardian-verification-purpose.ts +4 -2
- package/src/memory/migrations/031-conversations-thread-type-index.ts +4 -2
- package/src/memory/migrations/032-guardian-delivery-conversation-index.ts +4 -2
- package/src/memory/migrations/032-notification-delivery-thread-decision.ts +22 -8
- package/src/memory/migrations/033-scoped-approval-grants.ts +1 -1
- package/src/memory/migrations/034-guardian-action-tool-metadata.ts +15 -3
- package/src/memory/migrations/035-guardian-action-supersession.ts +15 -3
- package/src/memory/migrations/036-normalize-phone-identities.ts +101 -87
- package/src/memory/migrations/037-voice-invite-columns.ts +22 -4
- package/src/memory/migrations/038-actor-token-records.ts +5 -9
- package/src/memory/migrations/039-actor-refresh-token-records.ts +7 -13
- package/src/memory/migrations/100-core-tables.ts +1 -1
- package/src/memory/migrations/101-watchers-and-logs.ts +1 -1
- package/src/memory/migrations/103-complex-migrations.ts +9 -9
- package/src/memory/migrations/104-core-indexes.ts +188 -64
- package/src/memory/migrations/105-contacts-and-triage.ts +28 -10
- package/src/memory/migrations/106-call-sessions.ts +58 -16
- package/src/memory/migrations/107-followups.ts +16 -6
- package/src/memory/migrations/108-tasks-and-work-items.ts +43 -11
- package/src/memory/migrations/109-external-conversation-bindings.ts +11 -5
- package/src/memory/migrations/110-channel-guardian.ts +48 -10
- package/src/memory/migrations/111-media-assets.ts +52 -18
- package/src/memory/migrations/112-assistant-inbox.ts +32 -12
- package/src/memory/migrations/113-late-migrations.ts +12 -12
- package/src/memory/migrations/114-notifications.ts +28 -12
- package/src/memory/migrations/115-sequences.ts +10 -4
- package/src/memory/migrations/116-messages-fts.ts +1 -1
- package/src/memory/migrations/117-conversation-attention.ts +16 -6
- package/src/memory/migrations/118-reminder-routing-intent.ts +7 -3
- package/src/memory/migrations/119-schema-indexes-and-columns.ts +35 -15
- package/src/memory/migrations/120-fk-cascade-rebuilds.ts +36 -17
- package/src/memory/migrations/121-canonical-guardian-requests.ts +25 -9
- package/src/memory/migrations/122-canonical-guardian-requester-chat-id.ts +11 -3
- package/src/memory/migrations/123-canonical-guardian-deliveries-destination-index.ts +4 -2
- package/src/memory/migrations/124-voice-invite-display-metadata.ts +15 -3
- package/src/memory/migrations/125-guardian-principal-id-columns.ts +22 -4
- package/src/memory/migrations/126-backfill-guardian-principal-id.ts +174 -126
- package/src/memory/migrations/127-guardian-principal-id-not-null.ts +58 -42
- package/src/memory/migrations/128-contacts-role-principal.ts +26 -0
- package/src/memory/migrations/129-contact-channels-access-fields.ts +105 -0
- package/src/memory/migrations/130-contact-channels-type-ext-chat-id-index.ts +15 -0
- package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +134 -0
- package/src/memory/migrations/132-contacts-assistant-id.ts +21 -0
- package/src/memory/migrations/index.ts +82 -73
- package/src/memory/migrations/registry.ts +53 -37
- package/src/memory/migrations/validate-migration-state.ts +73 -46
- package/src/memory/profile-compiler.ts +58 -24
- package/src/memory/published-pages-store.ts +12 -16
- package/src/memory/qdrant-circuit-breaker.ts +28 -20
- package/src/memory/qdrant-client.ts +99 -63
- package/src/memory/qdrant-manager.ts +89 -57
- package/src/memory/query-builder.ts +9 -7
- package/src/memory/raw-query.ts +63 -14
- package/src/memory/recall-cache.ts +15 -8
- package/src/memory/retrieval-budget.ts +0 -1
- package/src/memory/retriever.ts +385 -192
- package/src/memory/schema-migration.ts +1 -1
- package/src/memory/schema.ts +44 -56
- package/src/memory/scoped-approval-grants.ts +99 -45
- package/src/memory/search/entity.ts +102 -40
- package/src/memory/search/formatting.ts +70 -52
- package/src/memory/search/lexical.ts +82 -43
- package/src/memory/search/ranking.ts +103 -39
- package/src/memory/search/semantic.ts +59 -35
- package/src/memory/search/types.ts +8 -8
- package/src/memory/segmenter.ts +20 -12
- package/src/memory/shared-app-links-store.ts +21 -16
- package/src/memory/task-memory-cleanup.ts +18 -8
- package/src/memory/tool-usage-store.ts +27 -19
- package/src/memory/validation.ts +4 -2
- package/src/messaging/activity-analyzer.ts +7 -7
- package/src/messaging/draft-store.ts +13 -10
- package/src/messaging/email-classifier.ts +73 -37
- package/src/messaging/index.ts +3 -3
- package/src/messaging/outreach-classifier.ts +76 -38
- package/src/messaging/provider-types.ts +2 -4
- package/src/messaging/provider.ts +37 -8
- package/src/messaging/providers/gmail/adapter.ts +183 -66
- package/src/messaging/providers/gmail/client.ts +3 -1
- package/src/messaging/providers/gmail/mime-builder.ts +21 -19
- package/src/messaging/providers/gmail/people-client.ts +22 -9
- package/src/messaging/providers/gmail/types.ts +6 -6
- package/src/messaging/providers/slack/adapter.ts +93 -43
- package/src/messaging/providers/slack/client.ts +100 -41
- package/src/messaging/providers/slack/types.ts +6 -0
- package/src/messaging/providers/sms/adapter.ts +76 -40
- package/src/messaging/providers/sms/client.ts +4 -4
- package/src/messaging/providers/telegram-bot/adapter.ts +52 -30
- package/src/messaging/providers/telegram-bot/client.ts +7 -7
- package/src/messaging/providers/whatsapp/adapter.ts +58 -31
- package/src/messaging/providers/whatsapp/client.ts +4 -4
- package/src/messaging/registry.ts +9 -5
- package/src/messaging/style-analyzer.ts +69 -39
- package/src/messaging/thread-summarizer.ts +101 -53
- package/src/messaging/triage-engine.ts +111 -82
- package/src/messaging/types.ts +10 -10
- package/src/migrations/config-merge.ts +18 -10
- package/src/migrations/data-layout.ts +35 -22
- package/src/migrations/data-merge.ts +17 -7
- package/src/migrations/hooks-merge.ts +43 -16
- package/src/migrations/index.ts +6 -6
- package/src/migrations/log.ts +9 -5
- package/src/migrations/skills-merge.ts +17 -7
- package/src/migrations/workspace-layout.ts +39 -25
- package/src/notifications/AGENTS.md +5 -0
- package/src/notifications/adapters/macos.ts +21 -14
- package/src/notifications/adapters/sms.ts +28 -15
- package/src/notifications/adapters/telegram.ts +24 -15
- package/src/notifications/broadcaster.ts +108 -52
- package/src/notifications/conversation-pairing.ts +64 -29
- package/src/notifications/copy-composer.ts +165 -95
- package/src/notifications/decision-engine.ts +353 -147
- package/src/notifications/decisions-store.ts +26 -10
- package/src/notifications/deliveries-store.ts +23 -13
- package/src/notifications/destination-resolver.ts +42 -24
- package/src/notifications/deterministic-checks.ts +78 -27
- package/src/notifications/emit-signal.ts +83 -45
- package/src/notifications/events-store.ts +13 -7
- package/src/notifications/guardian-question-mode.ts +125 -75
- package/src/notifications/preference-extractor.ts +85 -53
- package/src/notifications/preference-summary.ts +31 -18
- package/src/notifications/preferences-store.ts +29 -18
- package/src/notifications/runtime-dispatch.ts +22 -12
- package/src/notifications/signal.ts +4 -4
- package/src/notifications/thread-candidates.ts +59 -23
- package/src/notifications/thread-seed-composer.ts +45 -27
- package/src/notifications/types.ts +19 -10
- package/src/oauth/connect-orchestrator.ts +105 -54
- package/src/oauth/connect-types.ts +3 -3
- package/src/oauth/provider-profiles.ts +80 -59
- package/src/oauth/scope-policy.ts +5 -2
- package/src/oauth/token-persistence.ts +58 -24
- package/src/outbound-proxy/certs.ts +284 -0
- package/src/outbound-proxy/config.ts +94 -0
- package/src/outbound-proxy/connect-tunnel.ts +84 -0
- package/src/outbound-proxy/health.ts +62 -0
- package/src/outbound-proxy/host-pattern-match.ts +67 -0
- package/src/outbound-proxy/http-forwarder.ts +162 -0
- package/src/outbound-proxy/index.ts +80 -0
- package/src/outbound-proxy/logging.ts +193 -0
- package/src/outbound-proxy/mitm-handler.ts +292 -0
- package/src/outbound-proxy/policy.ts +172 -0
- package/src/outbound-proxy/router.ts +64 -0
- package/src/outbound-proxy/server.ts +145 -0
- package/src/outbound-proxy/types.ts +150 -0
- package/src/permissions/checker.ts +481 -189
- package/src/permissions/defaults.ts +135 -108
- package/src/permissions/prompter.ts +53 -27
- package/src/permissions/secret-prompter.ts +21 -15
- package/src/permissions/shell-identity.ts +47 -16
- package/src/permissions/trust-store.ts +185 -73
- package/src/permissions/types.ts +22 -12
- package/src/permissions/workspace-policy.ts +47 -38
- package/src/playbooks/index.ts +10 -2
- package/src/playbooks/playbook-compiler.ts +30 -24
- package/src/playbooks/types.ts +11 -8
- package/src/providers/anthropic/client.ts +325 -168
- package/src/providers/failover.ts +57 -22
- package/src/providers/fireworks/client.ts +9 -5
- package/src/providers/gemini/client.ts +61 -39
- package/src/providers/model-intents.ts +40 -33
- package/src/providers/ollama/client.ts +7 -7
- package/src/providers/openai/client.ts +106 -68
- package/src/providers/openrouter/client.ts +9 -5
- package/src/providers/provider-send-message.ts +59 -27
- package/src/providers/ratelimit.ts +25 -8
- package/src/providers/registry.ts +86 -38
- package/src/providers/retry.ts +84 -36
- package/src/providers/stream-timeout.ts +5 -3
- package/src/providers/types.ts +7 -6
- package/src/runtime/AGENTS.md +42 -0
- package/src/runtime/access-request-helper.ts +118 -68
- package/src/runtime/actor-refresh-token-store.ts +21 -16
- package/src/runtime/actor-token-store.ts +25 -18
- package/src/runtime/actor-trust-resolver.ts +183 -80
- package/src/runtime/approval-conversation-turn.ts +39 -26
- package/src/runtime/approval-message-composer.ts +116 -84
- package/src/runtime/assistant-event-hub.ts +25 -6
- package/src/runtime/assistant-event.ts +4 -4
- package/src/runtime/assistant-scope.ts +1 -1
- package/src/runtime/auth/__tests__/guard-tests.test.ts +36 -14
- package/src/runtime/auth/context.ts +8 -7
- package/src/runtime/auth/credential-service.ts +60 -38
- package/src/runtime/auth/external-assistant-id.ts +16 -8
- package/src/runtime/auth/index.ts +23 -16
- package/src/runtime/auth/route-policy.ts +170 -104
- package/src/runtime/auth/scopes.ts +22 -29
- package/src/runtime/auth/subject.ts +19 -13
- package/src/runtime/auth/token-service.ts +3 -3
- package/src/runtime/auth/types.ts +23 -23
- package/src/runtime/channel-approval-parser.ts +37 -14
- package/src/runtime/channel-approval-types.ts +12 -4
- package/src/runtime/channel-approvals.ts +41 -23
- package/src/runtime/channel-guardian-service.ts +144 -103
- package/src/runtime/channel-invite-transport.ts +4 -2
- package/src/runtime/channel-invite-transports/telegram.ts +16 -10
- package/src/runtime/channel-invite-transports/voice.ts +7 -7
- package/src/runtime/channel-readiness-service.ts +139 -90
- package/src/runtime/channel-readiness-types.ts +4 -2
- package/src/runtime/channel-reply-delivery.ts +21 -11
- package/src/runtime/channel-retry-sweep.ts +111 -62
- package/src/runtime/confirmation-request-guardian-bridge.ts +73 -54
- package/src/runtime/gateway-client.ts +86 -53
- package/src/runtime/guardian-action-conversation-turn.ts +34 -18
- package/src/runtime/guardian-action-followup-executor.ts +115 -45
- package/src/runtime/guardian-action-grant-minter.ts +40 -24
- package/src/runtime/guardian-action-message-composer.ts +105 -84
- package/src/runtime/guardian-decision-types.ts +28 -13
- package/src/runtime/guardian-outbound-actions.ts +9 -0
- package/src/runtime/guardian-reply-router.ts +274 -145
- package/src/runtime/guardian-vellum-migration.ts +38 -24
- package/src/runtime/guardian-verification-templates.ts +8 -11
- package/src/runtime/http-router.ts +175 -0
- package/src/runtime/http-server.ts +931 -669
- package/src/runtime/http-types.ts +2 -2
- package/src/runtime/ingress-service.ts +182 -89
- package/src/runtime/invite-redemption-service.ts +211 -134
- package/src/runtime/invite-redemption-templates.ts +18 -11
- package/src/runtime/local-actor-identity.ts +73 -55
- package/src/runtime/middleware/auth.ts +25 -14
- package/src/runtime/middleware/error-handler.ts +15 -11
- package/src/runtime/middleware/rate-limiter.ts +23 -17
- package/src/runtime/middleware/request-logger.ts +4 -4
- package/src/runtime/middleware/twilio-validation.ts +29 -20
- package/src/runtime/migrations/migration-transport.ts +575 -0
- package/src/runtime/migrations/migration-wizard.ts +715 -0
- package/src/runtime/migrations/rebind-secrets-screen.ts +351 -0
- package/src/runtime/migrations/transfer-progress-screen.ts +321 -0
- package/src/runtime/migrations/validation-results-screen.ts +467 -0
- package/src/runtime/migrations/vbundle-builder.ts +295 -0
- package/src/runtime/migrations/vbundle-import-analyzer.ts +212 -0
- package/src/runtime/migrations/vbundle-importer.ts +339 -0
- package/src/runtime/migrations/vbundle-validator.ts +356 -0
- package/src/runtime/pending-interactions.ts +16 -7
- package/src/runtime/routes/access-request-decision.ts +73 -52
- package/src/runtime/routes/app-routes.ts +56 -38
- package/src/runtime/routes/approval-routes.ts +165 -74
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +930 -0
- package/src/runtime/routes/approval-strategies/guardian-legacy-fallback-strategy.ts +82 -0
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +151 -0
- package/src/runtime/routes/attachment-routes.ts +59 -48
- package/src/runtime/routes/brain-graph-routes.ts +85 -69
- package/src/runtime/routes/call-routes.ts +79 -38
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +10 -10
- package/src/runtime/routes/channel-delivery-routes.ts +19 -14
- package/src/runtime/routes/channel-guardian-routes.ts +3 -3
- package/src/runtime/routes/channel-inbound-routes.ts +2 -2
- package/src/runtime/routes/channel-readiness-routes.ts +12 -6
- package/src/runtime/routes/channel-route-shared.ts +33 -25
- package/src/runtime/routes/channel-routes.ts +4 -6
- package/src/runtime/routes/contact-routes.ts +205 -16
- package/src/runtime/routes/conversation-attention-routes.ts +57 -28
- package/src/runtime/routes/conversation-routes.ts +321 -174
- package/src/runtime/routes/debug-routes.ts +14 -10
- package/src/runtime/routes/events-routes.ts +90 -57
- package/src/runtime/routes/global-search-routes.ts +266 -0
- package/src/runtime/routes/guardian-action-routes.ts +147 -56
- package/src/runtime/routes/guardian-approval-interception.ts +255 -880
- package/src/runtime/routes/guardian-approval-prompt.ts +40 -24
- package/src/runtime/routes/guardian-approval-reply-helpers.ts +135 -0
- package/src/runtime/routes/guardian-bootstrap-routes.ts +55 -36
- package/src/runtime/routes/guardian-expiry-sweep.ts +63 -37
- package/src/runtime/routes/guardian-refresh-routes.ts +40 -19
- package/src/runtime/routes/identity-routes.ts +71 -42
- package/src/runtime/routes/inbound-conversation.ts +17 -11
- package/src/runtime/routes/inbound-message-handler.ts +278 -1460
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +658 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +492 -0
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +214 -0
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +116 -0
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +167 -0
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +185 -0
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +132 -0
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +340 -0
- package/src/runtime/routes/ingress-routes.ts +34 -23
- package/src/runtime/routes/integration-routes.ts +60 -21
- package/src/runtime/routes/migration-routes.ts +434 -0
- package/src/runtime/routes/pairing-routes.ts +157 -79
- package/src/runtime/routes/secret-routes.ts +6 -2
- package/src/runtime/routes/twilio-routes.ts +443 -249
- package/src/runtime/tool-grant-request-helper.ts +36 -27
- package/src/runtime/{guardian-context-resolver.ts → trust-context-resolver.ts} +29 -41
- package/src/schedule/integration-status.ts +44 -9
- package/src/schedule/recurrence-engine.ts +47 -24
- package/src/schedule/recurrence-types.ts +12 -7
- package/src/schedule/schedule-store.ts +166 -83
- package/src/schedule/scheduler.ts +26 -22
- package/src/security/encrypted-store.ts +68 -38
- package/src/security/keychain.ts +183 -120
- package/src/security/oauth-callback-registry.ts +3 -3
- package/src/security/oauth2.ts +226 -138
- package/src/security/redaction.ts +24 -24
- package/src/security/secret-allowlist.ts +46 -21
- package/src/security/secret-ingress.ts +15 -7
- package/src/security/secret-scanner.ts +193 -104
- package/src/security/secure-keys.ts +9 -3
- package/src/security/token-manager.ts +99 -40
- package/src/security/tool-approval-digest.ts +3 -3
- package/src/sequence/analytics.ts +52 -27
- package/src/sequence/engine.ts +135 -72
- package/src/sequence/guardrails.ts +32 -20
- package/src/sequence/importer.ts +75 -37
- package/src/sequence/reply-matcher.ts +36 -18
- package/src/sequence/store.ts +137 -75
- package/src/sequence/types.ts +30 -16
- package/src/services/published-app-updater.ts +26 -16
- package/src/services/vercel-deploy.ts +19 -15
- package/src/skills/active-skill-tools.ts +3 -3
- package/src/skills/clawhub.ts +178 -90
- package/src/skills/include-graph.ts +24 -17
- package/src/skills/managed-store.ts +89 -42
- package/src/skills/path-classifier.ts +10 -10
- package/src/skills/remote-skill-policy.ts +31 -22
- package/src/skills/slash-commands.ts +36 -30
- package/src/skills/tool-manifest.ts +60 -31
- package/src/skills/version-hash.ts +25 -15
- package/src/slack/slack-webhook.ts +19 -15
- package/src/subagent/index.ts +4 -8
- package/src/subagent/manager.ts +119 -69
- package/src/subagent/types.ts +9 -12
- package/src/swarm/backend-claude-code.ts +124 -45
- package/src/swarm/checkpoint.ts +36 -16
- package/src/swarm/graph-utils.ts +1 -3
- package/src/swarm/index.ts +38 -19
- package/src/swarm/limits.ts +13 -4
- package/src/swarm/orchestrator.ts +108 -57
- package/src/swarm/plan-validator.ts +23 -17
- package/src/swarm/router-planner.ts +51 -22
- package/src/swarm/router-prompts.ts +4 -1
- package/src/swarm/synthesizer.ts +26 -18
- package/src/swarm/types.ts +14 -4
- package/src/swarm/worker-backend.ts +36 -26
- package/src/swarm/worker-prompts.ts +13 -9
- package/src/swarm/worker-runner.ts +40 -34
- package/src/tasks/candidate-store.ts +14 -6
- package/src/tasks/ephemeral-permissions.ts +9 -5
- package/src/tasks/task-compiler.ts +41 -38
- package/src/tasks/task-runner.ts +54 -26
- package/src/tasks/task-scheduler.ts +1 -1
- package/src/tasks/task-store.ts +20 -7
- package/src/tasks/tool-sanitizer.ts +3 -3
- package/src/tools/apps/definitions.ts +23 -15
- package/src/tools/apps/executors.ts +118 -37
- package/src/tools/apps/open-proxy.ts +5 -5
- package/src/tools/apps/registry.ts +2 -2
- package/src/tools/assets/materialize.ts +59 -41
- package/src/tools/assets/search.ts +86 -48
- package/src/tools/browser/api-map.ts +52 -36
- package/src/tools/browser/auth-cache.ts +21 -18
- package/src/tools/browser/auth-detector.ts +43 -28
- package/src/tools/browser/auto-navigate.ts +149 -68
- package/src/tools/browser/browser-execution.ts +9 -3
- package/src/tools/browser/headless-browser.ts +287 -150
- package/src/tools/browser/jit-auth.ts +37 -21
- package/src/tools/browser/network-recorder.ts +138 -56
- package/src/tools/browser/recording-store.ts +22 -15
- package/src/tools/browser/runtime-check.ts +8 -5
- package/src/tools/browser/x-auto-navigate.ts +88 -47
- package/src/tools/calls/call-end.ts +9 -6
- package/src/tools/calls/call-start.ts +30 -20
- package/src/tools/calls/call-status.ts +8 -5
- package/src/tools/claude-code/claude-code.ts +301 -165
- package/src/tools/computer-use/definitions.ts +159 -130
- package/src/tools/computer-use/registry.ts +2 -2
- package/src/tools/computer-use/request-computer-control.ts +21 -13
- package/src/tools/computer-use/skill-proxy-bridge.ts +1 -1
- package/src/tools/credentials/account-registry.ts +52 -35
- package/src/tools/credentials/broker-types.ts +1 -1
- package/src/tools/credentials/broker.ts +97 -55
- package/src/tools/credentials/domain-policy.ts +5 -2
- package/src/tools/credentials/host-pattern-match.ts +15 -8
- package/src/tools/credentials/metadata-store.ts +93 -43
- package/src/tools/credentials/policy-types.ts +5 -2
- package/src/tools/credentials/policy-validate.ts +21 -14
- package/src/tools/credentials/post-connect-hooks.ts +18 -7
- package/src/tools/credentials/resolve.ts +11 -10
- package/src/tools/credentials/selection.ts +30 -25
- package/src/tools/credentials/tool-policy.ts +5 -2
- package/src/tools/credentials/vault.ts +452 -183
- package/src/tools/document/document-tool.ts +23 -17
- package/src/tools/document/editor-template.ts +12 -7
- package/src/tools/execution-target.ts +13 -10
- package/src/tools/execution-timeout.ts +6 -5
- package/src/tools/executor.ts +141 -74
- package/src/tools/filesystem/edit.ts +82 -45
- package/src/tools/filesystem/fuzzy-match.ts +70 -32
- package/src/tools/filesystem/read.ts +46 -28
- package/src/tools/filesystem/view-image.ts +86 -42
- package/src/tools/filesystem/write.ts +53 -32
- package/src/tools/followups/followup_create.ts +43 -17
- package/src/tools/followups/followup_list.ts +28 -13
- package/src/tools/followups/followup_resolve.ts +9 -6
- package/src/tools/guardian-control-plane-policy.ts +15 -14
- package/src/tools/host-filesystem/edit.ts +77 -42
- package/src/tools/host-filesystem/read.ts +52 -33
- package/src/tools/host-filesystem/write.ts +50 -29
- package/src/tools/host-terminal/host-shell.ts +97 -61
- package/src/tools/mcp/mcp-tool-factory.ts +21 -14
- package/src/tools/memory/definitions.ts +60 -28
- package/src/tools/memory/handlers.ts +149 -77
- package/src/tools/memory/register.ts +39 -16
- package/src/tools/network/__tests__/web-search.test.ts +236 -177
- package/src/tools/network/domain-normalize.ts +13 -9
- package/src/tools/network/script-proxy/__tests__/logging.test.ts +193 -123
- package/src/tools/network/script-proxy/__tests__/policy.test.ts +225 -127
- package/src/tools/network/script-proxy/index.ts +1 -17
- package/src/tools/network/script-proxy/session-manager.ts +151 -84
- package/src/tools/network/url-safety.ts +56 -34
- package/src/tools/network/web-fetch.ts +273 -155
- package/src/tools/network/web-search.ts +166 -81
- package/src/tools/permission-checker.ts +6 -25
- package/src/tools/policy-context.ts +8 -5
- package/src/tools/registry.ts +73 -46
- package/src/tools/reminder/reminder-store.ts +65 -44
- package/src/tools/reminder/reminder.ts +76 -35
- package/src/tools/schedule/create.ts +44 -21
- package/src/tools/schedule/delete.ts +8 -5
- package/src/tools/schedule/list.ts +39 -19
- package/src/tools/schedule/update.ts +49 -26
- package/src/tools/secret-detection-handler.ts +130 -49
- package/src/tools/sensitive-output-placeholders.ts +15 -8
- package/src/tools/shared/filesystem/edit-engine.ts +45 -14
- package/src/tools/shared/filesystem/errors.ts +18 -18
- package/src/tools/shared/filesystem/file-ops-service.ts +59 -32
- package/src/tools/shared/filesystem/format-diff.ts +21 -11
- package/src/tools/shared/filesystem/path-policy.ts +17 -13
- package/src/tools/shared/filesystem/size-guard.ts +8 -4
- package/src/tools/shared/filesystem/types.ts +2 -2
- package/src/tools/shared/shell-output.ts +4 -3
- package/src/tools/side-effects.ts +36 -28
- package/src/tools/skills/delete-managed.ts +30 -17
- package/src/tools/skills/load.ts +88 -46
- package/src/tools/skills/sandbox-runner.ts +62 -46
- package/src/tools/skills/scaffold-managed.ts +98 -48
- package/src/tools/skills/script-contract.ts +5 -2
- package/src/tools/skills/skill-script-runner.ts +29 -13
- package/src/tools/skills/skill-tool-factory.ts +20 -10
- package/src/tools/subagent/abort.ts +10 -4
- package/src/tools/subagent/message.ts +14 -8
- package/src/tools/subagent/read.ts +20 -11
- package/src/tools/subagent/spawn.ts +14 -6
- package/src/tools/subagent/status.ts +7 -4
- package/src/tools/swarm/delegate.ts +75 -49
- package/src/tools/system/avatar-generator.ts +46 -33
- package/src/tools/system/navigate-settings.ts +29 -19
- package/src/tools/system/open-system-settings.ts +30 -20
- package/src/tools/system/request-permission.ts +59 -44
- package/src/tools/system/version.ts +27 -16
- package/src/tools/system/voice-config.ts +116 -53
- package/src/tools/tasks/index.ts +8 -8
- package/src/tools/tasks/task-delete.ts +61 -22
- package/src/tools/tasks/task-list.ts +23 -11
- package/src/tools/tasks/task-run.ts +41 -16
- package/src/tools/tasks/task-save.ts +27 -10
- package/src/tools/tasks/work-item-enqueue.ts +114 -48
- package/src/tools/tasks/work-item-list.ts +20 -10
- package/src/tools/tasks/work-item-remove.ts +49 -15
- package/src/tools/tasks/work-item-run.ts +34 -13
- package/src/tools/tasks/work-item-update.ts +84 -31
- package/src/tools/terminal/backends/native.ts +64 -35
- package/src/tools/terminal/backends/types.ts +6 -2
- package/src/tools/terminal/parser.ts +200 -125
- package/src/tools/terminal/safe-env.ts +27 -21
- package/src/tools/terminal/sandbox-diagnostics.ts +31 -13
- package/src/tools/terminal/sandbox.ts +10 -6
- package/src/tools/terminal/shell.ts +124 -68
- package/src/tools/tool-approval-handler.ts +193 -138
- package/src/tools/types.ts +43 -23
- package/src/tools/ui-surface/definitions.ts +124 -89
- package/src/tools/ui-surface/registry.ts +2 -2
- package/src/tools/watch/screen-watch.ts +50 -32
- package/src/tools/watch/watch-state.ts +41 -15
- package/src/tools/watcher/create.ts +37 -15
- package/src/tools/watcher/delete.ts +9 -6
- package/src/tools/watcher/digest.ts +10 -6
- package/src/tools/watcher/list.ts +37 -14
- package/src/tools/watcher/update.ts +33 -18
- package/src/tools/weather/service.ts +331 -174
- package/src/twitter/client.ts +261 -138
- package/src/twitter/oauth-client.ts +17 -13
- package/src/twitter/router.ts +51 -23
- package/src/twitter/session.ts +27 -18
- package/src/types/qrcode.d.ts +6 -3
- package/src/usage/actors.ts +16 -16
- package/src/usage/types.ts +3 -3
- package/src/util/bundled-asset.ts +10 -6
- package/src/util/canonicalize-identity.ts +11 -4
- package/src/util/clipboard.ts +7 -7
- package/src/util/content-id.ts +3 -3
- package/src/util/debounce.ts +3 -2
- package/src/util/diff.ts +55 -33
- package/src/util/errors.ts +26 -26
- package/src/util/fs.ts +8 -2
- package/src/util/log-redact.ts +12 -12
- package/src/util/logger.ts +112 -51
- package/src/util/network-info.ts +13 -5
- package/src/util/object.ts +4 -2
- package/src/util/phone.ts +4 -4
- package/src/util/platform.ts +80 -58
- package/src/util/pricing.ts +49 -31
- package/src/util/retry.ts +18 -7
- package/src/util/row-mapper.ts +7 -4
- package/src/util/silently.ts +7 -4
- package/src/util/spawn.ts +48 -0
- package/src/util/spinner.ts +9 -7
- package/src/util/time.ts +16 -3
- package/src/util/truncate.ts +1 -1
- package/src/util/voice-code.ts +6 -4
- package/src/util/xml.ts +5 -1
- package/src/version.ts +12 -8
- package/src/watcher/engine.ts +71 -44
- package/src/watcher/provider-registry.ts +1 -1
- package/src/watcher/providers/github.ts +40 -23
- package/src/watcher/providers/gmail.ts +59 -38
- package/src/watcher/providers/google-calendar.ts +62 -48
- package/src/watcher/providers/linear.ts +219 -150
- package/src/watcher/providers/slack.ts +93 -27
- package/src/watcher/watcher-store.ts +75 -55
- package/src/work-items/work-item-runner.ts +62 -29
- package/src/work-items/work-item-store.ts +137 -47
- package/src/workspace/commit-message-enrichment-service.ts +65 -25
- package/src/workspace/commit-message-provider.ts +14 -12
- package/src/workspace/git-service.ts +355 -239
- package/src/workspace/heartbeat-service.ts +74 -37
- package/src/workspace/provider-commit-message-generator.ts +95 -70
- package/src/workspace/top-level-renderer.ts +10 -8
- package/src/workspace/top-level-scanner.ts +9 -3
- package/src/workspace/turn-commit.ts +63 -36
- package/src/__tests__/ingress-member-store.test.ts +0 -294
- package/src/__tests__/script-proxy-router.test.ts +0 -215
- package/src/config/bundled-skills/trusted-contacts/SKILL.md +0 -372
- package/src/memory/guardian-bindings.ts +0 -158
- package/src/memory/ingress-member-store.ts +0 -352
- package/src/tools/network/script-proxy/__tests__/router.test.ts +0 -77
- package/src/tools/network/script-proxy/certs.ts +0 -7
- package/src/tools/network/script-proxy/connect-tunnel.ts +0 -1
- package/src/tools/network/script-proxy/http-forwarder.ts +0 -2
- package/src/tools/network/script-proxy/logging.ts +0 -12
- package/src/tools/network/script-proxy/mitm-handler.ts +0 -2
- package/src/tools/network/script-proxy/policy.ts +0 -4
- package/src/tools/network/script-proxy/router.ts +0 -2
- package/src/tools/network/script-proxy/server.ts +0 -5
- package/src/tools/network/script-proxy/types.ts +0 -19
|
@@ -1,52 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Approval interception: checks for pending approvals and handles inbound
|
|
3
3
|
* messages as decisions, reminders, or conversational follow-ups.
|
|
4
|
+
*
|
|
5
|
+
* This module is the top-level dispatcher. It delegates to strategy modules:
|
|
6
|
+
* - guardian-callback-strategy.ts — guardian callback button and text decisions
|
|
7
|
+
* - guardian-text-engine-strategy.ts — conversational engine for plain-text messages
|
|
8
|
+
* - guardian-legacy-fallback-strategy.ts — deterministic parser fallback
|
|
4
9
|
*/
|
|
5
|
-
import { applyGuardianDecision } from
|
|
6
|
-
import type { ChannelId } from
|
|
10
|
+
import { applyGuardianDecision } from "../../approvals/guardian-decision-primitive.js";
|
|
11
|
+
import type { ChannelId } from "../../channels/types.js";
|
|
12
|
+
import type { TrustContext } from "../../daemon/session-runtime-assembly.js";
|
|
7
13
|
import {
|
|
8
|
-
getAllPendingApprovalsByGuardianChat,
|
|
9
|
-
getPendingApprovalByRequestAndGuardianChat,
|
|
10
14
|
getPendingApprovalForRequest,
|
|
11
15
|
getUnresolvedApprovalForRequest,
|
|
12
|
-
type GuardianApprovalRequest,
|
|
13
16
|
updateApprovalDecision,
|
|
14
|
-
} from
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import { parseApprovalDecision } from '../channel-approval-parser.js';
|
|
20
|
-
import type {
|
|
21
|
-
ApprovalAction,
|
|
22
|
-
ApprovalDecisionResult,
|
|
23
|
-
} from '../channel-approval-types.js';
|
|
17
|
+
} from "../../memory/channel-guardian-store.js";
|
|
18
|
+
import { getLogger } from "../../util/logger.js";
|
|
19
|
+
import { runApprovalConversationTurn } from "../approval-conversation-turn.js";
|
|
20
|
+
import { composeApprovalMessageGenerative } from "../approval-message-composer.js";
|
|
21
|
+
import type { ApprovalDecisionResult } from "../channel-approval-types.js";
|
|
24
22
|
import {
|
|
25
23
|
getApprovalInfoByConversation,
|
|
26
24
|
getChannelApprovalPrompt,
|
|
27
25
|
handleChannelDecision,
|
|
28
|
-
} from
|
|
29
|
-
import { deliverChannelReply } from
|
|
26
|
+
} from "../channel-approvals.js";
|
|
27
|
+
import { deliverChannelReply } from "../gateway-client.js";
|
|
30
28
|
import type {
|
|
31
29
|
ApprovalConversationContext,
|
|
32
30
|
ApprovalConversationGenerator,
|
|
33
31
|
ApprovalCopyGenerator,
|
|
34
|
-
} from
|
|
35
|
-
import {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
handleAccessRequestDecision,
|
|
39
|
-
notifyRequesterOfApproval,
|
|
40
|
-
notifyRequesterOfDeliveryFailure,
|
|
41
|
-
notifyRequesterOfDenial,
|
|
42
|
-
} from './access-request-decision.js';
|
|
32
|
+
} from "../http-types.js";
|
|
33
|
+
import { handleGuardianCallbackDecision } from "./approval-strategies/guardian-callback-strategy.js";
|
|
34
|
+
import { handleGuardianLegacyFallback } from "./approval-strategies/guardian-legacy-fallback-strategy.js";
|
|
35
|
+
import { handleGuardianTextEngineDecision } from "./approval-strategies/guardian-text-engine-strategy.js";
|
|
43
36
|
import {
|
|
44
37
|
buildGuardianDenyContext,
|
|
45
|
-
type GuardianContext,
|
|
46
38
|
parseCallbackData,
|
|
47
|
-
} from
|
|
39
|
+
} from "./channel-route-shared.js";
|
|
40
|
+
import { deliverStaleApprovalReply } from "./guardian-approval-reply-helpers.js";
|
|
48
41
|
|
|
49
|
-
const log = getLogger(
|
|
42
|
+
const log = getLogger("runtime-http");
|
|
50
43
|
|
|
51
44
|
export interface ApprovalInterceptionParams {
|
|
52
45
|
conversationId: string;
|
|
@@ -57,7 +50,7 @@ export interface ApprovalInterceptionParams {
|
|
|
57
50
|
actorExternalId?: string;
|
|
58
51
|
replyCallbackUrl: string;
|
|
59
52
|
bearerToken?: string;
|
|
60
|
-
|
|
53
|
+
trustCtx: TrustContext;
|
|
61
54
|
assistantId: string;
|
|
62
55
|
approvalCopyGenerator?: ApprovalCopyGenerator;
|
|
63
56
|
approvalConversationGenerator?: ApprovalConversationGenerator;
|
|
@@ -65,7 +58,11 @@ export interface ApprovalInterceptionParams {
|
|
|
65
58
|
|
|
66
59
|
export interface ApprovalInterceptionResult {
|
|
67
60
|
handled: boolean;
|
|
68
|
-
type?:
|
|
61
|
+
type?:
|
|
62
|
+
| "decision_applied"
|
|
63
|
+
| "assistant_turn"
|
|
64
|
+
| "guardian_decision_applied"
|
|
65
|
+
| "stale_ignored";
|
|
69
66
|
}
|
|
70
67
|
|
|
71
68
|
/**
|
|
@@ -90,7 +87,7 @@ export async function handleApprovalInterception(
|
|
|
90
87
|
actorExternalId,
|
|
91
88
|
replyCallbackUrl,
|
|
92
89
|
bearerToken,
|
|
93
|
-
|
|
90
|
+
trustCtx,
|
|
94
91
|
assistantId,
|
|
95
92
|
approvalCopyGenerator,
|
|
96
93
|
approvalConversationGenerator,
|
|
@@ -99,449 +96,22 @@ export async function handleApprovalInterception(
|
|
|
99
96
|
// ── Guardian approval decision path ──
|
|
100
97
|
// When the sender is the guardian and there's a pending guardian approval
|
|
101
98
|
// request targeting this chat, the message might be a decision on behalf
|
|
102
|
-
// of a non-guardian requester.
|
|
103
|
-
if (
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
: null;
|
|
119
|
-
|
|
120
|
-
// When the scoped lookup didn't resolve an approval (either because
|
|
121
|
-
// there was no callback or the requestId pointed to a stale/expired request),
|
|
122
|
-
// fall back to checking all pending approvals for this guardian chat.
|
|
123
|
-
if (!guardianApproval && callbackDecision) {
|
|
124
|
-
const allPending = getAllPendingApprovalsByGuardianChat(sourceChannel, conversationExternalId, assistantId);
|
|
125
|
-
if (allPending.length === 1) {
|
|
126
|
-
guardianApproval = allPending[0];
|
|
127
|
-
} else if (allPending.length > 1) {
|
|
128
|
-
// The callback targeted a stale/expired request but the guardian has other
|
|
129
|
-
// pending approvals. Inform them the clicked approval is no longer valid.
|
|
130
|
-
try {
|
|
131
|
-
const staleText = await composeApprovalMessageGenerative({
|
|
132
|
-
scenario: 'guardian_disambiguation',
|
|
133
|
-
pendingCount: allPending.length,
|
|
134
|
-
channel: sourceChannel,
|
|
135
|
-
}, {}, approvalCopyGenerator);
|
|
136
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
137
|
-
chatId: conversationExternalId,
|
|
138
|
-
text: staleText,
|
|
139
|
-
assistantId,
|
|
140
|
-
}, bearerToken);
|
|
141
|
-
} catch (err) {
|
|
142
|
-
log.error({ err, conversationExternalId }, 'Failed to deliver stale callback disambiguation notice');
|
|
143
|
-
}
|
|
144
|
-
return { handled: true, type: 'stale_ignored' };
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// For plain-text messages (no callback), check if there are any pending
|
|
149
|
-
// approvals for this guardian chat to route through the conversation engine.
|
|
150
|
-
if (!guardianApproval && !callbackDecision) {
|
|
151
|
-
const allPending = getAllPendingApprovalsByGuardianChat(sourceChannel, conversationExternalId, assistantId);
|
|
152
|
-
if (allPending.length === 1) {
|
|
153
|
-
guardianApproval = allPending[0];
|
|
154
|
-
} else if (allPending.length > 1) {
|
|
155
|
-
// Multiple pending — pick the first approval matching this sender as
|
|
156
|
-
// primary context. The conversation engine sees all matching approvals
|
|
157
|
-
// via pendingApprovals and can disambiguate.
|
|
158
|
-
guardianApproval = allPending.find(a => a.guardianExternalUserId === actorExternalId) ?? allPending[0];
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (guardianApproval) {
|
|
163
|
-
// Validate that the sender is the specific guardian who was assigned
|
|
164
|
-
// this approval request. This is a defense-in-depth check — the
|
|
165
|
-
// trustClass check above already verifies the sender is a guardian,
|
|
166
|
-
// but this catches edge cases like binding rotation between request
|
|
167
|
-
// creation and decision.
|
|
168
|
-
if (actorExternalId !== guardianApproval.guardianExternalUserId) {
|
|
169
|
-
log.warn(
|
|
170
|
-
{ conversationExternalId, actorExternalId, expectedGuardian: guardianApproval.guardianExternalUserId },
|
|
171
|
-
'Non-guardian sender attempted to act on guardian approval request',
|
|
172
|
-
);
|
|
173
|
-
try {
|
|
174
|
-
const mismatchText = await composeApprovalMessageGenerative({
|
|
175
|
-
scenario: 'guardian_identity_mismatch',
|
|
176
|
-
channel: sourceChannel,
|
|
177
|
-
}, {}, approvalCopyGenerator);
|
|
178
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
179
|
-
chatId: conversationExternalId,
|
|
180
|
-
text: mismatchText,
|
|
181
|
-
assistantId,
|
|
182
|
-
}, bearerToken);
|
|
183
|
-
} catch (err) {
|
|
184
|
-
log.error({ err, conversationExternalId }, 'Failed to deliver guardian identity rejection notice');
|
|
185
|
-
}
|
|
186
|
-
return { handled: true, type: 'guardian_decision_applied' };
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (callbackDecision) {
|
|
190
|
-
// Access request approvals don't have a pending interaction in the
|
|
191
|
-
// session tracker, so they need a separate decision path that creates
|
|
192
|
-
// a verification session instead of resuming an agent loop.
|
|
193
|
-
if (guardianApproval.toolName === 'ingress_access_request') {
|
|
194
|
-
const accessResult = await handleAccessRequestApproval(
|
|
195
|
-
guardianApproval,
|
|
196
|
-
callbackDecision.action === 'reject' ? 'deny' : 'approve',
|
|
197
|
-
actorExternalId,
|
|
198
|
-
replyCallbackUrl,
|
|
199
|
-
assistantId,
|
|
200
|
-
bearerToken,
|
|
201
|
-
);
|
|
202
|
-
return accessResult;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Apply the decision through the unified guardian decision primitive.
|
|
206
|
-
// The primitive handles approve_always downgrade, approval info capture,
|
|
207
|
-
// record update, and scoped grant minting.
|
|
208
|
-
const result = applyGuardianDecision({
|
|
209
|
-
approval: guardianApproval,
|
|
210
|
-
decision: callbackDecision,
|
|
211
|
-
actorExternalUserId: actorExternalId,
|
|
212
|
-
actorChannel: sourceChannel,
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
if (result.applied) {
|
|
216
|
-
// Notify the requester's chat about the outcome with the tool name
|
|
217
|
-
const effectiveAction = callbackDecision.action === 'approve_always' ? 'approve_once' : callbackDecision.action;
|
|
218
|
-
const outcomeText = await composeApprovalMessageGenerative({
|
|
219
|
-
scenario: 'guardian_decision_outcome',
|
|
220
|
-
decision: effectiveAction === 'reject' ? 'denied' : 'approved',
|
|
221
|
-
toolName: guardianApproval.toolName,
|
|
222
|
-
channel: sourceChannel,
|
|
223
|
-
}, {}, approvalCopyGenerator);
|
|
224
|
-
try {
|
|
225
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
226
|
-
chatId: guardianApproval.requesterChatId,
|
|
227
|
-
text: outcomeText,
|
|
228
|
-
assistantId,
|
|
229
|
-
}, bearerToken);
|
|
230
|
-
} catch (err) {
|
|
231
|
-
log.error({ err, conversationId: guardianApproval.conversationId }, 'Failed to notify requester of guardian decision');
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Post-decision delivery is handled by the onEvent callback
|
|
235
|
-
// in the session that registered the pending interaction.
|
|
236
|
-
return { handled: true, type: 'guardian_decision_applied' };
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Race condition: callback arrived after request was already resolved.
|
|
240
|
-
return { handled: true, type: 'stale_ignored' };
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// ── Conversational engine for guardian plain-text messages ──
|
|
244
|
-
// Gather all pending guardian approvals for this chat so the engine
|
|
245
|
-
// can handle disambiguation when multiple are pending.
|
|
246
|
-
const allGuardianPending = getAllPendingApprovalsByGuardianChat(sourceChannel, conversationExternalId, assistantId);
|
|
247
|
-
// Only present approvals that belong to this sender so the engine
|
|
248
|
-
// does not offer disambiguation for requests assigned to a rotated
|
|
249
|
-
// guardian the sender cannot act on.
|
|
250
|
-
const senderPending = allGuardianPending.filter(a => a.guardianExternalUserId === actorExternalId);
|
|
251
|
-
const effectivePending = senderPending.length > 0 ? senderPending : allGuardianPending;
|
|
252
|
-
if (effectivePending.length > 0 && approvalConversationGenerator && content) {
|
|
253
|
-
const guardianAllowedActions = ['approve_once', 'reject'];
|
|
254
|
-
const engineContext: ApprovalConversationContext = {
|
|
255
|
-
toolName: guardianApproval.toolName,
|
|
256
|
-
allowedActions: guardianAllowedActions,
|
|
257
|
-
role: 'guardian',
|
|
258
|
-
pendingApprovals: effectivePending.map((a) => ({ requestId: a.requestId ?? a.runId, toolName: a.toolName })),
|
|
259
|
-
userMessage: content,
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
const engineResult = await runApprovalConversationTurn(engineContext, approvalConversationGenerator);
|
|
263
|
-
|
|
264
|
-
if (engineResult.disposition === 'keep_pending') {
|
|
265
|
-
// Non-decision follow-up (clarification, disambiguation, etc.)
|
|
266
|
-
try {
|
|
267
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
268
|
-
chatId: conversationExternalId,
|
|
269
|
-
text: engineResult.replyText,
|
|
270
|
-
assistantId,
|
|
271
|
-
}, bearerToken);
|
|
272
|
-
} catch (err) {
|
|
273
|
-
log.error({ err, conversationId: guardianApproval.conversationId }, 'Failed to deliver guardian conversation reply');
|
|
274
|
-
}
|
|
275
|
-
return { handled: true, type: 'assistant_turn' };
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// Decision-bearing disposition from the engine
|
|
279
|
-
let decisionAction = engineResult.disposition as ApprovalAction;
|
|
280
|
-
|
|
281
|
-
// Belt-and-suspenders: guardians cannot use broad allow modes even if
|
|
282
|
-
// the engine returns them (the engine's allowedActions validation should
|
|
283
|
-
// already prevent this, but enforce it here too).
|
|
284
|
-
if (decisionAction === 'approve_always' || decisionAction === 'approve_10m' || decisionAction === 'approve_thread') {
|
|
285
|
-
decisionAction = 'approve_once';
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Resolve the target approval: use targetRequestId from the engine if
|
|
289
|
-
// provided, otherwise use the single guardian approval.
|
|
290
|
-
const targetApproval = engineResult.targetRequestId
|
|
291
|
-
? allGuardianPending.find((a) => (a.requestId ?? a.runId) === engineResult.targetRequestId) ?? guardianApproval
|
|
292
|
-
: guardianApproval;
|
|
293
|
-
|
|
294
|
-
// Re-validate guardian identity against the resolved target. The
|
|
295
|
-
// engine may select a different pending approval (via targetRequestId)
|
|
296
|
-
// that was assigned to a different guardian. Without this check a
|
|
297
|
-
// currently bound guardian could act on a request assigned to a
|
|
298
|
-
// previous guardian after a binding rotation.
|
|
299
|
-
if (actorExternalId !== targetApproval.guardianExternalUserId) {
|
|
300
|
-
log.warn(
|
|
301
|
-
{ conversationExternalId, actorExternalId, expectedGuardian: targetApproval.guardianExternalUserId, targetRequestId: engineResult.targetRequestId },
|
|
302
|
-
'Guardian identity mismatch on engine-selected target approval',
|
|
303
|
-
);
|
|
304
|
-
try {
|
|
305
|
-
const mismatchText = await composeApprovalMessageGenerative({
|
|
306
|
-
scenario: 'guardian_identity_mismatch',
|
|
307
|
-
channel: sourceChannel,
|
|
308
|
-
}, {}, approvalCopyGenerator);
|
|
309
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
310
|
-
chatId: conversationExternalId,
|
|
311
|
-
text: mismatchText,
|
|
312
|
-
assistantId,
|
|
313
|
-
}, bearerToken);
|
|
314
|
-
} catch (err) {
|
|
315
|
-
log.error({ err, conversationExternalId }, 'Failed to deliver guardian identity mismatch notice for engine target');
|
|
316
|
-
}
|
|
317
|
-
return { handled: true, type: 'guardian_decision_applied' };
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Access request approvals need a separate decision path.
|
|
321
|
-
if (targetApproval.toolName === 'ingress_access_request') {
|
|
322
|
-
const accessResult = await handleAccessRequestApproval(
|
|
323
|
-
targetApproval,
|
|
324
|
-
decisionAction === 'reject' ? 'deny' : 'approve',
|
|
325
|
-
actorExternalId,
|
|
326
|
-
replyCallbackUrl,
|
|
327
|
-
assistantId,
|
|
328
|
-
bearerToken,
|
|
329
|
-
);
|
|
330
|
-
return accessResult;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
const engineDecision: ApprovalDecisionResult = {
|
|
334
|
-
action: decisionAction,
|
|
335
|
-
source: 'plain_text',
|
|
336
|
-
...(engineResult.targetRequestId ? { requestId: engineResult.targetRequestId } : {}),
|
|
337
|
-
};
|
|
338
|
-
|
|
339
|
-
// Apply the decision through the unified guardian decision primitive.
|
|
340
|
-
const result = applyGuardianDecision({
|
|
341
|
-
approval: targetApproval,
|
|
342
|
-
decision: engineDecision,
|
|
343
|
-
actorExternalUserId: actorExternalId,
|
|
344
|
-
actorChannel: sourceChannel,
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
if (result.applied) {
|
|
348
|
-
// Notify the requester's chat about the outcome
|
|
349
|
-
const outcomeText = await composeApprovalMessageGenerative({
|
|
350
|
-
scenario: 'guardian_decision_outcome',
|
|
351
|
-
decision: decisionAction === 'reject' ? 'denied' : 'approved',
|
|
352
|
-
toolName: targetApproval.toolName,
|
|
353
|
-
channel: sourceChannel,
|
|
354
|
-
}, {}, approvalCopyGenerator);
|
|
355
|
-
try {
|
|
356
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
357
|
-
chatId: targetApproval.requesterChatId,
|
|
358
|
-
text: outcomeText,
|
|
359
|
-
assistantId,
|
|
360
|
-
}, bearerToken);
|
|
361
|
-
} catch (err) {
|
|
362
|
-
log.error({ err, conversationId: targetApproval.conversationId }, 'Failed to notify requester of guardian decision');
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// Deliver the engine's reply to the guardian
|
|
366
|
-
try {
|
|
367
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
368
|
-
chatId: conversationExternalId,
|
|
369
|
-
text: engineResult.replyText,
|
|
370
|
-
assistantId,
|
|
371
|
-
}, bearerToken);
|
|
372
|
-
} catch (err) {
|
|
373
|
-
log.error({ err, conversationId: targetApproval.conversationId }, 'Failed to deliver guardian decision reply');
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
return { handled: true, type: 'guardian_decision_applied' };
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// Race condition: request was already resolved. Deliver a stale notice
|
|
380
|
-
// instead of the engine's optimistic reply.
|
|
381
|
-
try {
|
|
382
|
-
const staleText = await composeApprovalMessageGenerative({
|
|
383
|
-
scenario: 'approval_already_resolved',
|
|
384
|
-
channel: sourceChannel,
|
|
385
|
-
}, {}, approvalCopyGenerator);
|
|
386
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
387
|
-
chatId: conversationExternalId,
|
|
388
|
-
text: staleText,
|
|
389
|
-
assistantId,
|
|
390
|
-
}, bearerToken);
|
|
391
|
-
} catch (err) {
|
|
392
|
-
log.error({ err, conversationId: targetApproval.conversationId }, 'Failed to deliver stale guardian approval notice');
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
return { handled: true, type: 'stale_ignored' };
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// ── Legacy fallback when no conversational engine is available ──
|
|
399
|
-
// Use the deterministic parser to handle guardian plain-text so that
|
|
400
|
-
// simple yes/no replies still work when the engine is not injected.
|
|
401
|
-
if (content && !approvalConversationGenerator) {
|
|
402
|
-
const legacyGuardianDecision = parseApprovalDecision(content);
|
|
403
|
-
if (legacyGuardianDecision) {
|
|
404
|
-
// Guardians cannot approve_always — downgrade to approve_once.
|
|
405
|
-
if (legacyGuardianDecision.action === 'approve_always') {
|
|
406
|
-
legacyGuardianDecision.action = 'approve_once';
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
// Resolve the target approval: when a [ref:<requestId>] tag is
|
|
410
|
-
// present, look up the specific pending approval by that requestId
|
|
411
|
-
// so the decision applies to the correct conversation even when
|
|
412
|
-
// multiple guardian approvals are pending.
|
|
413
|
-
let targetLegacyApproval = guardianApproval;
|
|
414
|
-
if (legacyGuardianDecision.requestId) {
|
|
415
|
-
const resolvedByRequest = getPendingApprovalByRequestAndGuardianChat(
|
|
416
|
-
legacyGuardianDecision.requestId,
|
|
417
|
-
sourceChannel,
|
|
418
|
-
conversationExternalId,
|
|
419
|
-
assistantId,
|
|
420
|
-
);
|
|
421
|
-
if (!resolvedByRequest) {
|
|
422
|
-
// The referenced request doesn't match any pending guardian
|
|
423
|
-
// approval — it may have expired or already been resolved.
|
|
424
|
-
try {
|
|
425
|
-
const staleText = await composeApprovalMessageGenerative({
|
|
426
|
-
scenario: 'guardian_disambiguation',
|
|
427
|
-
channel: sourceChannel,
|
|
428
|
-
}, {}, approvalCopyGenerator);
|
|
429
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
430
|
-
chatId: conversationExternalId,
|
|
431
|
-
text: staleText,
|
|
432
|
-
assistantId,
|
|
433
|
-
}, bearerToken);
|
|
434
|
-
} catch (err) {
|
|
435
|
-
log.error({ err, conversationExternalId }, 'Failed to deliver stale approval notice (legacy path)');
|
|
436
|
-
}
|
|
437
|
-
return { handled: true, type: 'stale_ignored' };
|
|
438
|
-
}
|
|
439
|
-
targetLegacyApproval = resolvedByRequest;
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// Re-validate guardian identity against the resolved target.
|
|
443
|
-
// The default guardianApproval was already checked, but a
|
|
444
|
-
// requestId-resolved approval may belong to a different guardian.
|
|
445
|
-
if (actorExternalId !== targetLegacyApproval.guardianExternalUserId) {
|
|
446
|
-
log.warn(
|
|
447
|
-
{ conversationExternalId, actorExternalId, expectedGuardian: targetLegacyApproval.guardianExternalUserId, requestId: legacyGuardianDecision.requestId },
|
|
448
|
-
'Guardian identity mismatch on legacy ref-resolved target approval',
|
|
449
|
-
);
|
|
450
|
-
try {
|
|
451
|
-
const mismatchText = await composeApprovalMessageGenerative({
|
|
452
|
-
scenario: 'guardian_identity_mismatch',
|
|
453
|
-
channel: sourceChannel,
|
|
454
|
-
}, {}, approvalCopyGenerator);
|
|
455
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
456
|
-
chatId: conversationExternalId,
|
|
457
|
-
text: mismatchText,
|
|
458
|
-
assistantId,
|
|
459
|
-
}, bearerToken);
|
|
460
|
-
} catch (err) {
|
|
461
|
-
log.error({ err, conversationExternalId }, 'Failed to deliver guardian identity mismatch notice (legacy path)');
|
|
462
|
-
}
|
|
463
|
-
return { handled: true, type: 'guardian_decision_applied' };
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
// Access request approvals need a separate decision path.
|
|
467
|
-
if (targetLegacyApproval.toolName === 'ingress_access_request') {
|
|
468
|
-
const accessResult = await handleAccessRequestApproval(
|
|
469
|
-
targetLegacyApproval,
|
|
470
|
-
legacyGuardianDecision.action === 'reject' ? 'deny' : 'approve',
|
|
471
|
-
actorExternalId,
|
|
472
|
-
replyCallbackUrl,
|
|
473
|
-
assistantId,
|
|
474
|
-
bearerToken,
|
|
475
|
-
);
|
|
476
|
-
return accessResult;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// Apply the decision through the unified guardian decision primitive.
|
|
480
|
-
const result = applyGuardianDecision({
|
|
481
|
-
approval: targetLegacyApproval,
|
|
482
|
-
decision: legacyGuardianDecision,
|
|
483
|
-
actorExternalUserId: actorExternalId,
|
|
484
|
-
actorChannel: sourceChannel,
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
if (result.applied) {
|
|
488
|
-
// Notify the requester's chat about the outcome
|
|
489
|
-
const outcomeText = await composeApprovalMessageGenerative({
|
|
490
|
-
scenario: 'guardian_decision_outcome',
|
|
491
|
-
decision: legacyGuardianDecision.action === 'reject' ? 'denied' : 'approved',
|
|
492
|
-
toolName: targetLegacyApproval.toolName,
|
|
493
|
-
channel: sourceChannel,
|
|
494
|
-
}, {}, approvalCopyGenerator);
|
|
495
|
-
try {
|
|
496
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
497
|
-
chatId: targetLegacyApproval.requesterChatId,
|
|
498
|
-
text: outcomeText,
|
|
499
|
-
assistantId,
|
|
500
|
-
}, bearerToken);
|
|
501
|
-
} catch (err) {
|
|
502
|
-
log.error({ err, conversationId: targetLegacyApproval.conversationId }, 'Failed to notify requester of guardian decision (legacy path)');
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
return { handled: true, type: 'guardian_decision_applied' };
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
// Race condition: request was already resolved. Deliver stale notice.
|
|
509
|
-
try {
|
|
510
|
-
const staleText = await composeApprovalMessageGenerative({
|
|
511
|
-
scenario: 'approval_already_resolved',
|
|
512
|
-
channel: sourceChannel,
|
|
513
|
-
}, {}, approvalCopyGenerator);
|
|
514
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
515
|
-
chatId: conversationExternalId,
|
|
516
|
-
text: staleText,
|
|
517
|
-
assistantId,
|
|
518
|
-
}, bearerToken);
|
|
519
|
-
} catch (err) {
|
|
520
|
-
log.error({ err, conversationId: targetLegacyApproval.conversationId }, 'Failed to deliver stale guardian legacy fallback notice');
|
|
521
|
-
}
|
|
522
|
-
return { handled: true, type: 'stale_ignored' };
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
// No decision could be parsed — send a generic reminder to the guardian
|
|
526
|
-
try {
|
|
527
|
-
const reminderText = await composeApprovalMessageGenerative({
|
|
528
|
-
scenario: 'reminder_prompt',
|
|
529
|
-
toolName: guardianApproval.toolName,
|
|
530
|
-
channel: sourceChannel,
|
|
531
|
-
}, {}, approvalCopyGenerator);
|
|
532
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
533
|
-
chatId: conversationExternalId,
|
|
534
|
-
text: reminderText,
|
|
535
|
-
assistantId,
|
|
536
|
-
}, bearerToken);
|
|
537
|
-
} catch (err) {
|
|
538
|
-
log.error({ err, conversationId: guardianApproval.conversationId }, 'Failed to deliver guardian reminder (legacy path)');
|
|
539
|
-
}
|
|
540
|
-
return { handled: true, type: 'assistant_turn' };
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
// No content and no engine — nothing to do, fall through to standard
|
|
544
|
-
// approval interception below.
|
|
99
|
+
// of a non-guardian requester. Delegated to the guardian callback strategy.
|
|
100
|
+
if (trustCtx.trustClass === "guardian" && actorExternalId) {
|
|
101
|
+
const guardianResult = await handleGuardianCallbackDecision({
|
|
102
|
+
content,
|
|
103
|
+
callbackData,
|
|
104
|
+
conversationExternalId,
|
|
105
|
+
sourceChannel,
|
|
106
|
+
actorExternalId,
|
|
107
|
+
replyCallbackUrl,
|
|
108
|
+
bearerToken,
|
|
109
|
+
assistantId,
|
|
110
|
+
approvalCopyGenerator,
|
|
111
|
+
approvalConversationGenerator,
|
|
112
|
+
});
|
|
113
|
+
if (guardianResult) {
|
|
114
|
+
return guardianResult;
|
|
545
115
|
}
|
|
546
116
|
}
|
|
547
117
|
|
|
@@ -553,7 +123,8 @@ export async function handleApprovalInterception(
|
|
|
553
123
|
// unknown trust + explicit denial reason (`no_identity` / `no_binding`).
|
|
554
124
|
// Unknown without a denial reason means identity-known, non-member sender
|
|
555
125
|
// in a shared channel; that case must not force-reject someone else's request.
|
|
556
|
-
const isLegacyUnverifiedSender =
|
|
126
|
+
const isLegacyUnverifiedSender =
|
|
127
|
+
trustCtx.trustClass === "unknown" && !!trustCtx.denialReason;
|
|
557
128
|
|
|
558
129
|
// When the sender is from a legacy-unverified channel actor, auto-deny any
|
|
559
130
|
// pending confirmation and block self-approval.
|
|
@@ -562,14 +133,14 @@ export async function handleApprovalInterception(
|
|
|
562
133
|
if (pending.length > 0) {
|
|
563
134
|
handleChannelDecision(
|
|
564
135
|
conversationId,
|
|
565
|
-
{ action:
|
|
136
|
+
{ action: "reject", source: "plain_text" },
|
|
566
137
|
buildGuardianDenyContext(
|
|
567
138
|
pending[0].toolName,
|
|
568
|
-
|
|
139
|
+
trustCtx.denialReason ?? "no_binding",
|
|
569
140
|
sourceChannel,
|
|
570
141
|
),
|
|
571
142
|
);
|
|
572
|
-
return { handled: true, type:
|
|
143
|
+
return { handled: true, type: "decision_applied" };
|
|
573
144
|
}
|
|
574
145
|
}
|
|
575
146
|
|
|
@@ -579,12 +150,15 @@ export async function handleApprovalInterception(
|
|
|
579
150
|
//
|
|
580
151
|
// Include identity-known, non-member senders (`unknown` without denialReason)
|
|
581
152
|
// so shared-channel participants can't approve/deny someone else's pending request.
|
|
582
|
-
const isIdentityKnownNonGuardian =
|
|
583
|
-
|
|
153
|
+
const isIdentityKnownNonGuardian =
|
|
154
|
+
trustCtx.trustClass === "trusted_contact" ||
|
|
155
|
+
(trustCtx.trustClass === "unknown" && !trustCtx.denialReason);
|
|
584
156
|
if (isIdentityKnownNonGuardian) {
|
|
585
157
|
const pending = getApprovalInfoByConversation(conversationId);
|
|
586
158
|
if (pending.length > 0) {
|
|
587
|
-
const guardianApprovalForRequest = getPendingApprovalForRequest(
|
|
159
|
+
const guardianApprovalForRequest = getPendingApprovalForRequest(
|
|
160
|
+
pending[0].requestId,
|
|
161
|
+
);
|
|
588
162
|
if (guardianApprovalForRequest) {
|
|
589
163
|
// Allow the requester to cancel their own pending guardian request.
|
|
590
164
|
// Only reject/cancel is permitted — self-approval is still blocked.
|
|
@@ -599,24 +173,30 @@ export async function handleApprovalInterception(
|
|
|
599
173
|
if (approvalConversationGenerator) {
|
|
600
174
|
const cancelContext: ApprovalConversationContext = {
|
|
601
175
|
toolName: pending[0].toolName,
|
|
602
|
-
allowedActions: [
|
|
603
|
-
role:
|
|
604
|
-
pendingApprovals: pending.map(p => ({
|
|
176
|
+
allowedActions: ["reject"],
|
|
177
|
+
role: "requester",
|
|
178
|
+
pendingApprovals: pending.map((p) => ({
|
|
179
|
+
requestId: p.requestId,
|
|
180
|
+
toolName: p.toolName,
|
|
181
|
+
})),
|
|
605
182
|
userMessage: content,
|
|
606
183
|
};
|
|
607
|
-
const cancelResult = await runApprovalConversationTurn(
|
|
608
|
-
|
|
184
|
+
const cancelResult = await runApprovalConversationTurn(
|
|
185
|
+
cancelContext,
|
|
186
|
+
approvalConversationGenerator,
|
|
187
|
+
);
|
|
188
|
+
if (cancelResult.disposition === "reject") {
|
|
609
189
|
requesterCancelIntent = true;
|
|
610
190
|
cancelReplyText = cancelResult.replyText;
|
|
611
|
-
} else if (cancelResult.disposition ===
|
|
191
|
+
} else if (cancelResult.disposition === "keep_pending") {
|
|
612
192
|
requesterFollowupReplyText = cancelResult.replyText;
|
|
613
193
|
}
|
|
614
194
|
}
|
|
615
195
|
|
|
616
196
|
if (requesterCancelIntent) {
|
|
617
197
|
const rejectDecision: ApprovalDecisionResult = {
|
|
618
|
-
action:
|
|
619
|
-
source:
|
|
198
|
+
action: "reject",
|
|
199
|
+
source: "plain_text",
|
|
620
200
|
};
|
|
621
201
|
// Apply the cancel decision through the unified primitive.
|
|
622
202
|
// The primitive handles record update and (no-op) grant logic.
|
|
@@ -628,119 +208,152 @@ export async function handleApprovalInterception(
|
|
|
628
208
|
});
|
|
629
209
|
if (cancelApplyResult.applied) {
|
|
630
210
|
// Notify requester
|
|
631
|
-
const replyText =
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
211
|
+
const replyText =
|
|
212
|
+
cancelReplyText ??
|
|
213
|
+
(await composeApprovalMessageGenerative(
|
|
214
|
+
{
|
|
215
|
+
scenario: "requester_cancel",
|
|
216
|
+
toolName: pending[0].toolName,
|
|
217
|
+
channel: sourceChannel,
|
|
218
|
+
},
|
|
219
|
+
{},
|
|
220
|
+
approvalCopyGenerator,
|
|
221
|
+
));
|
|
636
222
|
try {
|
|
637
|
-
await deliverChannelReply(
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
223
|
+
await deliverChannelReply(
|
|
224
|
+
replyCallbackUrl,
|
|
225
|
+
{
|
|
226
|
+
chatId: conversationExternalId,
|
|
227
|
+
text: replyText,
|
|
228
|
+
assistantId,
|
|
229
|
+
},
|
|
230
|
+
bearerToken,
|
|
231
|
+
);
|
|
642
232
|
} catch (err) {
|
|
643
|
-
log.error(
|
|
233
|
+
log.error(
|
|
234
|
+
{ err, conversationId },
|
|
235
|
+
"Failed to deliver requester cancel notice",
|
|
236
|
+
);
|
|
644
237
|
}
|
|
645
238
|
|
|
646
239
|
// Notify guardian that the request was cancelled
|
|
647
240
|
try {
|
|
648
|
-
const guardianNotice = await composeApprovalMessageGenerative(
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
241
|
+
const guardianNotice = await composeApprovalMessageGenerative(
|
|
242
|
+
{
|
|
243
|
+
scenario: "guardian_decision_outcome",
|
|
244
|
+
decision: "denied",
|
|
245
|
+
toolName: pending[0].toolName,
|
|
246
|
+
channel: sourceChannel,
|
|
247
|
+
},
|
|
248
|
+
{},
|
|
249
|
+
approvalCopyGenerator,
|
|
250
|
+
);
|
|
251
|
+
await deliverChannelReply(
|
|
252
|
+
replyCallbackUrl,
|
|
253
|
+
{
|
|
254
|
+
chatId: guardianApprovalForRequest.guardianChatId,
|
|
255
|
+
text: guardianNotice,
|
|
256
|
+
assistantId,
|
|
257
|
+
},
|
|
258
|
+
bearerToken,
|
|
259
|
+
);
|
|
659
260
|
} catch (err) {
|
|
660
|
-
log.error(
|
|
261
|
+
log.error(
|
|
262
|
+
{ err, conversationId },
|
|
263
|
+
"Failed to notify guardian of requester cancellation",
|
|
264
|
+
);
|
|
661
265
|
}
|
|
662
266
|
|
|
663
|
-
return { handled: true, type:
|
|
267
|
+
return { handled: true, type: "decision_applied" };
|
|
664
268
|
}
|
|
665
269
|
|
|
666
270
|
// Race condition: approval was already resolved elsewhere.
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
}
|
|
680
|
-
return { handled: true, type:
|
|
271
|
+
await deliverStaleApprovalReply({
|
|
272
|
+
scenario: "approval_already_resolved",
|
|
273
|
+
sourceChannel,
|
|
274
|
+
replyCallbackUrl,
|
|
275
|
+
chatId: conversationExternalId,
|
|
276
|
+
assistantId,
|
|
277
|
+
bearerToken,
|
|
278
|
+
approvalCopyGenerator,
|
|
279
|
+
logger: log,
|
|
280
|
+
errorLogMessage:
|
|
281
|
+
"Failed to deliver stale requester-cancel notice",
|
|
282
|
+
errorLogContext: { conversationId },
|
|
283
|
+
});
|
|
284
|
+
return { handled: true, type: "stale_ignored" };
|
|
681
285
|
}
|
|
682
286
|
|
|
683
287
|
if (requesterFollowupReplyText) {
|
|
684
288
|
try {
|
|
685
|
-
await deliverChannelReply(
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
289
|
+
await deliverChannelReply(
|
|
290
|
+
replyCallbackUrl,
|
|
291
|
+
{
|
|
292
|
+
chatId: conversationExternalId,
|
|
293
|
+
text: requesterFollowupReplyText,
|
|
294
|
+
assistantId,
|
|
295
|
+
},
|
|
296
|
+
bearerToken,
|
|
297
|
+
);
|
|
690
298
|
} catch (err) {
|
|
691
|
-
log.error(
|
|
299
|
+
log.error(
|
|
300
|
+
{ err, conversationId },
|
|
301
|
+
"Failed to deliver requester follow-up reply while awaiting guardian",
|
|
302
|
+
);
|
|
692
303
|
}
|
|
693
|
-
return { handled: true, type:
|
|
304
|
+
return { handled: true, type: "assistant_turn" };
|
|
694
305
|
}
|
|
695
306
|
}
|
|
696
307
|
|
|
697
308
|
// Not a cancel intent — tell the requester their request is pending
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
}
|
|
711
|
-
return { handled: true, type:
|
|
309
|
+
await deliverStaleApprovalReply({
|
|
310
|
+
scenario: "request_pending_guardian",
|
|
311
|
+
sourceChannel,
|
|
312
|
+
replyCallbackUrl,
|
|
313
|
+
chatId: conversationExternalId,
|
|
314
|
+
assistantId,
|
|
315
|
+
bearerToken,
|
|
316
|
+
approvalCopyGenerator,
|
|
317
|
+
logger: log,
|
|
318
|
+
errorLogMessage:
|
|
319
|
+
"Failed to deliver guardian-pending notice to requester",
|
|
320
|
+
errorLogContext: { conversationId },
|
|
321
|
+
});
|
|
322
|
+
return { handled: true, type: "assistant_turn" };
|
|
712
323
|
}
|
|
713
324
|
|
|
714
325
|
// Check for an expired-but-unresolved guardian approval. If the approval
|
|
715
326
|
// expired without a guardian decision, auto-deny and transition
|
|
716
327
|
// the approval to 'expired'. Without this, the requester could bypass
|
|
717
328
|
// guardian-only controls by simply waiting for the TTL to elapse.
|
|
718
|
-
const unresolvedApproval = getUnresolvedApprovalForRequest(
|
|
329
|
+
const unresolvedApproval = getUnresolvedApprovalForRequest(
|
|
330
|
+
pending[0].requestId,
|
|
331
|
+
);
|
|
719
332
|
if (unresolvedApproval) {
|
|
720
|
-
updateApprovalDecision(unresolvedApproval.id, { status:
|
|
333
|
+
updateApprovalDecision(unresolvedApproval.id, { status: "expired" });
|
|
721
334
|
|
|
722
335
|
// Auto-deny the underlying request so it does not remain actionable
|
|
723
336
|
const expiredDecision: ApprovalDecisionResult = {
|
|
724
|
-
action:
|
|
725
|
-
source:
|
|
337
|
+
action: "reject",
|
|
338
|
+
source: "plain_text",
|
|
726
339
|
};
|
|
727
340
|
handleChannelDecision(conversationId, expiredDecision);
|
|
728
341
|
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
}
|
|
743
|
-
return { handled: true, type:
|
|
342
|
+
await deliverStaleApprovalReply({
|
|
343
|
+
scenario: "guardian_expired_requester",
|
|
344
|
+
sourceChannel,
|
|
345
|
+
replyCallbackUrl,
|
|
346
|
+
chatId: conversationExternalId,
|
|
347
|
+
assistantId,
|
|
348
|
+
bearerToken,
|
|
349
|
+
approvalCopyGenerator,
|
|
350
|
+
logger: log,
|
|
351
|
+
errorLogMessage:
|
|
352
|
+
"Failed to deliver guardian-expiry notice to requester",
|
|
353
|
+
extraContext: { toolName: pending[0].toolName },
|
|
354
|
+
errorLogContext: { conversationId },
|
|
355
|
+
});
|
|
356
|
+
return { handled: true, type: "decision_applied" };
|
|
744
357
|
}
|
|
745
358
|
|
|
746
359
|
// Guard: non-guardian actors with a guardian binding must not self-approve
|
|
@@ -751,25 +364,32 @@ export async function handleApprovalInterception(
|
|
|
751
364
|
// persisted, any non-guardian actor could otherwise fall through to the
|
|
752
365
|
// standard conversational engine / legacy parser and resolve their own
|
|
753
366
|
// pending request via handleChannelDecision.
|
|
754
|
-
if (
|
|
367
|
+
if (
|
|
368
|
+
trustCtx.trustClass !== "guardian" &&
|
|
369
|
+
trustCtx.guardianExternalUserId
|
|
370
|
+
) {
|
|
755
371
|
log.info(
|
|
756
|
-
{
|
|
757
|
-
|
|
372
|
+
{
|
|
373
|
+
conversationId,
|
|
374
|
+
conversationExternalId,
|
|
375
|
+
guardianExternalUserId: trustCtx.guardianExternalUserId,
|
|
376
|
+
},
|
|
377
|
+
"Blocking non-guardian self-approval: pending confirmation exists but guardian approval row not yet created",
|
|
758
378
|
);
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
}
|
|
772
|
-
return { handled: true, type:
|
|
379
|
+
await deliverStaleApprovalReply({
|
|
380
|
+
scenario: "request_pending_guardian",
|
|
381
|
+
sourceChannel,
|
|
382
|
+
replyCallbackUrl,
|
|
383
|
+
chatId: conversationExternalId,
|
|
384
|
+
assistantId,
|
|
385
|
+
bearerToken,
|
|
386
|
+
approvalCopyGenerator,
|
|
387
|
+
logger: log,
|
|
388
|
+
errorLogMessage:
|
|
389
|
+
"Failed to deliver guardian-pending notice to non-guardian actor (pre-row guard)",
|
|
390
|
+
errorLogContext: { conversationId },
|
|
391
|
+
});
|
|
392
|
+
return { handled: true, type: "assistant_turn" };
|
|
773
393
|
}
|
|
774
394
|
}
|
|
775
395
|
}
|
|
@@ -784,12 +404,15 @@ export async function handleApprovalInterception(
|
|
|
784
404
|
// previous approval prompt) must not apply to a different pending interaction.
|
|
785
405
|
if (cbDecision.requestId) {
|
|
786
406
|
const pending = getApprovalInfoByConversation(conversationId);
|
|
787
|
-
if (
|
|
407
|
+
if (
|
|
408
|
+
pending.length === 0 ||
|
|
409
|
+
!pending.some((p) => p.requestId === cbDecision.requestId)
|
|
410
|
+
) {
|
|
788
411
|
log.warn(
|
|
789
412
|
{ conversationId, callbackRequestId: cbDecision.requestId },
|
|
790
|
-
|
|
413
|
+
"Callback request ID does not match any pending interaction, ignoring stale button press",
|
|
791
414
|
);
|
|
792
|
-
return { handled: true, type:
|
|
415
|
+
return { handled: true, type: "stale_ignored" };
|
|
793
416
|
}
|
|
794
417
|
}
|
|
795
418
|
|
|
@@ -798,321 +421,73 @@ export async function handleApprovalInterception(
|
|
|
798
421
|
if (result.applied) {
|
|
799
422
|
// Post-decision delivery is handled by the onEvent callback
|
|
800
423
|
// in the session that registered the pending interaction.
|
|
801
|
-
return { handled: true, type:
|
|
424
|
+
return { handled: true, type: "decision_applied" };
|
|
802
425
|
}
|
|
803
426
|
|
|
804
427
|
// Race condition: request was already resolved between the stale check
|
|
805
428
|
// above and the decision attempt.
|
|
806
|
-
return { handled: true, type:
|
|
429
|
+
return { handled: true, type: "stale_ignored" };
|
|
807
430
|
}
|
|
808
431
|
}
|
|
809
432
|
|
|
810
433
|
// ── Conversational approval engine for plain-text messages ──
|
|
811
|
-
//
|
|
812
|
-
//
|
|
813
|
-
// and respond conversationally.
|
|
434
|
+
// Delegates to the text engine strategy which classifies natural language
|
|
435
|
+
// and responds conversationally.
|
|
814
436
|
const pending = getApprovalInfoByConversation(conversationId);
|
|
815
437
|
if (pending.length > 0 && approvalConversationGenerator && content) {
|
|
816
438
|
const allowedActions = pendingPrompt.actions.map((a) => a.id);
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
pendingApprovals: pending.map((p) => ({ requestId: p.requestId, toolName: p.toolName })),
|
|
822
|
-
userMessage: content,
|
|
823
|
-
};
|
|
824
|
-
|
|
825
|
-
const engineResult = await runApprovalConversationTurn(engineContext, approvalConversationGenerator);
|
|
826
|
-
|
|
827
|
-
if (engineResult.disposition === 'keep_pending') {
|
|
828
|
-
// Non-decision follow-up — deliver the engine's reply and keep the request pending
|
|
829
|
-
try {
|
|
830
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
831
|
-
chatId: conversationExternalId,
|
|
832
|
-
text: engineResult.replyText,
|
|
833
|
-
assistantId,
|
|
834
|
-
}, bearerToken);
|
|
835
|
-
} catch (err) {
|
|
836
|
-
log.error({ err, conversationId }, 'Failed to deliver approval conversation reply');
|
|
837
|
-
}
|
|
838
|
-
return { handled: true, type: 'assistant_turn' };
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
// Decision-bearing disposition — map to ApprovalDecisionResult and apply
|
|
842
|
-
const decisionAction = engineResult.disposition as ApprovalAction;
|
|
843
|
-
const engineDecision: ApprovalDecisionResult = {
|
|
844
|
-
action: decisionAction,
|
|
845
|
-
source: 'plain_text',
|
|
846
|
-
...(engineResult.targetRequestId ? { requestId: engineResult.targetRequestId } : {}),
|
|
847
|
-
};
|
|
848
|
-
|
|
849
|
-
const result = handleChannelDecision(conversationId, engineDecision);
|
|
850
|
-
|
|
851
|
-
if (result.applied) {
|
|
852
|
-
// Deliver the engine's reply text to the user
|
|
853
|
-
try {
|
|
854
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
855
|
-
chatId: conversationExternalId,
|
|
856
|
-
text: engineResult.replyText,
|
|
857
|
-
assistantId,
|
|
858
|
-
}, bearerToken);
|
|
859
|
-
} catch (err) {
|
|
860
|
-
log.error({ err, conversationId }, 'Failed to deliver approval decision reply');
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
return { handled: true, type: 'decision_applied' };
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
// Race condition: request was already resolved by expiry sweep or
|
|
867
|
-
// concurrent callback. Deliver a stale notice instead of the
|
|
868
|
-
// engine's optimistic reply.
|
|
869
|
-
try {
|
|
870
|
-
const staleText = await composeApprovalMessageGenerative({
|
|
871
|
-
scenario: 'approval_already_resolved',
|
|
872
|
-
channel: sourceChannel,
|
|
873
|
-
}, {}, approvalCopyGenerator);
|
|
874
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
875
|
-
chatId: conversationExternalId,
|
|
876
|
-
text: staleText,
|
|
877
|
-
assistantId,
|
|
878
|
-
}, bearerToken);
|
|
879
|
-
} catch (err) {
|
|
880
|
-
log.error({ err, conversationId }, 'Failed to deliver stale approval notice');
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
return { handled: true, type: 'stale_ignored' };
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
// Fallback: no conversational generator available or no content — use
|
|
887
|
-
// the legacy deterministic path as a safety net. This preserves backward
|
|
888
|
-
// compatibility when the generator is not injected.
|
|
889
|
-
if (content) {
|
|
890
|
-
const legacyDecision = parseApprovalDecision(content);
|
|
891
|
-
if (legacyDecision) {
|
|
892
|
-
if (legacyDecision.requestId) {
|
|
893
|
-
if (pending.length === 0 || !pending.some(p => p.requestId === legacyDecision.requestId)) {
|
|
894
|
-
return { handled: true, type: 'stale_ignored' };
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
const result = handleChannelDecision(conversationId, legacyDecision);
|
|
898
|
-
if (result.applied) {
|
|
899
|
-
return { handled: true, type: 'decision_applied' };
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
// Race condition: request was already resolved.
|
|
903
|
-
try {
|
|
904
|
-
const staleText = await composeApprovalMessageGenerative({
|
|
905
|
-
scenario: 'approval_already_resolved',
|
|
906
|
-
channel: sourceChannel,
|
|
907
|
-
}, {}, approvalCopyGenerator);
|
|
908
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
909
|
-
chatId: conversationExternalId,
|
|
910
|
-
text: staleText,
|
|
911
|
-
assistantId,
|
|
912
|
-
}, bearerToken);
|
|
913
|
-
} catch (err) {
|
|
914
|
-
log.error({ err, conversationId }, 'Failed to deliver stale approval notice (legacy path)');
|
|
915
|
-
}
|
|
916
|
-
return { handled: true, type: 'stale_ignored' };
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
// No decision could be extracted and no conversational engine is available —
|
|
921
|
-
// deliver a simple status reply rather than a reminder prompt.
|
|
922
|
-
try {
|
|
923
|
-
const statusText = await composeApprovalMessageGenerative({
|
|
924
|
-
scenario: 'reminder_prompt',
|
|
925
|
-
channel: sourceChannel,
|
|
926
|
-
toolName: pending.length > 0 ? pending[0].toolName : undefined,
|
|
927
|
-
}, {}, approvalCopyGenerator);
|
|
928
|
-
await deliverChannelReply(replyCallbackUrl, {
|
|
929
|
-
chatId: conversationExternalId,
|
|
930
|
-
text: statusText,
|
|
931
|
-
assistantId,
|
|
932
|
-
}, bearerToken);
|
|
933
|
-
} catch (err) {
|
|
934
|
-
log.error({ err, conversationId }, 'Failed to deliver approval status reply');
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
return { handled: true, type: 'assistant_turn' };
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
// ---------------------------------------------------------------------------
|
|
941
|
-
// Access request decision helper
|
|
942
|
-
// ---------------------------------------------------------------------------
|
|
943
|
-
|
|
944
|
-
/**
|
|
945
|
-
* Handle a guardian's decision on an `ingress_access_request` approval.
|
|
946
|
-
* Delegates to the access-request-decision module and orchestrates
|
|
947
|
-
* notification delivery.
|
|
948
|
-
*
|
|
949
|
-
* On approve: creates a verification session, delivers the code to the
|
|
950
|
-
* guardian, and notifies the requester to expect a code.
|
|
951
|
-
*
|
|
952
|
-
* On deny: marks the request as denied and notifies the requester.
|
|
953
|
-
*/
|
|
954
|
-
async function handleAccessRequestApproval(
|
|
955
|
-
approval: GuardianApprovalRequest,
|
|
956
|
-
action: 'approve' | 'deny',
|
|
957
|
-
decidedByExternalUserId: string,
|
|
958
|
-
replyCallbackUrl: string,
|
|
959
|
-
assistantId: string,
|
|
960
|
-
bearerToken?: string,
|
|
961
|
-
): Promise<ApprovalInterceptionResult> {
|
|
962
|
-
const decisionResult = handleAccessRequestDecision(
|
|
963
|
-
approval,
|
|
964
|
-
action,
|
|
965
|
-
decidedByExternalUserId,
|
|
966
|
-
);
|
|
967
|
-
|
|
968
|
-
if (decisionResult.type === 'stale' || decisionResult.type === 'idempotent') {
|
|
969
|
-
return { handled: true, type: 'stale_ignored' };
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
if (decisionResult.type === 'denied') {
|
|
973
|
-
await notifyRequesterOfDenial({
|
|
439
|
+
return handleGuardianTextEngineDecision({
|
|
440
|
+
conversationId,
|
|
441
|
+
conversationExternalId,
|
|
442
|
+
sourceChannel,
|
|
974
443
|
replyCallbackUrl,
|
|
975
|
-
|
|
444
|
+
content,
|
|
976
445
|
assistantId,
|
|
977
446
|
bearerToken,
|
|
447
|
+
approvalCopyGenerator,
|
|
448
|
+
approvalConversationGenerator,
|
|
449
|
+
pending,
|
|
450
|
+
allowedActions,
|
|
978
451
|
});
|
|
979
|
-
|
|
980
|
-
// Emit both guardian_decision and denied signals so all lifecycle
|
|
981
|
-
// observers are notified of the denial.
|
|
982
|
-
const deniedPayload = {
|
|
983
|
-
sourceChannel: approval.channel,
|
|
984
|
-
requesterExternalUserId: approval.requesterExternalUserId,
|
|
985
|
-
requesterChatId: approval.requesterChatId,
|
|
986
|
-
decidedByExternalUserId,
|
|
987
|
-
decision: 'denied' as const,
|
|
988
|
-
};
|
|
989
|
-
|
|
990
|
-
void emitNotificationSignal({
|
|
991
|
-
sourceEventName: 'ingress.trusted_contact.guardian_decision',
|
|
992
|
-
sourceChannel: approval.channel,
|
|
993
|
-
sourceSessionId: approval.conversationId,
|
|
994
|
-
assistantId,
|
|
995
|
-
attentionHints: {
|
|
996
|
-
requiresAction: false,
|
|
997
|
-
urgency: 'medium',
|
|
998
|
-
isAsyncBackground: false,
|
|
999
|
-
visibleInSourceNow: false,
|
|
1000
|
-
},
|
|
1001
|
-
contextPayload: deniedPayload,
|
|
1002
|
-
dedupeKey: `trusted-contact:guardian-decision:${approval.id}`,
|
|
1003
|
-
});
|
|
1004
|
-
|
|
1005
|
-
void emitNotificationSignal({
|
|
1006
|
-
sourceEventName: 'ingress.trusted_contact.denied',
|
|
1007
|
-
sourceChannel: approval.channel,
|
|
1008
|
-
sourceSessionId: approval.conversationId,
|
|
1009
|
-
assistantId,
|
|
1010
|
-
attentionHints: {
|
|
1011
|
-
requiresAction: false,
|
|
1012
|
-
urgency: 'low',
|
|
1013
|
-
isAsyncBackground: false,
|
|
1014
|
-
visibleInSourceNow: false,
|
|
1015
|
-
},
|
|
1016
|
-
contextPayload: deniedPayload,
|
|
1017
|
-
dedupeKey: `trusted-contact:denied:${approval.id}`,
|
|
1018
|
-
});
|
|
1019
|
-
|
|
1020
|
-
return { handled: true, type: 'guardian_decision_applied' };
|
|
1021
452
|
}
|
|
1022
453
|
|
|
1023
|
-
//
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
454
|
+
// ── Legacy deterministic fallback ──
|
|
455
|
+
// When no conversational engine is available, use the deterministic parser
|
|
456
|
+
// as a safety net for backward compatibility.
|
|
457
|
+
if (content) {
|
|
458
|
+
const legacyResult = await handleGuardianLegacyFallback({
|
|
459
|
+
conversationId,
|
|
460
|
+
conversationExternalId,
|
|
461
|
+
sourceChannel,
|
|
1029
462
|
replyCallbackUrl,
|
|
1030
|
-
|
|
1031
|
-
requesterIdentifier,
|
|
1032
|
-
verificationCode: decisionResult.verificationCode,
|
|
463
|
+
content,
|
|
1033
464
|
assistantId,
|
|
1034
465
|
bearerToken,
|
|
466
|
+
approvalCopyGenerator,
|
|
467
|
+
pending,
|
|
1035
468
|
});
|
|
1036
|
-
if (
|
|
1037
|
-
|
|
1038
|
-
{ reason: deliveryResult.reason, approvalId: approval.id },
|
|
1039
|
-
'Skipping requester notification — verification code was not delivered to guardian',
|
|
1040
|
-
);
|
|
1041
|
-
codeDelivered = false;
|
|
469
|
+
if (legacyResult) {
|
|
470
|
+
return legacyResult;
|
|
1042
471
|
}
|
|
1043
472
|
}
|
|
1044
473
|
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
// Don't emit guardian_decision for approvals that still require code
|
|
1063
|
-
// verification — the guardian already received the code, and emitting
|
|
1064
|
-
// this signal prematurely causes the notification pipeline to deliver
|
|
1065
|
-
// a confusing "approved" message before the requester has verified.
|
|
1066
|
-
// The guardian_decision signal should only fire once access is fully granted
|
|
1067
|
-
// (i.e. after code consumption), which is handled in the verification path.
|
|
1068
|
-
if (!decisionResult.verificationSessionId) {
|
|
1069
|
-
void emitNotificationSignal({
|
|
1070
|
-
sourceEventName: 'ingress.trusted_contact.guardian_decision',
|
|
1071
|
-
sourceChannel: approval.channel,
|
|
1072
|
-
sourceSessionId: approval.conversationId,
|
|
1073
|
-
assistantId,
|
|
1074
|
-
attentionHints: {
|
|
1075
|
-
requiresAction: false,
|
|
1076
|
-
urgency: 'medium',
|
|
1077
|
-
isAsyncBackground: false,
|
|
1078
|
-
visibleInSourceNow: false,
|
|
1079
|
-
},
|
|
1080
|
-
contextPayload: {
|
|
1081
|
-
sourceChannel: approval.channel,
|
|
1082
|
-
requesterExternalUserId: approval.requesterExternalUserId,
|
|
1083
|
-
requesterChatId: approval.requesterChatId,
|
|
1084
|
-
decidedByExternalUserId,
|
|
1085
|
-
decision: 'approved',
|
|
1086
|
-
},
|
|
1087
|
-
dedupeKey: `trusted-contact:guardian-decision:${approval.id}`,
|
|
1088
|
-
});
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
// Emit verification_sent with visibleInSourceNow=true so the notification
|
|
1092
|
-
// pipeline suppresses delivery — the guardian already received the
|
|
1093
|
-
// verification code directly. Without this flag, the pipeline generates
|
|
1094
|
-
// a redundant LLM message like "Good news! Your request has been approved."
|
|
1095
|
-
if (decisionResult.verificationSessionId && codeDelivered) {
|
|
1096
|
-
void emitNotificationSignal({
|
|
1097
|
-
sourceEventName: 'ingress.trusted_contact.verification_sent',
|
|
1098
|
-
sourceChannel: approval.channel,
|
|
1099
|
-
sourceSessionId: approval.conversationId,
|
|
1100
|
-
assistantId,
|
|
1101
|
-
attentionHints: {
|
|
1102
|
-
requiresAction: false,
|
|
1103
|
-
urgency: 'low',
|
|
1104
|
-
isAsyncBackground: true,
|
|
1105
|
-
visibleInSourceNow: true,
|
|
1106
|
-
},
|
|
1107
|
-
contextPayload: {
|
|
1108
|
-
sourceChannel: approval.channel,
|
|
1109
|
-
requesterExternalUserId: approval.requesterExternalUserId,
|
|
1110
|
-
requesterChatId: approval.requesterChatId,
|
|
1111
|
-
verificationSessionId: decisionResult.verificationSessionId,
|
|
1112
|
-
},
|
|
1113
|
-
dedupeKey: `trusted-contact:verification-sent:${decisionResult.verificationSessionId}`,
|
|
1114
|
-
});
|
|
1115
|
-
}
|
|
474
|
+
// No decision could be extracted and no conversational engine is available —
|
|
475
|
+
// deliver a simple status reply rather than a reminder prompt.
|
|
476
|
+
await deliverStaleApprovalReply({
|
|
477
|
+
scenario: "reminder_prompt",
|
|
478
|
+
sourceChannel,
|
|
479
|
+
replyCallbackUrl,
|
|
480
|
+
chatId: conversationExternalId,
|
|
481
|
+
assistantId,
|
|
482
|
+
bearerToken,
|
|
483
|
+
approvalCopyGenerator,
|
|
484
|
+
logger: log,
|
|
485
|
+
errorLogMessage: "Failed to deliver approval status reply",
|
|
486
|
+
extraContext: {
|
|
487
|
+
toolName: pending.length > 0 ? pending[0].toolName : undefined,
|
|
488
|
+
},
|
|
489
|
+
errorLogContext: { conversationId },
|
|
490
|
+
});
|
|
1116
491
|
|
|
1117
|
-
return { handled: true, type:
|
|
492
|
+
return { handled: true, type: "assistant_turn" };
|
|
1118
493
|
}
|