@vellumai/assistant 0.4.44 → 0.4.45
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/.prettierignore +4 -0
- package/ARCHITECTURE.md +34 -31
- package/README.md +4 -4
- package/bun.lock +10 -35
- package/docs/architecture/integrations.md +102 -197
- package/docs/architecture/keychain-broker.md +1 -1
- package/docs/architecture/memory.md +2 -2
- package/docs/architecture/scheduling.md +1 -1
- package/docs/architecture/security.md +11 -11
- package/docs/error-handling.md +1 -1
- package/docs/trusted-contact-access.md +3 -3
- package/drizzle/meta/0000_snapshot.json +34 -100
- package/drizzle/meta/_journal.json +1 -1
- package/drizzle.config.ts +4 -4
- package/package.json +3 -2
- package/scripts/capture-x-graphql.ts +237 -141
- package/scripts/generate-bundled-tool-registry.ts +223 -0
- package/src/__tests__/access-request-decision.test.ts +0 -1
- package/src/__tests__/actor-token-service.test.ts +23 -24
- package/src/__tests__/agent-loop.test.ts +0 -131
- package/src/__tests__/always-loaded-tools-guard.test.ts +71 -0
- package/src/__tests__/amazon-cdp-integration.test.ts +11 -9
- package/src/__tests__/approval-primitive.test.ts +0 -1
- package/src/__tests__/approval-routes-http.test.ts +11 -1
- package/src/__tests__/asset-materialize-tool.test.ts +0 -1
- package/src/__tests__/asset-search-tool.test.ts +0 -1
- package/src/__tests__/assistant-attachment-directive.test.ts +1 -1
- package/src/__tests__/assistant-events-sse-hardening.test.ts +0 -1
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
- package/src/__tests__/assistant-feature-flags-integration.test.ts +70 -18
- package/src/__tests__/assistant-id-boundary-guard.test.ts +6 -6
- package/src/__tests__/attachments-store.test.ts +0 -1
- package/src/__tests__/avatar-e2e.test.ts +74 -115
- package/src/__tests__/avatar-router.test.ts +25 -62
- package/src/__tests__/browser-manager.test.ts +24 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +4 -3
- package/src/__tests__/browser-skill-endstate.test.ts +8 -11
- package/src/__tests__/btw-routes.test.ts +326 -0
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +23 -9
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/call-conversation-messages.test.ts +0 -1
- package/src/__tests__/call-domain.test.ts +0 -1
- package/src/__tests__/call-pointer-messages.test.ts +0 -1
- package/src/__tests__/call-recovery.test.ts +0 -1
- package/src/__tests__/call-routes-http.test.ts +0 -1
- package/src/__tests__/call-store.test.ts +0 -1
- package/src/__tests__/canonical-guardian-store.test.ts +0 -1
- package/src/__tests__/channel-approval-routes.test.ts +1 -1
- package/src/__tests__/channel-approvals.test.ts +1 -1
- package/src/__tests__/channel-delivery-store.test.ts +0 -1
- package/src/__tests__/channel-guardian.test.ts +5 -7
- package/src/__tests__/channel-retry-sweep.test.ts +0 -1
- package/src/__tests__/checker.test.ts +4 -11
- package/src/__tests__/compaction.benchmark.test.ts +16 -14
- package/src/__tests__/computer-use-session-lifecycle.test.ts +10 -11
- package/src/__tests__/computer-use-session-working-dir.test.ts +2 -6
- package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +2 -5
- package/src/__tests__/computer-use-tools.test.ts +35 -31
- package/src/__tests__/config-schema.test.ts +11 -15
- package/src/__tests__/config-watcher.test.ts +0 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/conflict-store.test.ts +0 -1
- package/src/__tests__/connection-policy.test.ts +4 -7
- package/src/__tests__/contacts-tools.test.ts +0 -1
- package/src/__tests__/context-memory-e2e.test.ts +2 -4
- package/src/__tests__/context-overflow-reducer.test.ts +2 -4
- package/src/__tests__/context-window-manager.test.ts +147 -60
- package/src/__tests__/contradiction-checker.test.ts +0 -1
- package/src/__tests__/conversation-attention-store.test.ts +0 -1
- package/src/__tests__/conversation-attention-telegram.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +25 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +381 -0
- package/src/__tests__/conversation-store.test.ts +0 -1
- package/src/__tests__/conversation-unread-route.test.ts +1 -2
- package/src/__tests__/credential-security-invariants.test.ts +7 -8
- package/src/__tests__/cross-provider-web-search.test.ts +353 -0
- package/src/__tests__/daemon-assistant-events.test.ts +6 -7
- package/src/__tests__/db-schedule-syntax-migration.test.ts +15 -3
- package/src/__tests__/delete-managed-skill-tool.test.ts +5 -9
- package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
- package/src/__tests__/diagnostics-export.test.ts +189 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
- package/src/__tests__/entity-extractor.test.ts +0 -1
- package/src/__tests__/entity-search.test.ts +0 -1
- package/src/__tests__/ephemeral-permissions.test.ts +2 -4
- package/src/__tests__/file-read-tool.test.ts +86 -0
- package/src/__tests__/followup-tools.test.ts +0 -1
- package/src/__tests__/frontmatter.test.ts +77 -34
- package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
- package/src/__tests__/gateway-only-guard.test.ts +1 -1
- package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -1
- package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
- package/src/__tests__/guardian-action-followup-store.test.ts +0 -1
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
- package/src/__tests__/guardian-action-late-reply.test.ts +0 -1
- package/src/__tests__/guardian-action-store.test.ts +0 -1
- package/src/__tests__/guardian-action-sweep.test.ts +0 -1
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -2
- package/src/__tests__/guardian-grant-minting.test.ts +1 -1
- package/src/__tests__/guardian-outbound-http.test.ts +0 -1
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -1
- package/src/__tests__/guardian-routing-invariants.test.ts +1 -1
- package/src/__tests__/guardian-routing-state.test.ts +0 -1
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
- package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +3 -5
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +28 -426
- package/src/__tests__/host-bash-proxy.test.ts +335 -0
- package/src/__tests__/host-file-proxy.test.ts +374 -0
- package/src/__tests__/host-shell-tool.test.ts +147 -1
- package/src/__tests__/http-user-message-parity.test.ts +361 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
- package/src/__tests__/integration-status.test.ts +3 -8
- package/src/__tests__/intent-routing.test.ts +7 -46
- package/src/__tests__/invite-redemption-service.test.ts +0 -1
- package/src/__tests__/invite-routes-http.test.ts +0 -1
- package/src/__tests__/llm-usage-store.test.ts +0 -1
- package/src/__tests__/managed-avatar-client.test.ts +101 -55
- package/src/__tests__/managed-skill-lifecycle.test.ts +9 -18
- package/src/__tests__/managed-store.test.ts +94 -21
- package/src/__tests__/media-reuse-story.e2e.test.ts +0 -1
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +2 -4
- package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -1
- package/src/__tests__/memory-recall-quality.test.ts +0 -1
- package/src/__tests__/memory-regressions.experimental.test.ts +0 -1
- package/src/__tests__/memory-regressions.test.ts +0 -1
- package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -1
- package/src/__tests__/memory-upsert-concurrency.test.ts +0 -1
- package/src/__tests__/messaging-send-tool.test.ts +35 -0
- package/src/__tests__/messaging-skill-split.test.ts +138 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1
- package/src/__tests__/migration-export-http.test.ts +2 -3
- package/src/__tests__/migration-import-commit-http.test.ts +1 -2
- package/src/__tests__/migration-import-preflight-http.test.ts +1 -2
- package/src/__tests__/migration-validate-http.test.ts +1 -2
- package/src/__tests__/native-web-search.test.ts +475 -0
- package/src/__tests__/navigate-settings-tab.test.ts +84 -0
- package/src/__tests__/non-member-access-request.test.ts +0 -1
- package/src/__tests__/notification-broadcaster.test.ts +15 -15
- package/src/__tests__/notification-decision-strategy.test.ts +6 -6
- package/src/__tests__/notification-deep-link.test.ts +7 -7
- package/src/__tests__/notification-guardian-path.test.ts +2 -3
- package/src/__tests__/notification-telegram-adapter.test.ts +1 -1
- package/src/__tests__/notification-thread-candidates.test.ts +4 -4
- package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
- package/src/__tests__/playbook-execution.test.ts +0 -1
- package/src/__tests__/playbook-tools.test.ts +0 -1
- package/src/__tests__/profile-compiler.test.ts +0 -1
- package/src/__tests__/provider-managed-proxy-integration.test.ts +25 -0
- package/src/__tests__/qdrant-collection-migration.test.ts +223 -0
- package/src/__tests__/recording-handler.test.ts +30 -94
- package/src/__tests__/registry.test.ts +28 -35
- package/src/__tests__/relay-server.test.ts +0 -1
- package/src/__tests__/ride-shotgun-handler.test.ts +4 -20
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
- package/src/__tests__/runtime-events-sse.test.ts +0 -1
- package/src/__tests__/sandbox-diagnostics.test.ts +0 -1
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +30 -28
- package/src/__tests__/schedule-store.test.ts +441 -1
- package/src/__tests__/schedule-tools.test.ts +468 -7
- package/src/__tests__/scheduler-recurrence.test.ts +196 -23
- package/src/__tests__/scoped-approval-grants.test.ts +0 -1
- package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +6 -3
- package/src/__tests__/secret-response-routing.test.ts +4 -1
- package/src/__tests__/send-endpoint-busy.test.ts +14 -2
- package/src/__tests__/send-notification-tool.test.ts +0 -7
- package/src/__tests__/sequence-store.test.ts +0 -1
- package/src/__tests__/server-history-render.test.ts +1 -2
- package/src/__tests__/session-abort-tool-results.test.ts +0 -1
- package/src/__tests__/session-agent-loop.test.ts +46 -6
- package/src/__tests__/session-confirmation-signals.test.ts +0 -1
- package/src/__tests__/session-conflict-gate.test.ts +2 -6
- package/src/__tests__/session-error.test.ts +5 -14
- package/src/__tests__/session-init.benchmark.test.ts +3 -5
- package/src/__tests__/session-load-history-repair.test.ts +0 -1
- package/src/__tests__/session-media-retry.test.ts +12 -74
- package/src/__tests__/session-pre-run-repair.test.ts +0 -1
- package/src/__tests__/session-profile-injection.test.ts +2 -6
- package/src/__tests__/session-provider-retry-repair.test.ts +2 -6
- package/src/__tests__/session-queue.test.ts +94 -139
- package/src/__tests__/session-skill-tools.test.ts +115 -115
- package/src/__tests__/session-slash-known.test.ts +0 -1
- package/src/__tests__/session-slash-queue.test.ts +0 -1
- package/src/__tests__/session-slash-unknown.test.ts +0 -1
- package/src/__tests__/session-surfaces-task-progress.test.ts +34 -0
- package/src/__tests__/session-usage.test.ts +0 -1
- package/src/__tests__/session-workspace-cache-state.test.ts +2 -6
- package/src/__tests__/session-workspace-injection.test.ts +2 -6
- package/src/__tests__/session-workspace-tool-tracking.test.ts +2 -6
- package/src/__tests__/skill-feature-flags-integration.test.ts +180 -184
- package/src/__tests__/skill-feature-flags.test.ts +125 -18
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -2
- package/src/__tests__/skill-load-tool.test.ts +194 -2
- package/src/__tests__/skill-projection-feature-flag.test.ts +27 -16
- package/src/__tests__/skill-projection.benchmark.test.ts +15 -14
- package/src/__tests__/skills.test.ts +14 -53
- package/src/__tests__/slack-channel-config.test.ts +0 -1
- package/src/__tests__/slack-inbound-verification.test.ts +0 -1
- package/src/__tests__/slack-skill.test.ts +1 -1
- package/src/__tests__/subagent-tools.test.ts +2 -2
- package/src/__tests__/system-prompt.test.ts +4 -3
- package/src/__tests__/task-compiler.test.ts +0 -1
- package/src/__tests__/task-management-tools.test.ts +0 -1
- package/src/__tests__/task-memory-cleanup.test.ts +0 -1
- package/src/__tests__/task-runner.test.ts +0 -1
- package/src/__tests__/task-scheduler.test.ts +0 -1
- package/src/__tests__/terminal-tools.test.ts +0 -1
- package/src/__tests__/test-support/computer-use-skill-harness.ts +2 -4
- package/src/__tests__/thread-seed-composer.test.ts +5 -5
- package/src/__tests__/tool-approval-handler.test.ts +0 -1
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +8 -86
- package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
- package/src/__tests__/tool-notification-listener.test.ts +1 -1
- package/src/__tests__/tool-preview-lifecycle.test.ts +416 -0
- package/src/__tests__/trust-store.test.ts +80 -4
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -1
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
- package/src/__tests__/trusted-contact-verification.test.ts +0 -1
- package/src/__tests__/twilio-provider.test.ts +0 -1
- package/src/__tests__/twilio-routes.test.ts +0 -1
- package/src/__tests__/{request-file-tool.test.ts → ui-file-upload-surface.test.ts} +11 -72
- package/src/__tests__/update-bulletin.test.ts +0 -1
- package/src/__tests__/usage-cache-backfill-migration.test.ts +0 -1
- package/src/__tests__/usage-routes.test.ts +0 -1
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -4
- package/src/__tests__/voice-invite-redemption.test.ts +0 -1
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
- package/src/__tests__/voice-session-bridge.test.ts +9 -1
- package/src/__tests__/web-fetch.test.ts +57 -0
- package/src/__tests__/workspace-git-service.test.ts +5 -14
- package/src/__tests__/workspace-policy.test.ts +0 -1
- package/src/agent/loop.ts +22 -34
- package/src/bundler/bundle-signer.ts +4 -4
- package/src/calls/call-controller.ts +1 -1
- package/src/calls/relay-server.ts +1 -1
- package/src/calls/twilio-rest.ts +1 -1
- package/src/calls/voice-session-bridge.ts +3 -1
- package/src/cli/__tests__/notifications.test.ts +3 -4
- package/src/cli/commands/map.ts +2 -6
- package/src/cli/commands/mcp.ts +73 -15
- package/src/cli/commands/notifications.ts +4 -4
- package/src/cli/commands/sessions.ts +9 -1
- package/src/cli/commands/skills.ts +6 -10
- package/src/cli/http-client.ts +2 -3
- package/src/cli/main-screen.tsx +10 -10
- package/src/cli/program.ts +0 -4
- package/src/cli/reference.ts +0 -2
- package/src/cli.ts +15 -9
- package/src/config/__tests__/bundled-tool-registry-guard.test.ts +120 -0
- package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +11 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +6 -1
- package/src/config/bundled-skills/browser/SKILL.md +6 -1
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +5 -1
- package/src/config/bundled-skills/claude-code/SKILL.md +5 -1
- package/src/config/bundled-skills/computer-use/SKILL.md +6 -1
- package/src/config/bundled-skills/computer-use/TOOLS.json +6 -69
- package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +10 -1
- package/src/config/bundled-skills/contacts/SKILL.md +10 -1
- package/src/config/bundled-skills/contacts/TOOLS.json +35 -0
- package/src/config/bundled-skills/{messaging → contacts}/tools/google-contacts.ts +9 -2
- package/src/config/bundled-skills/document/SKILL.md +4 -1
- package/src/config/bundled-skills/doordash/SKILL.md +8 -1
- package/src/config/bundled-skills/doordash/lib/shared/platform.ts +4 -1
- package/src/config/bundled-skills/followups/SKILL.md +4 -1
- package/src/config/bundled-skills/gmail/SKILL.md +180 -0
- package/src/config/bundled-skills/gmail/TOOLS.json +506 -0
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +149 -0
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +110 -0
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-draft.ts +1 -1
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-filters.ts +1 -1
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-follow-up.ts +1 -1
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-forward.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +50 -0
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-outreach-scan.ts +8 -90
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-send-draft.ts +1 -1
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-sender-digest.ts +2 -2
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-trash.ts +1 -1
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-unsubscribe.ts +1 -1
- package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-vacation.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/shared.ts +47 -0
- package/src/config/bundled-skills/google-calendar/SKILL.md +5 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +5 -1
- package/src/config/bundled-skills/knowledge-graph/SKILL.md +4 -1
- package/src/config/bundled-skills/media-processing/SKILL.md +7 -13
- package/src/config/bundled-skills/media-processing/TOOLS.json +0 -22
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +12 -1
- package/src/config/bundled-skills/messaging/SKILL.md +23 -139
- package/src/config/bundled-skills/messaging/TOOLS.json +33 -1215
- package/src/config/bundled-skills/messaging/tools/gmail-mime-helpers.ts +42 -0
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +165 -2
- package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +1 -13
- package/src/config/bundled-skills/messaging/tools/shared.ts +81 -34
- package/src/config/bundled-skills/notifications/SKILL.md +5 -1
- package/src/config/bundled-skills/orchestration/SKILL.md +30 -0
- package/src/config/bundled-skills/orchestration/TOOLS.json +35 -0
- package/src/config/bundled-skills/{reminder/tools/reminder-create.ts → orchestration/tools/swarm-delegate.ts} +3 -3
- package/src/config/bundled-skills/phone-calls/SKILL.md +9 -1
- package/src/config/bundled-skills/playbooks/SKILL.md +4 -1
- package/src/config/bundled-skills/schedule/SKILL.md +70 -9
- package/src/config/bundled-skills/schedule/TOOLS.json +38 -6
- package/src/config/bundled-skills/screen-watch/SKILL.md +28 -0
- package/src/config/bundled-skills/screen-watch/TOOLS.json +35 -0
- package/src/config/bundled-skills/{reminder/tools/reminder-cancel.ts → screen-watch/tools/start-screen-watch.ts} +3 -3
- package/src/config/bundled-skills/sequences/SKILL.md +47 -0
- package/src/config/bundled-skills/sequences/TOOLS.json +340 -0
- package/src/config/bundled-skills/sequences/tools/sequence-update.ts +128 -0
- package/src/config/bundled-skills/sequences/tools/shared.ts +9 -0
- package/src/config/bundled-skills/settings/SKILL.md +12 -0
- package/src/config/bundled-skills/settings/TOOLS.json +112 -0
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +43 -0
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +52 -0
- package/src/config/bundled-skills/{computer-use/tools/computer-use-right-click.ts → settings/tools/set-avatar.ts} +2 -6
- package/src/{tools/system/voice-config.ts → config/bundled-skills/settings/tools/voice-config-update.ts} +59 -96
- package/src/config/bundled-skills/skill-management/SKILL.md +18 -0
- package/src/config/bundled-skills/skill-management/TOOLS.json +90 -0
- package/src/config/bundled-skills/{computer-use/tools/computer-use-double-click.ts → skill-management/tools/delete-managed.ts} +2 -6
- package/src/config/bundled-skills/skill-management/tools/scaffold-managed.ts +12 -0
- package/src/config/bundled-skills/slack/SKILL.md +5 -1
- package/src/config/bundled-skills/subagent/SKILL.md +4 -1
- package/src/config/bundled-skills/tasks/SKILL.md +5 -2
- package/src/config/bundled-skills/transcribe/SKILL.md +4 -1
- package/src/config/bundled-skills/watcher/SKILL.md +4 -1
- package/src/config/bundled-tool-registry.ts +118 -107
- package/src/config/env.ts +5 -2
- package/src/config/feature-flag-registry.json +25 -9
- package/src/config/loader.ts +10 -2
- package/src/config/schema.ts +19 -16
- package/src/config/schemas/inference.ts +12 -22
- package/src/config/schemas/memory-storage.ts +19 -1
- package/src/config/schemas/platform.ts +0 -16
- package/src/config/skill-state.ts +11 -8
- package/src/config/skills.ts +83 -32
- package/src/context/token-estimator.ts +11 -0
- package/src/context/window-manager.ts +180 -151
- package/src/daemon/computer-use-session.ts +11 -43
- package/src/daemon/daemon-control.ts +4 -1
- package/src/daemon/handlers/config-channels.ts +5 -9
- package/src/daemon/handlers/config-ingress.ts +0 -4
- package/src/daemon/handlers/config-model.ts +7 -13
- package/src/daemon/handlers/config-telegram.ts +4 -8
- package/src/daemon/handlers/config-voice.ts +2 -5
- package/src/daemon/handlers/dictation.ts +2 -12
- package/src/daemon/handlers/identity.ts +0 -105
- package/src/daemon/handlers/recording.ts +3 -23
- package/src/daemon/handlers/session-history.ts +1 -1
- package/src/daemon/handlers/sessions.ts +53 -72
- package/src/daemon/handlers/shared.ts +7 -28
- package/src/daemon/handlers/skills.ts +31 -27
- package/src/daemon/host-bash-proxy.ts +148 -0
- package/src/daemon/host-file-proxy.ts +135 -0
- package/src/daemon/lifecycle.ts +49 -24
- package/src/daemon/mcp-reload-service.ts +123 -0
- package/src/daemon/message-protocol.ts +6 -0
- package/src/daemon/message-types/browser.ts +1 -1
- package/src/daemon/message-types/computer-use.ts +1 -4
- package/src/daemon/message-types/guardian-actions.ts +1 -1
- package/src/daemon/message-types/host-bash.ts +18 -0
- package/src/daemon/message-types/host-file.ts +44 -0
- package/src/daemon/message-types/integrations.ts +1 -67
- package/src/daemon/message-types/messages.ts +15 -0
- package/src/daemon/message-types/schedules.ts +11 -27
- package/src/daemon/message-types/sessions.ts +2 -1
- package/src/daemon/message-types/settings.ts +1 -1
- package/src/daemon/message-types/shared.ts +1 -1
- package/src/daemon/ride-shotgun-handler.ts +2 -42
- package/src/daemon/server.ts +43 -10
- package/src/daemon/session-agent-loop-handlers.ts +48 -7
- package/src/daemon/session-agent-loop.ts +97 -66
- package/src/daemon/session-attachments.ts +1 -1
- package/src/daemon/session-error.ts +17 -16
- package/src/daemon/session-lifecycle.ts +20 -1
- package/src/daemon/session-media-retry.ts +1 -15
- package/src/daemon/session-messaging.ts +14 -6
- package/src/daemon/session-process.ts +36 -7
- package/src/daemon/session-queue-manager.ts +62 -103
- package/src/daemon/session-runtime-assembly.ts +27 -0
- package/src/daemon/session-skill-tools.ts +12 -11
- package/src/daemon/session-slash.ts +7 -0
- package/src/daemon/session-surfaces.ts +19 -97
- package/src/daemon/session-tool-setup.ts +146 -6
- package/src/daemon/session.ts +77 -13
- package/src/errors.ts +0 -2
- package/src/export/formatter.ts +6 -0
- package/src/mcp/mcp-oauth-provider.ts +1 -3
- package/src/media/avatar-router.ts +20 -28
- package/src/media/avatar-types.ts +7 -14
- package/src/media/managed-avatar-client.ts +70 -34
- package/src/memory/conversation-title-service.ts +1 -2
- package/src/memory/db-init.ts +16 -0
- package/src/memory/embedding-backend.ts +129 -27
- package/src/memory/embedding-gemini.test.ts +256 -0
- package/src/memory/embedding-gemini.ts +47 -13
- package/src/memory/embedding-local.ts +14 -2
- package/src/memory/embedding-ollama.ts +15 -2
- package/src/memory/embedding-openai.ts +15 -2
- package/src/memory/embedding-types.test.ts +116 -0
- package/src/memory/embedding-types.ts +61 -0
- package/src/memory/fingerprint.ts +1 -1
- package/src/memory/indexer.ts +25 -1
- package/src/memory/job-handlers/embedding.test.ts +258 -0
- package/src/memory/job-handlers/embedding.ts +81 -1
- package/src/memory/job-handlers/index-maintenance.ts +35 -1
- package/src/memory/job-handlers/media-processing.ts +11 -1
- package/src/memory/job-utils.ts +21 -6
- package/src/memory/jobs-store.ts +5 -1
- package/src/memory/jobs-worker.ts +8 -0
- package/src/memory/message-content.ts +66 -0
- package/src/memory/migrations/100-core-tables.ts +1 -31
- package/src/memory/migrations/104-core-indexes.ts +0 -11
- package/src/memory/migrations/145-drop-accounts-table.ts +19 -0
- package/src/memory/migrations/146-schedule-oneshot-routing.ts +94 -0
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +129 -0
- package/src/memory/migrations/148-drop-reminders-table.ts +18 -0
- package/src/memory/migrations/index.ts +4 -0
- package/src/memory/migrations/registry.ts +19 -0
- package/src/memory/qdrant-client.ts +158 -43
- package/src/memory/retriever.test.ts +0 -1
- package/src/memory/retriever.ts +12 -2
- package/src/memory/schema/infrastructure.ts +5 -29
- package/src/memory/search/formatting.ts +34 -9
- package/src/memory/search/semantic.ts +57 -2
- package/src/memory/search/types.ts +2 -1
- package/src/notifications/AGENTS.md +2 -2
- package/src/notifications/README.md +59 -58
- package/src/notifications/adapters/macos.ts +1 -1
- package/src/notifications/broadcaster.ts +5 -5
- package/src/notifications/copy-composer.ts +1 -1
- package/src/notifications/decision-engine.ts +2 -2
- package/src/notifications/destination-resolver.ts +2 -2
- package/src/notifications/emit-signal.ts +8 -8
- package/src/notifications/signal.ts +1 -1
- package/src/notifications/thread-seed-composer.ts +1 -1
- package/src/oauth/connect-orchestrator.ts +1 -1
- package/src/oauth/token-persistence.ts +1 -1
- package/src/permissions/checker.ts +12 -1
- package/src/permissions/defaults.ts +10 -14
- package/src/permissions/trust-store.ts +37 -0
- package/src/permissions/workspace-policy.ts +0 -1
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +11 -0
- package/src/prompts/computer-use-prompt.ts +1 -1
- package/src/prompts/system-prompt.ts +29 -30
- package/src/prompts/templates/SOUL.md +1 -2
- package/src/prompts/templates/UPDATES.md +16 -7
- package/src/providers/anthropic/client.ts +87 -33
- package/src/providers/gemini/client.ts +6 -0
- package/src/providers/managed-proxy/constants.ts +5 -0
- package/src/providers/openai/client.ts +15 -0
- package/src/providers/registry.ts +2 -2
- package/src/providers/types.ts +24 -2
- package/src/runtime/AGENTS.md +18 -0
- package/src/runtime/assistant-event-hub.ts +2 -3
- package/src/runtime/assistant-event.ts +4 -4
- package/src/runtime/auth/__tests__/context.test.ts +5 -5
- package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
- package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -2
- package/src/runtime/auth/__tests__/{ipc-auth-context.test.ts → local-auth-context.test.ts} +21 -21
- package/src/runtime/auth/__tests__/route-policy.test.ts +2 -2
- package/src/runtime/auth/__tests__/scopes.test.ts +7 -7
- package/src/runtime/auth/__tests__/subject.test.ts +8 -8
- package/src/runtime/auth/__tests__/token-service.test.ts +0 -1
- package/src/runtime/auth/route-policy.ts +8 -4
- package/src/runtime/auth/scopes.ts +1 -1
- package/src/runtime/auth/subject.ts +4 -4
- package/src/runtime/auth/token-service.ts +0 -23
- package/src/runtime/auth/types.ts +3 -3
- package/src/runtime/guardian-action-followup-executor.ts +1 -1
- package/src/runtime/guardian-action-grant-minter.ts +1 -1
- package/src/runtime/guardian-action-service.ts +3 -3
- package/src/runtime/http-server.ts +15 -2
- package/src/runtime/invite-service.ts +3 -3
- package/src/runtime/local-actor-identity.ts +17 -22
- package/src/runtime/pending-interactions.ts +21 -9
- package/src/runtime/routes/app-management-routes.ts +2 -3
- package/src/runtime/routes/approval-routes.ts +1 -3
- package/src/runtime/routes/btw-routes.ts +155 -0
- package/src/runtime/routes/computer-use-routes.ts +77 -31
- package/src/runtime/routes/conversation-routes.ts +230 -46
- package/src/runtime/routes/diagnostics-routes.ts +63 -29
- package/src/runtime/routes/documents-routes.ts +2 -2
- package/src/runtime/routes/global-search-routes.ts +1 -1
- package/src/runtime/routes/host-bash-routes.ts +83 -0
- package/src/runtime/routes/host-file-routes.ts +79 -0
- package/src/runtime/routes/integrations/slack/share.ts +1 -1
- package/src/runtime/routes/log-export-routes.ts +120 -0
- package/src/runtime/routes/mcp-routes.ts +20 -0
- package/src/runtime/routes/migration-routes.ts +3 -3
- package/src/runtime/routes/pairing-routes.ts +1 -1
- package/src/runtime/routes/recording-routes.ts +6 -4
- package/src/runtime/routes/schedule-routes.ts +31 -5
- package/src/runtime/routes/session-management-routes.ts +2 -6
- package/src/runtime/routes/session-query-routes.ts +18 -15
- package/src/runtime/routes/settings-routes.ts +7 -261
- package/src/runtime/routes/skills-routes.ts +7 -6
- package/src/runtime/routes/subagents-routes.ts +4 -10
- package/src/runtime/routes/surface-action-routes.ts +3 -14
- package/src/runtime/routes/surface-content-routes.ts +22 -5
- package/src/runtime/routes/work-items-routes.ts +21 -25
- package/src/runtime/routes/workspace-routes.test.ts +3 -3
- package/src/runtime/routes/workspace-utils.ts +1 -1
- package/src/runtime/telegram-streaming-delivery.ts +3 -0
- package/src/runtime/verification-outbound-actions.ts +2 -2
- package/src/schedule/integration-status.ts +0 -6
- package/src/schedule/schedule-store.ts +234 -43
- package/src/schedule/scheduler.ts +73 -74
- package/src/security/oauth2.ts +1 -1
- package/src/sequence/store.ts +12 -2
- package/src/skills/frontmatter.ts +19 -77
- package/src/skills/managed-store.ts +11 -2
- package/src/subagent/manager.ts +5 -3
- package/src/tasks/ephemeral-permissions.ts +3 -5
- package/src/tools/AGENTS.md +0 -1
- package/src/tools/browser/browser-manager.ts +17 -11
- package/src/tools/browser/jit-auth.ts +4 -1
- package/src/tools/claude-code/claude-code.ts +1 -1
- package/src/tools/computer-use/definitions.ts +48 -60
- package/src/tools/document/document-tool.ts +6 -6
- package/src/tools/filesystem/edit.ts +2 -1
- package/src/tools/filesystem/read.ts +20 -2
- package/src/tools/filesystem/write.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +17 -1
- package/src/tools/host-filesystem/read.ts +16 -1
- package/src/tools/host-filesystem/write.ts +15 -1
- package/src/tools/host-terminal/host-shell.ts +24 -0
- package/src/tools/memory/definitions.ts +45 -81
- package/src/tools/memory/handlers.test.ts +0 -1
- package/src/tools/memory/handlers.ts +1 -1
- package/src/tools/memory/register.ts +26 -60
- package/src/tools/network/script-proxy/session-manager.ts +6 -8
- package/src/tools/network/web-fetch.ts +7 -1
- package/src/tools/network/web-search.ts +2 -1
- package/src/tools/registry.ts +23 -0
- package/src/tools/schedule/create.ts +113 -5
- package/src/tools/schedule/list.ts +57 -15
- package/src/tools/schedule/update.ts +73 -3
- package/src/tools/shared/filesystem/image-read.ts +192 -0
- package/src/tools/side-effects.ts +1 -7
- package/src/tools/skills/delete-managed.ts +27 -64
- package/src/tools/skills/execute.ts +54 -0
- package/src/tools/skills/load.ts +127 -5
- package/src/tools/skills/scaffold-managed.ts +93 -172
- package/src/tools/subagent/message.ts +0 -7
- package/src/tools/subagent/spawn.ts +1 -1
- package/src/tools/swarm/delegate.ts +0 -3
- package/src/tools/system/avatar-generator.ts +13 -19
- package/src/tools/system/request-permission.ts +2 -1
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/tool-manifest.ts +41 -47
- package/src/tools/types.ts +6 -2
- package/src/tools/ui-surface/definitions.ts +0 -55
- package/src/util/errors.ts +0 -10
- package/src/workspace/git-service.ts +0 -2
- package/src/__tests__/account-registry.test.ts +0 -258
- package/src/__tests__/email-classifier.test.ts +0 -25
- package/src/__tests__/gmail-integration.test.ts +0 -97
- package/src/__tests__/handle-user-message-secret-resume.test.ts +0 -172
- package/src/__tests__/managed-twitter-guardrails.test.ts +0 -357
- package/src/__tests__/recording-intent-fallback.test.ts +0 -199
- package/src/__tests__/recording-intent.test.ts +0 -985
- package/src/__tests__/recording-state-machine.test.ts +0 -1574
- package/src/__tests__/reminder-store.test.ts +0 -350
- package/src/__tests__/reminder.test.ts +0 -337
- package/src/__tests__/scan-result-store.test.ts +0 -121
- package/src/__tests__/twitter-platform-proxy-client.test.ts +0 -475
- package/src/__tests__/view-image-tool.test.ts +0 -241
- package/src/cli/commands/amazon/cart.ts +0 -513
- package/src/cli/commands/amazon/checkout.ts +0 -394
- package/src/cli/commands/amazon/client.ts +0 -513
- package/src/cli/commands/amazon/index.ts +0 -885
- package/src/cli/commands/amazon/product-details.ts +0 -145
- package/src/cli/commands/amazon/request-extractor.ts +0 -187
- package/src/cli/commands/amazon/search.ts +0 -76
- package/src/cli/commands/amazon/session.ts +0 -108
- package/src/cli/commands/twitter/__tests__/cli-read-routing.test.ts +0 -345
- package/src/cli/commands/twitter/__tests__/cli-routing.test.ts +0 -252
- package/src/cli/commands/twitter/__tests__/oauth-client.test.ts +0 -151
- package/src/cli/commands/twitter/index.ts +0 -420
- package/src/cli/commands/twitter/oauth-client.ts +0 -60
- package/src/cli/commands/twitter/router.ts +0 -351
- package/src/cli/commands/twitter/types.ts +0 -30
- package/src/config/bundled-skills/agentmail/SKILL.md +0 -132
- package/src/config/bundled-skills/agentmail/icon.svg +0 -21
- package/src/config/bundled-skills/amazon/SKILL.md +0 -136
- package/src/config/bundled-skills/amazon/icon.svg +0 -13
- package/src/config/bundled-skills/api-mapping/SKILL.md +0 -78
- package/src/config/bundled-skills/api-mapping/icon.svg +0 -18
- package/src/config/bundled-skills/cli-discover/SKILL.md +0 -68
- package/src/config/bundled-skills/deploy-fullstack-vercel/SKILL.md +0 -179
- package/src/config/bundled-skills/document-writer/SKILL.md +0 -195
- package/src/config/bundled-skills/elevenlabs-voice/SKILL.md +0 -140
- package/src/config/bundled-skills/email-setup/SKILL.md +0 -68
- package/src/config/bundled-skills/frontend-design/SKILL.md +0 -44
- package/src/config/bundled-skills/frontend-design/icon.svg +0 -16
- package/src/config/bundled-skills/google-oauth-setup/SKILL.md +0 -452
- package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +0 -203
- package/src/config/bundled-skills/influencer/SKILL.md +0 -144
- package/src/config/bundled-skills/influencer/scripts/client.ts +0 -1269
- package/src/config/bundled-skills/influencer/scripts/influencer.ts +0 -267
- package/src/config/bundled-skills/macos-automation/SKILL.md +0 -65
- package/src/config/bundled-skills/macos-automation/icon.svg +0 -12
- package/src/config/bundled-skills/mcp-setup/SKILL.md +0 -75
- package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +0 -184
- package/src/config/bundled-skills/messaging/tools/gmail-archive-by-query.ts +0 -80
- package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +0 -29
- package/src/config/bundled-skills/messaging/tools/gmail-batch-archive.ts +0 -56
- package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +0 -34
- package/src/config/bundled-skills/messaging/tools/gmail-download-attachment.ts +0 -47
- package/src/config/bundled-skills/messaging/tools/gmail-label.ts +0 -31
- package/src/config/bundled-skills/messaging/tools/gmail-list-attachments.ts +0 -67
- package/src/config/bundled-skills/messaging/tools/gmail-send-with-attachments.ts +0 -97
- package/src/config/bundled-skills/messaging/tools/gmail-summarize-thread.ts +0 -87
- package/src/config/bundled-skills/messaging/tools/gmail-triage.ts +0 -135
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +0 -24
- package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +0 -201
- package/src/config/bundled-skills/messaging/tools/send-notification.ts +0 -1
- package/src/config/bundled-skills/messaging/tools/sequence-cancel.ts +0 -27
- package/src/config/bundled-skills/messaging/tools/sequence-pause.ts +0 -48
- package/src/config/bundled-skills/messaging/tools/sequence-resume.ts +0 -27
- package/src/config/bundled-skills/messaging/tools/sequence-update.ts +0 -56
- package/src/config/bundled-skills/notion/SKILL.md +0 -240
- package/src/config/bundled-skills/notion-oauth-setup/SKILL.md +0 -126
- package/src/config/bundled-skills/oauth-setup/SKILL.md +0 -143
- package/src/config/bundled-skills/public-ingress/SKILL.md +0 -258
- package/src/config/bundled-skills/reminder/SKILL.md +0 -79
- package/src/config/bundled-skills/reminder/TOOLS.json +0 -89
- package/src/config/bundled-skills/reminder/tools/reminder-list.ts +0 -12
- package/src/config/bundled-skills/restaurant-reservation/SKILL.md +0 -141
- package/src/config/bundled-skills/screen-recording/SKILL.md +0 -148
- package/src/config/bundled-skills/self-upgrade/SKILL.md +0 -69
- package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -78
- package/src/config/bundled-skills/slack-app-setup/SKILL.md +0 -178
- package/src/config/bundled-skills/slack-digest-setup/SKILL.md +0 -163
- package/src/config/bundled-skills/slack-oauth-setup/SKILL.md +0 -157
- package/src/config/bundled-skills/start-the-day/SKILL.md +0 -70
- package/src/config/bundled-skills/start-the-day/icon.svg +0 -13
- package/src/config/bundled-skills/telegram-setup/SKILL.md +0 -105
- package/src/config/bundled-skills/time-based-actions/SKILL.md +0 -142
- package/src/config/bundled-skills/twilio-setup/SKILL.md +0 -232
- package/src/config/bundled-skills/twitter/SKILL.md +0 -206
- package/src/config/bundled-skills/twitter/icon.svg +0 -14
- package/src/config/bundled-skills/typescript-eval/SKILL.md +0 -60
- package/src/config/bundled-skills/vercel-token-setup/SKILL.md +0 -214
- package/src/config/bundled-skills/voice-setup/SKILL.md +0 -131
- package/src/config/bundled-skills/voice-setup/icon.svg +0 -20
- package/src/daemon/handlers/pairing.ts +0 -119
- package/src/daemon/handlers/session-user-message.ts +0 -961
- package/src/daemon/recording-executor.ts +0 -180
- package/src/daemon/recording-intent-fallback.ts +0 -162
- package/src/daemon/recording-intent.ts +0 -493
- package/src/memory/account-store.ts +0 -117
- package/src/messaging/activity-analyzer.ts +0 -76
- package/src/messaging/email-classifier.ts +0 -208
- package/src/messaging/index.ts +0 -2
- package/src/messaging/outreach-classifier.ts +0 -185
- package/src/messaging/thread-summarizer.ts +0 -346
- package/src/messaging/types.ts +0 -17
- package/src/tools/browser/x-auto-navigate.ts +0 -254
- package/src/tools/credentials/account-registry.ts +0 -144
- package/src/tools/filesystem/view-image.ts +0 -244
- package/src/tools/reminder/reminder-store.ts +0 -194
- package/src/tools/reminder/reminder.ts +0 -158
- package/src/tools/system/navigate-settings.ts +0 -74
- package/src/tools/system/open-system-settings.ts +0 -85
- package/src/tools/system/version.ts +0 -54
- package/src/twitter/platform-proxy-client.ts +0 -408
- /package/src/config/bundled-skills/{messaging → gmail}/tools/scan-result-store.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-analytics.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-create.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-delete.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-enroll.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-enrollment-list.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-get.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-import.ts +0 -0
- /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-list.ts +0 -0
|
@@ -1,493 +0,0 @@
|
|
|
1
|
-
// Recording intent resolution for standalone screen recording routing.
|
|
2
|
-
// Exports `resolveRecordingIntent` as the single public entry point for
|
|
3
|
-
// text-based intent detection. Handlers use this (or structured
|
|
4
|
-
// `commandIntent` payloads) to intercept recording-related prompts
|
|
5
|
-
// before they reach the classifier or create a CU session.
|
|
6
|
-
//
|
|
7
|
-
// Internal helpers (detect/strip/classify) are kept as private utilities
|
|
8
|
-
// consumed only by `resolveRecordingIntent`.
|
|
9
|
-
|
|
10
|
-
export type RecordingIntentResult =
|
|
11
|
-
| { kind: "none" }
|
|
12
|
-
| { kind: "start_only" }
|
|
13
|
-
| { kind: "stop_only" }
|
|
14
|
-
| { kind: "start_with_remainder"; remainder: string }
|
|
15
|
-
| { kind: "stop_with_remainder"; remainder: string }
|
|
16
|
-
| { kind: "start_and_stop_only" }
|
|
17
|
-
| { kind: "start_and_stop_with_remainder"; remainder: string }
|
|
18
|
-
| { kind: "restart_only" }
|
|
19
|
-
| { kind: "restart_with_remainder"; remainder: string }
|
|
20
|
-
| { kind: "pause_only" }
|
|
21
|
-
| { kind: "resume_only" };
|
|
22
|
-
|
|
23
|
-
// ─── Start recording patterns ────────────────────────────────────────────────
|
|
24
|
-
|
|
25
|
-
const START_RECORDING_PATTERNS: RegExp[] = [
|
|
26
|
-
/\brecord\s+(my\s+)?screen\b/i,
|
|
27
|
-
/\brecord\s+the\s+screen\b/i,
|
|
28
|
-
/\bscreen\s+record(ing)?\b/i,
|
|
29
|
-
/\bstart\s+recording\b/i,
|
|
30
|
-
/\bbegin\s+recording\b/i,
|
|
31
|
-
/\bcapture\s+(my\s+)?(screen|display)\b/i,
|
|
32
|
-
/\bmake\s+a\s+(screen\s+)?recording\b/i,
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
// ─── Stop recording patterns ────────────────────────────────────────────────
|
|
36
|
-
|
|
37
|
-
const STOP_RECORDING_PATTERNS: RegExp[] = [
|
|
38
|
-
/\bstop\s+(the\s+)?recording\b/i,
|
|
39
|
-
/\bend\s+(the\s+)?recording\b/i,
|
|
40
|
-
/\bfinish\s+(the\s+)?recording\b/i,
|
|
41
|
-
/\bhalt\s+(the\s+)?recording\b/i,
|
|
42
|
-
];
|
|
43
|
-
|
|
44
|
-
// ─── Restart recording patterns (compound: stop + start a new one) ──────────
|
|
45
|
-
|
|
46
|
-
const RESTART_RECORDING_PATTERNS: RegExp[] = [
|
|
47
|
-
/\brestart\s+(the\s+)?recording\b/i,
|
|
48
|
-
/\bredo\s+(the\s+)?recording\b/i,
|
|
49
|
-
/\bstop\s+(the\s+)?recording\s+and\s+(start|begin)\s+(a\s+)?(new|fresh|another)\s+(recording|one)\b/i,
|
|
50
|
-
/\bstop\s+(the\s+)?recording\s+and\s+(start|begin)\s+(a\s+)?(new|fresh|another)[.!?\s]*$/i,
|
|
51
|
-
/\bstop\s+and\s+restart\s+(the\s+)?recording\b/i,
|
|
52
|
-
/\bstop\s+recording\s+and\s+start\s+(a\s+)?(new|another|fresh)\s+(recording|one)\b/i,
|
|
53
|
-
/\bstop\s+recording\s+and\s+start\s+(a\s+)?(new|another|fresh)[.!?\s]*$/i,
|
|
54
|
-
];
|
|
55
|
-
|
|
56
|
-
// ─── Pause/resume recording patterns ────────────────────────────────────────
|
|
57
|
-
|
|
58
|
-
const PAUSE_RECORDING_PATTERNS: RegExp[] = [/\bpause\s+(the\s+)?recording\b/i];
|
|
59
|
-
|
|
60
|
-
const RESUME_RECORDING_PATTERNS: RegExp[] = [
|
|
61
|
-
/\bresume\s+(the\s+)?recording\b/i,
|
|
62
|
-
/\bunpause\s+(the\s+)?recording\b/i,
|
|
63
|
-
];
|
|
64
|
-
|
|
65
|
-
// ─── Stop-recording clause removal for mixed-intent prompts ─────────────────
|
|
66
|
-
|
|
67
|
-
const STOP_RECORDING_CLAUSE_PATTERNS: RegExp[] = [
|
|
68
|
-
/\b(and\s+)?(also\s+)?stop\s+(the\s+)?recording\b/i,
|
|
69
|
-
/\b(and\s+)?(also\s+)?end\s+(the\s+)?recording\b/i,
|
|
70
|
-
/\b(and\s+)?(also\s+)?finish\s+(the\s+)?recording\b/i,
|
|
71
|
-
/\b(and\s+)?(also\s+)?halt\s+(the\s+)?recording\b/i,
|
|
72
|
-
];
|
|
73
|
-
|
|
74
|
-
// ─── Clause removal for mixed-intent prompts ─────────────────────────────────
|
|
75
|
-
|
|
76
|
-
const RECORDING_CLAUSE_PATTERNS: RegExp[] = [
|
|
77
|
-
/\b(and\s+)?(also\s+)?record\s+(my\s+|the\s+)?screen\b/i,
|
|
78
|
-
/\b(and\s+)?(also\s+)?screen\s+record(ing)?\b/i,
|
|
79
|
-
/\b(and\s+)?(also\s+)?start\s+recording\b/i,
|
|
80
|
-
/\b(and\s+)?(also\s+)?begin\s+recording\b/i,
|
|
81
|
-
/\b(and\s+)?(also\s+)?capture\s+(my\s+)?(screen|display)\b/i,
|
|
82
|
-
/\b(and\s+)?(also\s+)?make\s+a\s+(screen\s+)?recording\b/i,
|
|
83
|
-
/\bwhile\s+(you\s+)?record(ing)?\s+(my\s+|the\s+)?screen\b/i,
|
|
84
|
-
/\brecord\s+(my\s+|the\s+)?screen\s+while\b/i,
|
|
85
|
-
];
|
|
86
|
-
|
|
87
|
-
// ─── Restart clause removal ─────────────────────────────────────────────────
|
|
88
|
-
|
|
89
|
-
const RESTART_RECORDING_CLAUSE_PATTERNS: RegExp[] = [
|
|
90
|
-
// Longer compound patterns first — avoids partial matches by shorter patterns
|
|
91
|
-
/\bstop\s+(the\s+)?recording\s+and\s+(start|begin)\s+(a\s+)?(new|fresh|another)\s+(recording|one)\b/i,
|
|
92
|
-
/\bstop\s+(the\s+)?recording\s+and\s+(start|begin)\s+(a\s+)?(new|fresh|another)[.!?\s]*$/i,
|
|
93
|
-
/\bstop\s+and\s+restart\s+(the\s+)?recording\b/i,
|
|
94
|
-
/\bstop\s+recording\s+and\s+start\s+(a\s+)?(new|another|fresh)\s+(recording|one)\b/i,
|
|
95
|
-
/\bstop\s+recording\s+and\s+start\s+(a\s+)?(new|another|fresh)[.!?\s]*$/i,
|
|
96
|
-
/\b(and\s+)?(also\s+)?restart\s+(the\s+)?recording\b/i,
|
|
97
|
-
/\b(and\s+)?(also\s+)?redo\s+(the\s+)?recording\b/i,
|
|
98
|
-
];
|
|
99
|
-
|
|
100
|
-
// ─── Pause/resume clause removal ────────────────────────────────────────────
|
|
101
|
-
|
|
102
|
-
const PAUSE_RECORDING_CLAUSE_PATTERNS: RegExp[] = [
|
|
103
|
-
/\b(and\s+)?(also\s+)?pause\s+(the\s+)?recording\b/i,
|
|
104
|
-
];
|
|
105
|
-
|
|
106
|
-
const RESUME_RECORDING_CLAUSE_PATTERNS: RegExp[] = [
|
|
107
|
-
/\b(and\s+)?(also\s+)?resume\s+(the\s+)?recording\b/i,
|
|
108
|
-
/\b(and\s+)?(also\s+)?unpause\s+(the\s+)?recording\b/i,
|
|
109
|
-
];
|
|
110
|
-
|
|
111
|
-
/** Common polite/filler words stripped before checking intent-only status. */
|
|
112
|
-
const FILLER_PATTERN =
|
|
113
|
-
/\b(please|pls|plz|can\s+you|could\s+you|would\s+you|now|right\s+now|thanks|thank\s+you|thx|ty|for\s+me|ok(ay)?|hey|hi|just)\b/gi;
|
|
114
|
-
|
|
115
|
-
// ─── Internal helpers ────────────────────────────────────────────────────────
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Returns true if the user's message includes any recording-related phrases.
|
|
119
|
-
* Does not distinguish between recording-only and mixed-intent prompts.
|
|
120
|
-
*/
|
|
121
|
-
function detectRecordingIntent(taskText: string): boolean {
|
|
122
|
-
return START_RECORDING_PATTERNS.some((p) => p.test(taskText));
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Returns true if the prompt is purely about recording with no additional task.
|
|
127
|
-
* "record my screen" -> true
|
|
128
|
-
* "record my screen while I work" -> false (has CU task component)
|
|
129
|
-
* "open Chrome and record my screen" -> false (has CU task component)
|
|
130
|
-
*/
|
|
131
|
-
function isRecordingOnly(taskText: string): boolean {
|
|
132
|
-
if (!detectRecordingIntent(taskText)) return false;
|
|
133
|
-
|
|
134
|
-
// Strip the recording clause and check if anything substantive remains
|
|
135
|
-
const stripped = stripRecordingIntent(taskText);
|
|
136
|
-
// Also remove common polite/filler words that don't change the intent
|
|
137
|
-
const withoutFillers = stripped.replace(FILLER_PATTERN, "");
|
|
138
|
-
// If after removing the recording clause and fillers, only whitespace/punctuation
|
|
139
|
-
// remains, this is a recording-only prompt.
|
|
140
|
-
return withoutFillers.replace(/[.,;!?\s]+/g, "").length === 0;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Returns true if the user wants to stop recording.
|
|
145
|
-
* Requires explicit "stop/end/finish/halt recording" phrasing --
|
|
146
|
-
* bare "stop", "end it", or "quit" are too ambiguous and will not match.
|
|
147
|
-
*/
|
|
148
|
-
function detectStopRecordingIntent(taskText: string): boolean {
|
|
149
|
-
return STOP_RECORDING_PATTERNS.some((p) => p.test(taskText));
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/** Returns true if any restart compound pattern matches. */
|
|
153
|
-
function detectRestartRecordingIntent(taskText: string): boolean {
|
|
154
|
-
return RESTART_RECORDING_PATTERNS.some((p) => p.test(taskText));
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/** Returns true if any pause pattern matches. */
|
|
158
|
-
function detectPauseRecordingIntent(taskText: string): boolean {
|
|
159
|
-
return PAUSE_RECORDING_PATTERNS.some((p) => p.test(taskText));
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/** Returns true if any resume pattern matches. */
|
|
163
|
-
function detectResumeRecordingIntent(taskText: string): boolean {
|
|
164
|
-
return RESUME_RECORDING_PATTERNS.some((p) => p.test(taskText));
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Removes recording-related clauses from a task, returning the cleaned text.
|
|
169
|
-
* Used when a recording intent is embedded in a broader CU task so the
|
|
170
|
-
* recording portion can be handled separately while the task continues.
|
|
171
|
-
*/
|
|
172
|
-
function stripRecordingIntent(taskText: string): string {
|
|
173
|
-
let result = taskText;
|
|
174
|
-
for (const pattern of RECORDING_CLAUSE_PATTERNS) {
|
|
175
|
-
result = result.replace(pattern, "");
|
|
176
|
-
}
|
|
177
|
-
// Clean up any leftover double spaces or leading/trailing whitespace
|
|
178
|
-
return result.replace(/\s{2,}/g, " ").trim();
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Removes stop-recording clauses from a message, returning the cleaned text.
|
|
183
|
-
* Analogous to stripRecordingIntent but for stop-recording phrases.
|
|
184
|
-
*/
|
|
185
|
-
function stripStopRecordingIntent(taskText: string): string {
|
|
186
|
-
let result = taskText;
|
|
187
|
-
for (const pattern of STOP_RECORDING_CLAUSE_PATTERNS) {
|
|
188
|
-
result = result.replace(pattern, "");
|
|
189
|
-
}
|
|
190
|
-
return result.replace(/\s{2,}/g, " ").trim();
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/** Removes restart-recording clauses from text. */
|
|
194
|
-
function stripRestartRecordingIntent(taskText: string): string {
|
|
195
|
-
let result = taskText;
|
|
196
|
-
for (const pattern of RESTART_RECORDING_CLAUSE_PATTERNS) {
|
|
197
|
-
result = result.replace(pattern, "");
|
|
198
|
-
}
|
|
199
|
-
return result.replace(/\s{2,}/g, " ").trim();
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/** Removes pause-recording clauses from text. */
|
|
203
|
-
function stripPauseRecordingIntent(taskText: string): string {
|
|
204
|
-
let result = taskText;
|
|
205
|
-
for (const pattern of PAUSE_RECORDING_CLAUSE_PATTERNS) {
|
|
206
|
-
result = result.replace(pattern, "");
|
|
207
|
-
}
|
|
208
|
-
return result.replace(/\s{2,}/g, " ").trim();
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/** Removes resume-recording clauses from text. */
|
|
212
|
-
function stripResumeRecordingIntent(taskText: string): string {
|
|
213
|
-
let result = taskText;
|
|
214
|
-
for (const pattern of RESUME_RECORDING_CLAUSE_PATTERNS) {
|
|
215
|
-
result = result.replace(pattern, "");
|
|
216
|
-
}
|
|
217
|
-
return result.replace(/\s{2,}/g, " ").trim();
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Returns true if the prompt is purely about stopping recording with no
|
|
222
|
-
* additional task. Analogous to isRecordingOnly but for stop-recording.
|
|
223
|
-
* "stop recording" -> true
|
|
224
|
-
* "how do I stop recording?" -> false (has additional context)
|
|
225
|
-
* "stop recording and close the browser" -> false (has CU task component)
|
|
226
|
-
*/
|
|
227
|
-
function isStopRecordingOnly(taskText: string): boolean {
|
|
228
|
-
if (!detectStopRecordingIntent(taskText)) return false;
|
|
229
|
-
|
|
230
|
-
const stripped = stripStopRecordingIntent(taskText);
|
|
231
|
-
// Also remove common polite/filler words that don't change the intent
|
|
232
|
-
const withoutFillers = stripped.replace(FILLER_PATTERN, "");
|
|
233
|
-
return withoutFillers.replace(/[.,;!?\s]+/g, "").length === 0;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/** Returns true if the text is purely a restart command (no additional task). */
|
|
237
|
-
function isRestartRecordingOnly(taskText: string): boolean {
|
|
238
|
-
if (!detectRestartRecordingIntent(taskText)) return false;
|
|
239
|
-
const stripped = stripRestartRecordingIntent(taskText);
|
|
240
|
-
const withoutFillers = stripped.replace(FILLER_PATTERN, "");
|
|
241
|
-
return withoutFillers.replace(/[.,;!?\s]+/g, "").length === 0;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/** Returns true if the text is purely a pause command (no additional task). */
|
|
245
|
-
function isPauseRecordingOnly(taskText: string): boolean {
|
|
246
|
-
if (!detectPauseRecordingIntent(taskText)) return false;
|
|
247
|
-
const stripped = stripPauseRecordingIntent(taskText);
|
|
248
|
-
const withoutFillers = stripped.replace(FILLER_PATTERN, "");
|
|
249
|
-
return withoutFillers.replace(/[.,;!?\s]+/g, "").length === 0;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/** Returns true if the text is purely a resume command (no additional task). */
|
|
253
|
-
function isResumeRecordingOnly(taskText: string): boolean {
|
|
254
|
-
if (!detectResumeRecordingIntent(taskText)) return false;
|
|
255
|
-
const stripped = stripResumeRecordingIntent(taskText);
|
|
256
|
-
const withoutFillers = stripped.replace(FILLER_PATTERN, "");
|
|
257
|
-
return withoutFillers.replace(/[.,;!?\s]+/g, "").length === 0;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// ─── Dynamic name normalization ─────────────────────────────────────────────
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Strips dynamic assistant name aliases from the beginning of text.
|
|
264
|
-
* Handles patterns like "Nova, ...", "Nova ...", "hey Nova, ...", "hey, Nova, ..." (case-insensitive).
|
|
265
|
-
* Periods in names are optional to handle natural omission (e.g., "Jr" vs "Jr.").
|
|
266
|
-
*/
|
|
267
|
-
export function stripDynamicNames(
|
|
268
|
-
text: string,
|
|
269
|
-
dynamicNames: string[],
|
|
270
|
-
): string {
|
|
271
|
-
let result = text;
|
|
272
|
-
for (const name of dynamicNames) {
|
|
273
|
-
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
274
|
-
// Make escaped periods optional — users often omit dots (e.g., "Jr" vs "Jr.")
|
|
275
|
-
const withOptionalDots = escaped.replace(/\\\./g, "\\.?");
|
|
276
|
-
// "hey <name>, ..." / "hey <name> ..." / "hey, <name>, ..."
|
|
277
|
-
// Lookahead ensures the name is a whole token (not a prefix of a longer word).
|
|
278
|
-
const heyPattern = new RegExp(
|
|
279
|
-
`^hey[,\\s]+${withOptionalDots}(?=[,:\\s]|$)[,:]?\\s*`,
|
|
280
|
-
"i",
|
|
281
|
-
);
|
|
282
|
-
// "<name>, ..." or "<name> ..."
|
|
283
|
-
const namePattern = new RegExp(
|
|
284
|
-
`^${withOptionalDots}(?=[,:\\s]|$)[,:]?\\s*`,
|
|
285
|
-
"i",
|
|
286
|
-
);
|
|
287
|
-
result = result.replace(heyPattern, "");
|
|
288
|
-
result = result.replace(namePattern, "");
|
|
289
|
-
}
|
|
290
|
-
return result.trim();
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Returns true if the text contains substantive content beyond fillers,
|
|
295
|
-
* punctuation, and dynamic assistant names. Used to determine whether
|
|
296
|
-
* remaining text after stripping recording clauses needs further processing.
|
|
297
|
-
*/
|
|
298
|
-
function hasSubstantiveContent(text: string, dynamicNames?: string[]): boolean {
|
|
299
|
-
let cleaned = text;
|
|
300
|
-
if (dynamicNames && dynamicNames.length > 0) {
|
|
301
|
-
cleaned = stripDynamicNames(cleaned, dynamicNames);
|
|
302
|
-
}
|
|
303
|
-
cleaned = cleaned.replace(FILLER_PATTERN, "");
|
|
304
|
-
return cleaned.replace(/[.,;!?\s]+/g, "").length > 0;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// ─── Interrogative detection ────────────────────────────────────────────────
|
|
308
|
-
|
|
309
|
-
/** WH-question starters — these almost always indicate a genuine question,
|
|
310
|
-
* not an imperative command. Prevents "how do I stop recording?" from
|
|
311
|
-
* triggering recording side effects in the mixed handler. */
|
|
312
|
-
const WH_INTERROGATIVE = /^\s*(how|what|why|when|where|who|which)\b/i;
|
|
313
|
-
|
|
314
|
-
/**
|
|
315
|
-
* Indirect informational patterns that indicate the user is asking *about*
|
|
316
|
-
* recording rather than commanding a recording action. These catch prompts
|
|
317
|
-
* where the WH-word is buried after polite filler or an informational verb:
|
|
318
|
-
*
|
|
319
|
-
* - "can you tell me how to stop recording?"
|
|
320
|
-
* - "explain how to stop the recording"
|
|
321
|
-
* - "is there a way to stop recording?"
|
|
322
|
-
* - "I'd like to know how to pause the recording"
|
|
323
|
-
* - "do you know how to start recording?"
|
|
324
|
-
*
|
|
325
|
-
* Critical: these must NOT match polite imperatives like "can you stop
|
|
326
|
-
* recording?" — the key distinction is the intermediary informational
|
|
327
|
-
* verb/phrase (tell/explain/describe/show + how, "is there a way", etc.).
|
|
328
|
-
*/
|
|
329
|
-
const INDIRECT_INFORMATIONAL_PATTERNS: RegExp[] = [
|
|
330
|
-
// "tell me how...", "can you explain how...", "show me how..."
|
|
331
|
-
/^\s*(can\s+you\s+|could\s+you\s+|would\s+you\s+)?(tell|explain|describe|show)\s+(me\s+)?how\b/i,
|
|
332
|
-
// "is there a way to...", "are there any ways to..."
|
|
333
|
-
/^\s*(is\s+there|are\s+there)\s+(a\s+|any\s+)?(ways?|methods?|options?|means)\s+to\b/i,
|
|
334
|
-
// "I'd like to know...", "I want to know..."
|
|
335
|
-
/^\s*(i('d|\s+would)\s+like\s+to\s+know|i\s+want\s+to\s+know)\b/i,
|
|
336
|
-
// "do you know how to...", "can I learn how to..."
|
|
337
|
-
/^\s*(do\s+you\s+know\s+how|can\s+i\s+learn(\s+how)?)\s+to\b/i,
|
|
338
|
-
// Bare informational verbs at start: "explain how...", "tell me how..."
|
|
339
|
-
/^\s*(explain|describe)\s+(to\s+me\s+)?how\b/i,
|
|
340
|
-
// "tell me about..." (informational, not imperative)
|
|
341
|
-
/^\s*(tell|explain|describe|show)\s+(me\s+)?(about\s+)?(how|what|why|when|where)\b/i,
|
|
342
|
-
];
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* Returns true if the text appears to be a question about recording rather
|
|
346
|
-
* than an imperative command that includes recording.
|
|
347
|
-
*
|
|
348
|
-
* "how do I stop recording?" → true (question — don't trigger side effects)
|
|
349
|
-
* "can you tell me how to stop recording?" → true (informational — don't trigger)
|
|
350
|
-
* "explain how to stop the recording" → true (informational — don't trigger)
|
|
351
|
-
* "is there a way to stop recording?" → true (capability question — don't trigger)
|
|
352
|
-
* "open Chrome and record my screen" → false (command — trigger recording)
|
|
353
|
-
* "can you record my screen?" → false (polite imperative — trigger recording)
|
|
354
|
-
* "can you stop recording?" → false (polite imperative — trigger stop)
|
|
355
|
-
*/
|
|
356
|
-
function isInterrogative(text: string, dynamicNames?: string[]): boolean {
|
|
357
|
-
let cleaned = text;
|
|
358
|
-
if (dynamicNames && dynamicNames.length > 0) {
|
|
359
|
-
cleaned = stripDynamicNames(cleaned, dynamicNames);
|
|
360
|
-
}
|
|
361
|
-
// Strip polite prefixes that don't change interrogative status
|
|
362
|
-
cleaned = cleaned.replace(/^\s*(hey|hi|hello|please|pls|plz)[,\s]+/i, "");
|
|
363
|
-
|
|
364
|
-
// Direct WH-questions (how/what/why/when/where/who/which)
|
|
365
|
-
if (WH_INTERROGATIVE.test(cleaned)) {
|
|
366
|
-
return true;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
// Indirect informational patterns — checked on cleaned text after
|
|
370
|
-
// stripping polite prefixes, so "please tell me how..." is caught
|
|
371
|
-
if (INDIRECT_INFORMATIONAL_PATTERNS.some((p) => p.test(cleaned))) {
|
|
372
|
-
return true;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
return false;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// ─── Structured intent resolver ─────────────────────────────────────────────
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Resolves recording intent from user text into a structured result that
|
|
382
|
-
* distinguishes pure recording commands from commands with remaining task text.
|
|
383
|
-
*
|
|
384
|
-
* Pipeline:
|
|
385
|
-
* 1. Strip dynamic assistant names (leading vocative)
|
|
386
|
-
* 2. Strip leading polite wrappers
|
|
387
|
-
* 3. Interrogative gate — questions return `none`
|
|
388
|
-
* 3.5. Restart compound detection (before independent start/stop)
|
|
389
|
-
* 3.6. Pause/resume detection
|
|
390
|
-
* 4. Detect start/stop patterns (start takes precedence when both present)
|
|
391
|
-
* 5. Determine if recording-only or has a remainder, stripping from the
|
|
392
|
-
* ORIGINAL text to preserve the user's exact phrasing
|
|
393
|
-
*/
|
|
394
|
-
export function resolveRecordingIntent(
|
|
395
|
-
text: string,
|
|
396
|
-
dynamicNames?: string[],
|
|
397
|
-
): RecordingIntentResult {
|
|
398
|
-
// Step 1: Strip dynamic assistant names for normalization
|
|
399
|
-
let normalized =
|
|
400
|
-
dynamicNames && dynamicNames.length > 0
|
|
401
|
-
? stripDynamicNames(text, dynamicNames)
|
|
402
|
-
: text;
|
|
403
|
-
|
|
404
|
-
// Step 2: Strip leading polite wrappers for normalization
|
|
405
|
-
normalized = normalized.replace(
|
|
406
|
-
/^\s*(hey|hi|hello|please|pls|plz)[,\s]+/i,
|
|
407
|
-
"",
|
|
408
|
-
);
|
|
409
|
-
|
|
410
|
-
// Step 3: Interrogative gate — questions (WH-words and indirect
|
|
411
|
-
// informational patterns) are not commands
|
|
412
|
-
if (isInterrogative(normalized, dynamicNames)) {
|
|
413
|
-
return { kind: "none" };
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// Step 3.5: Restart compound detection — check BEFORE independent start/stop
|
|
417
|
-
// so "stop recording and start a new one" is recognized as restart, not
|
|
418
|
-
// as separate stop + start patterns.
|
|
419
|
-
if (detectRestartRecordingIntent(normalized)) {
|
|
420
|
-
if (isRestartRecordingOnly(normalized)) {
|
|
421
|
-
return { kind: "restart_only" };
|
|
422
|
-
}
|
|
423
|
-
// Strip from the ORIGINAL text to preserve user's exact phrasing
|
|
424
|
-
const remainder = stripRestartRecordingIntent(text);
|
|
425
|
-
if (hasSubstantiveContent(remainder, dynamicNames)) {
|
|
426
|
-
return { kind: "restart_with_remainder", remainder };
|
|
427
|
-
}
|
|
428
|
-
return { kind: "restart_only" };
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// Step 3.6: Pause/resume detection — check before start/stop
|
|
432
|
-
if (detectPauseRecordingIntent(normalized)) {
|
|
433
|
-
if (isPauseRecordingOnly(normalized)) {
|
|
434
|
-
return { kind: "pause_only" };
|
|
435
|
-
}
|
|
436
|
-
// Pause with additional text falls through to normal processing
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
if (detectResumeRecordingIntent(normalized)) {
|
|
440
|
-
if (isResumeRecordingOnly(normalized)) {
|
|
441
|
-
return { kind: "resume_only" };
|
|
442
|
-
}
|
|
443
|
-
// Resume with additional text falls through to normal processing
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// Step 4: Detect start and stop patterns on the normalized text
|
|
447
|
-
const hasStart = detectRecordingIntent(normalized);
|
|
448
|
-
const hasStop = detectStopRecordingIntent(normalized);
|
|
449
|
-
|
|
450
|
-
// Step 5: Resolve
|
|
451
|
-
if (hasStart) {
|
|
452
|
-
if (hasStop) {
|
|
453
|
-
// Both start and stop detected — use combined variants
|
|
454
|
-
if (isRecordingOnly(normalized)) {
|
|
455
|
-
// Check if stop-only after stripping start patterns
|
|
456
|
-
const withoutStart = stripRecordingIntent(normalized);
|
|
457
|
-
if (isStopRecordingOnly(withoutStart)) {
|
|
458
|
-
return { kind: "start_and_stop_only" };
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
let remainder = stripRecordingIntent(text);
|
|
462
|
-
remainder = stripStopRecordingIntent(remainder);
|
|
463
|
-
if (hasSubstantiveContent(remainder, dynamicNames)) {
|
|
464
|
-
return { kind: "start_and_stop_with_remainder", remainder };
|
|
465
|
-
}
|
|
466
|
-
return { kind: "start_and_stop_only" };
|
|
467
|
-
}
|
|
468
|
-
// Only start detected
|
|
469
|
-
if (isRecordingOnly(normalized)) {
|
|
470
|
-
return { kind: "start_only" };
|
|
471
|
-
}
|
|
472
|
-
// Strip from the ORIGINAL text to preserve user's exact phrasing
|
|
473
|
-
const remainder = stripRecordingIntent(text);
|
|
474
|
-
if (hasSubstantiveContent(remainder, dynamicNames)) {
|
|
475
|
-
return { kind: "start_with_remainder", remainder };
|
|
476
|
-
}
|
|
477
|
-
return { kind: "start_only" };
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
if (hasStop) {
|
|
481
|
-
if (isStopRecordingOnly(normalized)) {
|
|
482
|
-
return { kind: "stop_only" };
|
|
483
|
-
}
|
|
484
|
-
// Strip from the ORIGINAL text to preserve user's exact phrasing
|
|
485
|
-
const remainder = stripStopRecordingIntent(text);
|
|
486
|
-
if (hasSubstantiveContent(remainder, dynamicNames)) {
|
|
487
|
-
return { kind: "stop_with_remainder", remainder };
|
|
488
|
-
}
|
|
489
|
-
return { kind: "stop_only" };
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
return { kind: "none" };
|
|
493
|
-
}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
-
|
|
3
|
-
import { and, eq } from "drizzle-orm";
|
|
4
|
-
|
|
5
|
-
import { getDb } from "./db.js";
|
|
6
|
-
import { accounts } from "./schema.js";
|
|
7
|
-
|
|
8
|
-
export interface AccountRecord {
|
|
9
|
-
id: string;
|
|
10
|
-
service: string;
|
|
11
|
-
username: string | null;
|
|
12
|
-
email: string | null;
|
|
13
|
-
displayName: string | null;
|
|
14
|
-
status: string;
|
|
15
|
-
credentialRef: string | null;
|
|
16
|
-
metadataJson: string | null;
|
|
17
|
-
createdAt: number;
|
|
18
|
-
updatedAt: number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function createAccount(params: {
|
|
22
|
-
service: string;
|
|
23
|
-
username?: string;
|
|
24
|
-
email?: string;
|
|
25
|
-
displayName?: string;
|
|
26
|
-
status?: string;
|
|
27
|
-
credentialRef?: string;
|
|
28
|
-
metadata?: Record<string, unknown>;
|
|
29
|
-
}): AccountRecord {
|
|
30
|
-
const db = getDb();
|
|
31
|
-
const now = Date.now();
|
|
32
|
-
const id = randomUUID();
|
|
33
|
-
|
|
34
|
-
const record = {
|
|
35
|
-
id,
|
|
36
|
-
service: params.service,
|
|
37
|
-
username: params.username ?? null,
|
|
38
|
-
email: params.email ?? null,
|
|
39
|
-
displayName: params.displayName ?? null,
|
|
40
|
-
status: params.status ?? "active",
|
|
41
|
-
credentialRef: params.credentialRef ?? null,
|
|
42
|
-
metadataJson: params.metadata ? JSON.stringify(params.metadata) : null,
|
|
43
|
-
createdAt: now,
|
|
44
|
-
updatedAt: now,
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
db.insert(accounts).values(record).run();
|
|
48
|
-
return record;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function listAccounts(filters?: {
|
|
52
|
-
service?: string;
|
|
53
|
-
status?: string;
|
|
54
|
-
}): AccountRecord[] {
|
|
55
|
-
const db = getDb();
|
|
56
|
-
|
|
57
|
-
const conditions = [];
|
|
58
|
-
if (filters?.service) {
|
|
59
|
-
conditions.push(eq(accounts.service, filters.service));
|
|
60
|
-
}
|
|
61
|
-
if (filters?.status) {
|
|
62
|
-
conditions.push(eq(accounts.status, filters.status));
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (conditions.length === 0) {
|
|
66
|
-
return db.select().from(accounts).all();
|
|
67
|
-
}
|
|
68
|
-
if (conditions.length === 1) {
|
|
69
|
-
return db.select().from(accounts).where(conditions[0]).all();
|
|
70
|
-
}
|
|
71
|
-
return db
|
|
72
|
-
.select()
|
|
73
|
-
.from(accounts)
|
|
74
|
-
.where(and(...conditions))
|
|
75
|
-
.all();
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function getAccount(id: string): AccountRecord | undefined {
|
|
79
|
-
const db = getDb();
|
|
80
|
-
const rows = db.select().from(accounts).where(eq(accounts.id, id)).all();
|
|
81
|
-
return rows[0] ?? undefined;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function updateAccount(
|
|
85
|
-
id: string,
|
|
86
|
-
updates: {
|
|
87
|
-
service?: string;
|
|
88
|
-
username?: string;
|
|
89
|
-
email?: string;
|
|
90
|
-
displayName?: string;
|
|
91
|
-
status?: string;
|
|
92
|
-
credentialRef?: string;
|
|
93
|
-
metadata?: Record<string, unknown>;
|
|
94
|
-
},
|
|
95
|
-
): AccountRecord | undefined {
|
|
96
|
-
const existing = getAccount(id);
|
|
97
|
-
if (!existing) return undefined;
|
|
98
|
-
|
|
99
|
-
const now = Date.now();
|
|
100
|
-
const values: Record<string, unknown> = { updatedAt: now };
|
|
101
|
-
|
|
102
|
-
if (updates.service !== undefined) values.service = updates.service;
|
|
103
|
-
if (updates.username !== undefined) values.username = updates.username;
|
|
104
|
-
if (updates.email !== undefined) values.email = updates.email;
|
|
105
|
-
if (updates.displayName !== undefined)
|
|
106
|
-
values.displayName = updates.displayName;
|
|
107
|
-
if (updates.status !== undefined) values.status = updates.status;
|
|
108
|
-
if (updates.credentialRef !== undefined)
|
|
109
|
-
values.credentialRef = updates.credentialRef;
|
|
110
|
-
if (updates.metadata !== undefined)
|
|
111
|
-
values.metadataJson = JSON.stringify(updates.metadata);
|
|
112
|
-
|
|
113
|
-
const db = getDb();
|
|
114
|
-
db.update(accounts).set(values).where(eq(accounts.id, id)).run();
|
|
115
|
-
|
|
116
|
-
return getAccount(id);
|
|
117
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Activity classifier for messaging conversations.
|
|
3
|
-
*
|
|
4
|
-
* Takes Conversation[] from any provider and groups them by activity level.
|
|
5
|
-
* Works for Slack channels, Gmail senders, Discord servers — anything
|
|
6
|
-
* that maps to the Conversation type.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { Conversation } from "./provider-types.js";
|
|
10
|
-
|
|
11
|
-
export type ActivityLevel = "dead" | "low" | "medium" | "high";
|
|
12
|
-
|
|
13
|
-
export interface ActivityGroup {
|
|
14
|
-
level: ActivityLevel;
|
|
15
|
-
conversations: Conversation[];
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface ActivitySummary {
|
|
19
|
-
platform: string;
|
|
20
|
-
totalConversations: number;
|
|
21
|
-
groups: ActivityGroup[];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Classify conversations by activity level based on last activity timestamp
|
|
28
|
-
* and unread count. Returns sorted groups from high to dead.
|
|
29
|
-
*/
|
|
30
|
-
export function classifyActivity(
|
|
31
|
-
conversations: Conversation[],
|
|
32
|
-
platform: string,
|
|
33
|
-
now = Date.now(),
|
|
34
|
-
): ActivitySummary {
|
|
35
|
-
const groups: Record<ActivityLevel, Conversation[]> = {
|
|
36
|
-
high: [],
|
|
37
|
-
medium: [],
|
|
38
|
-
low: [],
|
|
39
|
-
dead: [],
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
for (const conv of conversations) {
|
|
43
|
-
const ageDays = (now - conv.lastActivityAt) / ONE_DAY_MS;
|
|
44
|
-
|
|
45
|
-
let level: ActivityLevel;
|
|
46
|
-
if (conv.unreadCount > 0 && ageDays < 1) {
|
|
47
|
-
level = "high";
|
|
48
|
-
} else if (ageDays < 7) {
|
|
49
|
-
level = "medium";
|
|
50
|
-
} else if (ageDays < 30) {
|
|
51
|
-
level = "low";
|
|
52
|
-
} else {
|
|
53
|
-
level = "dead";
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
groups[level].push(conv);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Sort each group by lastActivityAt descending
|
|
60
|
-
for (const level of Object.keys(groups) as ActivityLevel[]) {
|
|
61
|
-
groups[level].sort((a, b) => b.lastActivityAt - a.lastActivityAt);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const result: ActivityGroup[] = [];
|
|
65
|
-
for (const level of ["high", "medium", "low", "dead"] as ActivityLevel[]) {
|
|
66
|
-
if (groups[level].length > 0) {
|
|
67
|
-
result.push({ level, conversations: groups[level] });
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
platform,
|
|
73
|
-
totalConversations: conversations.length,
|
|
74
|
-
groups: result,
|
|
75
|
-
};
|
|
76
|
-
}
|