@toddzheng024/dscode-desktop 0.0.0-stage → 0.7.33
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/LICENSE +21 -0
- package/README.md +120 -2
- package/THIRD_PARTY_NOTICES.md +30 -0
- package/bin/apply_patch +9 -0
- package/cordis.patch.yml +433 -0
- package/docs/CHANGELOG.md +641 -0
- package/docs/account-login.md +44 -0
- package/docs/auto-review.md +128 -0
- package/docs/browser-use.md +783 -0
- package/docs/computer-use.md +81 -0
- package/docs/custom-providers.md +88 -0
- package/docs/demo.md +76 -0
- package/docs/distribution.md +58 -0
- package/docs/dscode-ultra.md +75 -0
- package/docs/email.md +296 -0
- package/docs/exec.md +40 -0
- package/docs/hub-distribution.md +190 -0
- package/docs/memory.md +121 -0
- package/docs/opencode-go.md +61 -0
- package/docs/plugin-hub.md +68 -0
- package/docs/releases/0.2.0.md +28 -0
- package/docs/releases/0.3.0.md +21 -0
- package/docs/releases/0.4.0.md +20 -0
- package/docs/releases/0.5.0.md +19 -0
- package/docs/releases/0.6.0.md +20 -0
- package/docs/releases/0.7.0.md +22 -0
- package/docs/releases/0.7.1.md +20 -0
- package/docs/releases/0.7.10.md +10 -0
- package/docs/releases/0.7.11.md +17 -0
- package/docs/releases/0.7.12.md +11 -0
- package/docs/releases/0.7.13.md +12 -0
- package/docs/releases/0.7.14.md +11 -0
- package/docs/releases/0.7.15.md +11 -0
- package/docs/releases/0.7.16.md +10 -0
- package/docs/releases/0.7.17.md +12 -0
- package/docs/releases/0.7.18.md +13 -0
- package/docs/releases/0.7.19.md +8 -0
- package/docs/releases/0.7.2.md +19 -0
- package/docs/releases/0.7.20.md +10 -0
- package/docs/releases/0.7.21.md +9 -0
- package/docs/releases/0.7.22.md +11 -0
- package/docs/releases/0.7.23.md +14 -0
- package/docs/releases/0.7.24.md +11 -0
- package/docs/releases/0.7.25.md +8 -0
- package/docs/releases/0.7.26.md +18 -0
- package/docs/releases/0.7.27.md +8 -0
- package/docs/releases/0.7.28.md +22 -0
- package/docs/releases/0.7.29.md +12 -0
- package/docs/releases/0.7.3.md +23 -0
- package/docs/releases/0.7.30.md +19 -0
- package/docs/releases/0.7.31.md +14 -0
- package/docs/releases/0.7.32.md +14 -0
- package/docs/releases/0.7.33.md +30 -0
- package/docs/releases/0.7.4.md +16 -0
- package/docs/releases/0.7.5.md +18 -0
- package/docs/releases/0.7.6.md +29 -0
- package/docs/releases/0.7.7.md +36 -0
- package/docs/releases/0.7.8.md +14 -0
- package/docs/releases/0.7.9.md +15 -0
- package/docs/session-bridge.md +80 -0
- package/docs/session-cards.md +53 -0
- package/docs/session-communication.md +186 -0
- package/docs/session-metrics.md +41 -0
- package/docs/skills.md +81 -0
- package/docs/triggers.md +338 -0
- package/docs/tui-commands.md +204 -0
- package/extensions/browser/manifest.json +22 -0
- package/extensions/browser/popup.css +6 -0
- package/extensions/browser/popup.html +11 -0
- package/extensions/browser/popup.mjs +47 -0
- package/extensions/browser/protocol.mjs +168 -0
- package/extensions/browser/worker.mjs +94 -0
- package/icon.svg +7 -0
- package/locale/en.json +6 -0
- package/locale/zh-cn.json +6 -0
- package/node_modules/@deepseek-ai/node-addon-system/LICENSE +21 -0
- package/node_modules/@deepseek-ai/node-addon-system/README.i18n.yaml +6 -0
- package/node_modules/@deepseek-ai/node-addon-system/README.md +15 -0
- package/node_modules/@deepseek-ai/node-addon-system/README.zh.md +15 -0
- package/node_modules/@deepseek-ai/node-addon-system/lib/flock.d.ts +13 -0
- package/node_modules/@deepseek-ai/node-addon-system/lib/flock.js +51 -0
- package/node_modules/@deepseek-ai/node-addon-system/lib/index.d.ts +73 -0
- package/node_modules/@deepseek-ai/node-addon-system/lib/index.js +98 -0
- package/node_modules/@deepseek-ai/node-addon-system/package.json +45 -0
- package/node_modules/@deepseek-ai/node-addon-system/src/flock.c +164 -0
- package/node_modules/@deepseek-ai/node-addon-system/src/main.c +298 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/LICENSE +28 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/README.i18n.yaml +6 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/README.md +9 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/README.zh.md +9 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/bin/system.node +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/package.json +31 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/prebuilds.json +6 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/LICENSE +28 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/README.i18n.yaml +6 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/README.md +9 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/README.zh.md +9 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/bin/system.node +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/package.json +31 -0
- package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/prebuilds.json +6 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/LICENSE +28 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/README.i18n.yaml +6 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/README.md +11 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/README.zh.md +11 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/bin/glibc/system.node +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/bin/landlock-run +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/bin/musl/system.node +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/package.json +31 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/prebuilds.json +24 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/LICENSE +28 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/README.i18n.yaml +6 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/README.md +11 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/README.zh.md +11 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/bin/glibc/system.node +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/bin/landlock-run +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/bin/musl/system.node +0 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/package.json +31 -0
- package/node_modules/@deepseek-ai/node-addon-system-linux-x64/prebuilds.json +24 -0
- package/package.json +156 -4
- package/plugins/account/index.mjs +178 -0
- package/plugins/account/state.mjs +123 -0
- package/plugins/auto-review/audit.mjs +24 -0
- package/plugins/auto-review/index.mjs +267 -0
- package/plugins/auto-review/policy.mjs +92 -0
- package/plugins/browser/SKILL.md +158 -0
- package/plugins/browser/access.mjs +143 -0
- package/plugins/browser/config.mjs +60 -0
- package/plugins/browser/connection.mjs +385 -0
- package/plugins/browser/desktop-client.mjs +282 -0
- package/plugins/browser/desktop-host.mjs +74 -0
- package/plugins/browser/document-identity.mjs +57 -0
- package/plugins/browser/extension-relay.mjs +66 -0
- package/plugins/browser/files.mjs +32 -0
- package/plugins/browser/index.mjs +235 -0
- package/plugins/browser/mcp-entry.mjs +18 -0
- package/plugins/browser/mcp-tools.mjs +21 -0
- package/plugins/browser/presentation.mjs +45 -0
- package/plugins/browser/preview.mjs +77 -0
- package/plugins/browser/review.mjs +20 -0
- package/plugins/browser/screenshots.mjs +35 -0
- package/plugins/clipboard-image/clipboard-image.swift +56 -0
- package/plugins/clipboard-image/index.mjs +70 -0
- package/plugins/code-review/baseline.mjs +143 -0
- package/plugins/code-review/git.mjs +163 -0
- package/plugins/code-review/index.mjs +236 -0
- package/plugins/compaction/engine.mjs +304 -0
- package/plugins/compaction/tetris.mjs +65 -0
- package/plugins/compaction/threshold.mjs +98 -0
- package/plugins/computer-use/DESKTOP-SKILL.md +64 -0
- package/plugins/computer-use/desktop-host.mjs +75 -0
- package/plugins/computer-use/desktop-skill.mjs +28 -0
- package/plugins/computer-use/desktop-upstream.mjs +3 -0
- package/plugins/computer-use/index.mjs +37 -0
- package/plugins/cordis-config/plain.mjs +31 -0
- package/plugins/credentials/index.mjs +73 -0
- package/plugins/custom/adapter.mjs +110 -0
- package/plugins/custom/config.mjs +85 -0
- package/plugins/custom/desktop-client.mjs +150 -0
- package/plugins/custom/desktop-host.mjs +78 -0
- package/plugins/custom/images.mjs +32 -0
- package/plugins/custom/index.mjs +145 -0
- package/plugins/custom/wire.mjs +179 -0
- package/plugins/desktop/client.mjs +1041 -0
- package/plugins/desktop/index.mjs +10 -0
- package/plugins/desktop/shell-environment.mjs +9 -0
- package/plugins/desktop-workspace/hooks.mjs +29 -0
- package/plugins/desktop-workspace/index.mjs +37 -0
- package/plugins/dscode/board.mjs +260 -0
- package/plugins/dscode/child-target.mjs +11 -0
- package/plugins/dscode/control.mjs +17 -0
- package/plugins/dscode/desktop-client.mjs +55 -0
- package/plugins/dscode/desktop-host.mjs +37 -0
- package/plugins/dscode/index.mjs +270 -0
- package/plugins/email/cli.mjs +32 -0
- package/plugins/email/contacts.mjs +36 -0
- package/plugins/email/desktop-client.mjs +117 -0
- package/plugins/email/desktop-host.mjs +54 -0
- package/plugins/email/desktop-service.mjs +106 -0
- package/plugins/email/gmail-oauth.mjs +69 -0
- package/plugins/email/gmail-store.mjs +2 -0
- package/plugins/email/gmail.mjs +194 -0
- package/plugins/email/imap.mjs +136 -0
- package/plugins/email/inbox.d.mts +25 -0
- package/plugins/email/inbox.mjs +76 -0
- package/plugins/email/smtp.mjs +70 -0
- package/plugins/email/store.mjs +32 -0
- package/plugins/email-tools/index.mjs +46 -0
- package/plugins/exec/cli.mjs +64 -0
- package/plugins/exec/index.mjs +112 -0
- package/plugins/grok/adapter.mjs +114 -0
- package/plugins/grok/auth.mjs +76 -0
- package/plugins/grok/billing.mjs +146 -0
- package/plugins/grok/index.mjs +122 -0
- package/plugins/grok/models.mjs +129 -0
- package/plugins/grok/status.mjs +28 -0
- package/plugins/grok/wire.mjs +268 -0
- package/plugins/hub/catalog.mjs +82 -0
- package/plugins/hub/desktop-client.mjs +114 -0
- package/plugins/hub/desktop-host.mjs +129 -0
- package/plugins/i18n/messages.d.mts +21 -0
- package/plugins/i18n/messages.mjs +537 -0
- package/plugins/jev/approval.mjs +131 -0
- package/plugins/jev/client.mjs +74 -0
- package/plugins/jev/index.mjs +99 -0
- package/plugins/memory/content.mjs +57 -0
- package/plugins/memory/desktop-host.mjs +3 -0
- package/plugins/memory/index.mjs +168 -0
- package/plugins/memory/pipeline.mjs +79 -0
- package/plugins/memory/store.mjs +93 -0
- package/plugins/message-source/kind.mjs +20 -0
- package/plugins/opencode-go/adapter.mjs +96 -0
- package/plugins/opencode-go/command.mjs +128 -0
- package/plugins/opencode-go/index.mjs +120 -0
- package/plugins/opencode-go/models.mjs +58 -0
- package/plugins/opencode-go/oauth.mjs +194 -0
- package/plugins/opencode-go/search.mjs +86 -0
- package/plugins/opencode-go/usage.mjs +119 -0
- package/plugins/opencode-go/version.mjs +10 -0
- package/plugins/opencode-go/wire.mjs +73 -0
- package/plugins/openrouter/adapter.mjs +232 -0
- package/plugins/openrouter/index.mjs +123 -0
- package/plugins/openrouter/models.mjs +157 -0
- package/plugins/openrouter/search.mjs +113 -0
- package/plugins/openrouter/wire.mjs +101 -0
- package/plugins/providers/catalog.mjs +160 -0
- package/plugins/providers/chat-messages.mjs +120 -0
- package/plugins/providers/chat-stream.mjs +174 -0
- package/plugins/providers/desktop-client.mjs +84 -0
- package/plugins/providers/desktop-host.mjs +63 -0
- package/plugins/providers/effort.mjs +35 -0
- package/plugins/providers/http-errors.mjs +50 -0
- package/plugins/providers/openrouter-account.mjs +171 -0
- package/plugins/session-bridge/client.mjs +106 -0
- package/plugins/session-bridge/communication.mjs +260 -0
- package/plugins/session-bridge/index.mjs +68 -0
- package/plugins/session-bridge/mailbox.mjs +267 -0
- package/plugins/session-bridge/paths.mjs +21 -0
- package/plugins/session-bridge/server.mjs +172 -0
- package/plugins/session-bridge/tasks.mjs +229 -0
- package/plugins/session-cards/content.mjs +64 -0
- package/plugins/session-cards/index.mjs +38 -0
- package/plugins/session-cards/manager.mjs +140 -0
- package/plugins/session-metrics/attribution.mjs +30 -0
- package/plugins/session-metrics/balance.mjs +81 -0
- package/plugins/session-metrics/desktop-client.mjs +62 -0
- package/plugins/session-metrics/desktop-host.mjs +46 -0
- package/plugins/session-metrics/index.mjs +96 -0
- package/plugins/session-metrics/pricing.mjs +84 -0
- package/plugins/session-metrics/rate.mjs +59 -0
- package/plugins/session-metrics/store.mjs +75 -0
- package/plugins/session-metrics/turns.mjs +134 -0
- package/plugins/session-metrics/view.mjs +271 -0
- package/plugins/time-marks/desktop-host.mjs +2 -0
- package/plugins/time-marks/index.mjs +116 -0
- package/plugins/time-marks/marks.mjs +152 -0
- package/plugins/triggers/cli.mjs +558 -0
- package/plugins/triggers/commands.mjs +143 -0
- package/plugins/triggers/config.mjs +264 -0
- package/plugins/triggers/desktop-client.mjs +155 -0
- package/plugins/triggers/desktop-host.mjs +88 -0
- package/plugins/triggers/desktop-management.mjs +97 -0
- package/plugins/triggers/desktop-scheduler.mjs +125 -0
- package/plugins/triggers/host.mjs +24 -0
- package/plugins/triggers/index.mjs +27 -0
- package/plugins/triggers/job-cli.mjs +110 -0
- package/plugins/triggers/jobs.mjs +156 -0
- package/plugins/triggers/launchd.mjs +101 -0
- package/plugins/triggers/lease.mjs +24 -0
- package/plugins/triggers/log.mjs +104 -0
- package/plugins/triggers/management.mjs +181 -0
- package/plugins/triggers/options.mjs +117 -0
- package/plugins/triggers/overlay.mjs +7 -0
- package/plugins/triggers/poll.mjs +65 -0
- package/plugins/triggers/run.mjs +157 -0
- package/plugins/triggers/schedule.mjs +40 -0
- package/plugins/triggers/scheduler-service.mjs +46 -0
- package/plugins/triggers/scheduler.mjs +92 -0
- package/plugins/triggers/session-run.mjs +125 -0
- package/plugins/triggers/session.mjs +48 -0
- package/plugins/triggers/source-emit.mjs +19 -0
- package/plugins/triggers/source-host.mjs +78 -0
- package/plugins/triggers/source-ingress.mjs +70 -0
- package/plugins/triggers/source-sandbox.mjs +35 -0
- package/plugins/triggers/sources.mjs +45 -0
- package/plugins/triggers/spool.mjs +145 -0
- package/plugins/triggers/tools.mjs +67 -0
- package/plugins/triggers/unattended.mjs +18 -0
- package/plugins/tui-tools/composition.mjs +28 -0
- package/plugins/tui-tools/desktop-host.mjs +2 -0
- package/plugins/tui-tools/doctor-cli.mjs +22 -0
- package/plugins/tui-tools/doctor.mjs +148 -0
- package/plugins/tui-tools/hook-sources.mjs +113 -0
- package/plugins/tui-tools/hooks.mjs +23 -0
- package/plugins/tui-tools/index.mjs +268 -0
- package/plugins/tui-tools/sandbox-runner.mjs +123 -0
- package/plugins/tui-tools/shell.mjs +27 -0
- package/plugins/tui-tools/update.mjs +111 -0
- package/plugins/tui-tools/workspace-discovery.mjs +129 -0
- package/plugins/ultra/policy.mjs +42 -0
- package/plugins/worktree-subagent/worktree.mjs +56 -0
- package/runtime-sources.json +94 -0
- package/vendor/bash/LICENSE +21 -0
- package/vendor/bash/index.js +717 -0
- package/vendor/bash/types/background.d.ts +50 -0
- package/vendor/bash/types/index.d.ts +38 -0
- package/vendor/bash/types/render.d.ts +57 -0
- package/vendor/command-goal/LICENSE +21 -0
- package/vendor/command-goal/index.js +210 -0
- package/vendor/command-goal/types/index.d.ts +10 -0
- package/vendor/computer-use/LICENSE +21 -0
- package/vendor/computer-use/lib/approval-policy.js +12 -0
- package/vendor/computer-use/lib/approval-policy.js.map +1 -0
- package/vendor/computer-use/lib/artifacts.js +79 -0
- package/vendor/computer-use/lib/artifacts.js.map +1 -0
- package/vendor/computer-use/lib/backend.js +3 -0
- package/vendor/computer-use/lib/backend.js.map +1 -0
- package/vendor/computer-use/lib/client.js +369 -0
- package/vendor/computer-use/lib/client.js.map +1 -0
- package/vendor/computer-use/lib/config.js +159 -0
- package/vendor/computer-use/lib/config.js.map +1 -0
- package/vendor/computer-use/lib/confirmations.js +99 -0
- package/vendor/computer-use/lib/confirmations.js.map +1 -0
- package/vendor/computer-use/lib/diff.js +58 -0
- package/vendor/computer-use/lib/diff.js.map +1 -0
- package/vendor/computer-use/lib/errors.js +22 -0
- package/vendor/computer-use/lib/errors.js.map +1 -0
- package/vendor/computer-use/lib/exposure.js +244 -0
- package/vendor/computer-use/lib/exposure.js.map +1 -0
- package/vendor/computer-use/lib/index.js +66 -0
- package/vendor/computer-use/lib/index.js.map +1 -0
- package/vendor/computer-use/lib/leases.js +262 -0
- package/vendor/computer-use/lib/leases.js.map +1 -0
- package/vendor/computer-use/lib/providers/macos.js +243 -0
- package/vendor/computer-use/lib/providers/macos.js.map +1 -0
- package/vendor/computer-use/lib/providers/native-helper.js +726 -0
- package/vendor/computer-use/lib/providers/native-helper.js.map +1 -0
- package/vendor/computer-use/lib/providers/unsupported.js +51 -0
- package/vendor/computer-use/lib/providers/unsupported.js.map +1 -0
- package/vendor/computer-use/lib/service.js +608 -0
- package/vendor/computer-use/lib/service.js.map +1 -0
- package/vendor/computer-use/lib/skill.js +136 -0
- package/vendor/computer-use/lib/skill.js.map +1 -0
- package/vendor/computer-use/lib/target-resolver.js +180 -0
- package/vendor/computer-use/lib/target-resolver.js.map +1 -0
- package/vendor/computer-use/lib/tools.js +511 -0
- package/vendor/computer-use/lib/tools.js.map +1 -0
- package/vendor/computer-use/lib/types/approval-policy.d.ts +13 -0
- package/vendor/computer-use/lib/types/approval-policy.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/artifacts.d.ts +10 -0
- package/vendor/computer-use/lib/types/artifacts.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/backend.d.ts +124 -0
- package/vendor/computer-use/lib/types/backend.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/client/index.d.ts +83 -0
- package/vendor/computer-use/lib/types/client/index.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/config.d.ts +94 -0
- package/vendor/computer-use/lib/types/config.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/confirmations.d.ts +23 -0
- package/vendor/computer-use/lib/types/confirmations.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/diff.d.ts +5 -0
- package/vendor/computer-use/lib/types/diff.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/errors.d.ts +15 -0
- package/vendor/computer-use/lib/types/errors.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/exposure.d.ts +30 -0
- package/vendor/computer-use/lib/types/exposure.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/index.d.ts +21 -0
- package/vendor/computer-use/lib/types/index.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/leases.d.ts +81 -0
- package/vendor/computer-use/lib/types/leases.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/providers/macos.d.ts +39 -0
- package/vendor/computer-use/lib/types/providers/macos.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/providers/native-helper.d.ts +48 -0
- package/vendor/computer-use/lib/types/providers/native-helper.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/providers/unsupported.d.ts +23 -0
- package/vendor/computer-use/lib/types/providers/unsupported.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/service.d.ts +58 -0
- package/vendor/computer-use/lib/types/service.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/skill.d.ts +14 -0
- package/vendor/computer-use/lib/types/skill.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/target-resolver.d.ts +38 -0
- package/vendor/computer-use/lib/types/target-resolver.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/tools.d.ts +6 -0
- package/vendor/computer-use/lib/types/tools.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/types.d.ts +270 -0
- package/vendor/computer-use/lib/types/types.d.ts.map +1 -0
- package/vendor/computer-use/lib/types/web.d.ts +33 -0
- package/vendor/computer-use/lib/types/web.d.ts.map +1 -0
- package/vendor/computer-use/lib/types.js +9 -0
- package/vendor/computer-use/lib/types.js.map +1 -0
- package/vendor/computer-use/lib/web.js +188 -0
- package/vendor/computer-use/lib/web.js.map +1 -0
- package/vendor/computer-use/native/macos/Sources/Fixture/main.swift +412 -0
- package/vendor/computer-use/native/macos/Sources/Helper/CursorImage.swift +11 -0
- package/vendor/computer-use/native/macos/Sources/Helper/CursorMotion.swift +67 -0
- package/vendor/computer-use/native/macos/Sources/Helper/CursorOverlay.swift +840 -0
- package/vendor/computer-use/native/macos/Sources/Helper/TargetedPointer.swift +327 -0
- package/vendor/computer-use/native/macos/Sources/Helper/WindowNumberMatcher.swift +29 -0
- package/vendor/computer-use/native/macos/Sources/Helper/main.swift +1244 -0
- package/vendor/computer-use/native/macos/Sources/Monitor/main.swift +153 -0
- package/vendor/computer-use/native/macos/bin/dsh-computer-use-helper +0 -0
- package/vendor/computer-use/native/macos/manifest.json +14 -0
- package/vendor/persistent/LICENSE +21 -0
- package/vendor/persistent/index.js +411 -0
- package/vendor/persistent/types/index.d.ts +24 -0
- package/vendor/subagent/LICENSE +21 -0
- package/vendor/subagent/index.js +694 -0
- package/vendor/subagent/invariant.js +52 -0
- package/vendor/subagent/model-selection-settings.js +68 -0
- package/vendor/subagent/types/index.d.ts +82 -0
- package/vendor/subagent/types/invariant.d.ts +16 -0
- package/vendor/subagent/types/list-models.d.ts +10 -0
- package/vendor/subagent/types/model-selection-settings.d.ts +45 -0
- package/vendor/subagent/types/model-selection-state.d.ts +48 -0
- package/vendor/subagent/types/model-selection.d.ts +81 -0
- package/vendor/subagent-core/LICENSE +21 -0
- package/vendor/subagent-core/index.js +3202 -0
- package/vendor/subagent-core/invariant.js +76 -0
- package/vendor/subagent-core/typert.host.d.ts +3 -0
- package/vendor/subagent-core/typert.host.js +978 -0
- package/vendor/subagent-core/typert.remote-client.d.ts +25 -0
- package/vendor/subagent-core/typert.remote-client.js +114 -0
- package/vendor/subagent-core/types/archive-admission.d.ts +16 -0
- package/vendor/subagent-core/types/archive-admission.js +151 -0
- package/vendor/subagent-core/types/assistant-output.d.ts +48 -0
- package/vendor/subagent-core/types/assistant-output.js +73 -0
- package/vendor/subagent-core/types/catalog.d.ts +84 -0
- package/vendor/subagent-core/types/catalog.js +109 -0
- package/vendor/subagent-core/types/child-agent.d.ts +156 -0
- package/vendor/subagent-core/types/child-agent.js +213 -0
- package/vendor/subagent-core/types/client.d.ts +8 -0
- package/vendor/subagent-core/types/client.js +7 -0
- package/vendor/subagent-core/types/continuation-activation.d.ts +267 -0
- package/vendor/subagent-core/types/continuation-activation.js +700 -0
- package/vendor/subagent-core/types/continuation-messages.d.ts +62 -0
- package/vendor/subagent-core/types/continuation-messages.js +106 -0
- package/vendor/subagent-core/types/continuation.d.ts +124 -0
- package/vendor/subagent-core/types/continuation.js +455 -0
- package/vendor/subagent-core/types/control-types.d.ts +135 -0
- package/vendor/subagent-core/types/control-types.js +8 -0
- package/vendor/subagent-core/types/control.d.ts +45 -0
- package/vendor/subagent-core/types/control.js +79 -0
- package/vendor/subagent-core/types/depth.d.ts +31 -0
- package/vendor/subagent-core/types/depth.js +39 -0
- package/vendor/subagent-core/types/descriptor.d.ts +144 -0
- package/vendor/subagent-core/types/descriptor.js +193 -0
- package/vendor/subagent-core/types/error.d.ts +11 -0
- package/vendor/subagent-core/types/error.js +14 -0
- package/vendor/subagent-core/types/inbox.d.ts +43 -0
- package/vendor/subagent-core/types/inbox.js +61 -0
- package/vendor/subagent-core/types/index.d.ts +320 -0
- package/vendor/subagent-core/types/index.js +475 -0
- package/vendor/subagent-core/types/internal.d.ts +58 -0
- package/vendor/subagent-core/types/internal.js +58 -0
- package/vendor/subagent-core/types/invariant.d.ts +13 -0
- package/vendor/subagent-core/types/invariant.js +91 -0
- package/vendor/subagent-core/types/lifecycle.d.ts +113 -0
- package/vendor/subagent-core/types/lifecycle.js +180 -0
- package/vendor/subagent-core/types/list-children.d.ts +36 -0
- package/vendor/subagent-core/types/list-children.js +166 -0
- package/vendor/subagent-core/types/out-of-process.d.ts +118 -0
- package/vendor/subagent-core/types/out-of-process.js +219 -0
- package/vendor/subagent-core/types/projection-types.d.ts +82 -0
- package/vendor/subagent-core/types/projection-types.js +7 -0
- package/vendor/subagent-core/types/projection.d.ts +100 -0
- package/vendor/subagent-core/types/projection.js +157 -0
- package/vendor/subagent-core/types/run-settlement.d.ts +17 -0
- package/vendor/subagent-core/types/run-settlement.js +70 -0
- package/vendor/subagent-core/types/types.d.ts +377 -0
- package/vendor/subagent-core/types/types.js +19 -0
- package/vendor/subagent-driver/LICENSE +21 -0
- package/vendor/subagent-driver/index.js +255 -0
- package/vendor/subagent-driver/types/index.d.ts +33 -0
- package/vendor/subagent-driver/types/structured.d.ts +42 -0
- package/vendor/subagent-fork/LICENSE +21 -0
- package/vendor/subagent-fork/index.js +61 -0
- package/vendor/subagent-fork/types/index.d.ts +20 -0
- package/vendor/subagent-spawn/LICENSE +21 -0
- package/vendor/subagent-spawn/index.js +45 -0
- package/vendor/subagent-spawn/types/index.d.ts +19 -0
- package/vendor/terminal/LICENSE +21 -0
- package/vendor/terminal/index.js +1093 -0
- package/vendor/terminal/types/config.d.ts +82 -0
- package/vendor/terminal/types/index.d.ts +36 -0
- package/vendor/terminal/types/sanitize.d.ts +47 -0
- package/vendor/terminal/types/session.d.ts +87 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import CoreGraphics
|
|
2
|
+
import Darwin
|
|
3
|
+
import Foundation
|
|
4
|
+
|
|
5
|
+
struct TargetedPointerError: Error {
|
|
6
|
+
let message: String
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
struct TargetedPointerTarget {
|
|
10
|
+
let pid: pid_t
|
|
11
|
+
let windowNumber: Int64
|
|
12
|
+
let windowFrame: CGRect
|
|
13
|
+
|
|
14
|
+
func localPoint(for screenPoint: CGPoint) -> CGPoint {
|
|
15
|
+
CGPoint(
|
|
16
|
+
x: screenPoint.x - windowFrame.origin.x,
|
|
17
|
+
y: screenPoint.y - windowFrame.origin.y
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private typealias PostToPidFunction = @convention(c) (pid_t, UnsafeMutableRawPointer?) -> Void
|
|
23
|
+
private typealias SetIntegerFieldFunction = @convention(c) (UnsafeMutableRawPointer?, UInt32, Int64) -> Void
|
|
24
|
+
private typealias SetWindowLocationFunction = @convention(c) (UnsafeMutableRawPointer?, Double, Double) -> Void
|
|
25
|
+
|
|
26
|
+
private final class SkyLightPointerBridge {
|
|
27
|
+
static let shared = SkyLightPointerBridge()
|
|
28
|
+
|
|
29
|
+
private let handle: UnsafeMutableRawPointer?
|
|
30
|
+
private let postToPid: PostToPidFunction?
|
|
31
|
+
private let setIntegerField: SetIntegerFieldFunction?
|
|
32
|
+
private let setWindowLocation: SetWindowLocationFunction?
|
|
33
|
+
|
|
34
|
+
private init() {
|
|
35
|
+
handle = dlopen(
|
|
36
|
+
"/System/Library/PrivateFrameworks/SkyLight.framework/SkyLight",
|
|
37
|
+
RTLD_LAZY | RTLD_GLOBAL
|
|
38
|
+
)
|
|
39
|
+
postToPid = Self.resolve(handle, "SLEventPostToPid", as: PostToPidFunction.self)
|
|
40
|
+
setIntegerField = Self.resolve(handle, "SLEventSetIntegerValueField", as: SetIntegerFieldFunction.self)
|
|
41
|
+
setWindowLocation = Self.resolve(handle, "CGEventSetWindowLocation", as: SetWindowLocationFunction.self)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
deinit {
|
|
45
|
+
if let handle { dlclose(handle) }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private static func resolve<T>(_ handle: UnsafeMutableRawPointer?, _ name: String, as type: T.Type) -> T? {
|
|
49
|
+
guard let handle, let symbol = dlsym(handle, name) else { return nil }
|
|
50
|
+
return unsafeBitCast(symbol, to: type)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
var isAvailable: Bool {
|
|
54
|
+
postToPid != nil && setIntegerField != nil && setWindowLocation != nil
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
func post(
|
|
58
|
+
_ event: CGEvent,
|
|
59
|
+
target: TargetedPointerTarget,
|
|
60
|
+
localPoint: CGPoint,
|
|
61
|
+
clickState: Int64,
|
|
62
|
+
buttonNumber: Int64,
|
|
63
|
+
subtype: Int64,
|
|
64
|
+
gesturePhase: Int64,
|
|
65
|
+
clickGroup: Int64
|
|
66
|
+
) throws {
|
|
67
|
+
guard let postToPid, let setIntegerField, let setWindowLocation else {
|
|
68
|
+
throw TargetedPointerError(message: "SkyLight target-process pointer routing is unavailable")
|
|
69
|
+
}
|
|
70
|
+
let pointer = Unmanaged.passUnretained(event).toOpaque()
|
|
71
|
+
setWindowLocation(pointer, localPoint.x, localPoint.y)
|
|
72
|
+
setIntegerField(pointer, 0, gesturePhase)
|
|
73
|
+
setIntegerField(pointer, 1, clickState)
|
|
74
|
+
setIntegerField(pointer, 3, buttonNumber)
|
|
75
|
+
setIntegerField(pointer, 7, subtype)
|
|
76
|
+
setIntegerField(pointer, 40, Int64(target.pid))
|
|
77
|
+
setIntegerField(pointer, 51, target.windowNumber)
|
|
78
|
+
setIntegerField(pointer, 58, clickGroup)
|
|
79
|
+
setIntegerField(pointer, 91, target.windowNumber)
|
|
80
|
+
setIntegerField(pointer, 92, target.windowNumber)
|
|
81
|
+
|
|
82
|
+
postToPid(target.pid, pointer)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private func targetedPointerSource() throws -> CGEventSource {
|
|
87
|
+
guard SkyLightPointerBridge.shared.isAvailable else {
|
|
88
|
+
throw TargetedPointerError(message: "SkyLight target-process pointer routing is unavailable")
|
|
89
|
+
}
|
|
90
|
+
guard let source = CGEventSource(stateID: .privateState) else {
|
|
91
|
+
throw TargetedPointerError(message: "CoreGraphics pointer event source is unavailable")
|
|
92
|
+
}
|
|
93
|
+
return source
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private func clickGroup() -> Int64 {
|
|
97
|
+
Int64(DispatchTime.now().uptimeNanoseconds & 0x7fff_ffff)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private func buttonNumber(_ button: CGMouseButton) -> Int64 {
|
|
101
|
+
switch button {
|
|
102
|
+
case .right: return 1
|
|
103
|
+
case .center: return 2
|
|
104
|
+
default: return 0
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private func pointerEvent(
|
|
109
|
+
source: CGEventSource,
|
|
110
|
+
type: CGEventType,
|
|
111
|
+
button: CGMouseButton
|
|
112
|
+
) throws -> CGEvent {
|
|
113
|
+
let cursorLocation = CGEvent(source: nil)?.location ?? .zero
|
|
114
|
+
guard let event = CGEvent(
|
|
115
|
+
mouseEventSource: source,
|
|
116
|
+
mouseType: type,
|
|
117
|
+
mouseCursorPosition: cursorLocation,
|
|
118
|
+
mouseButton: button
|
|
119
|
+
) else {
|
|
120
|
+
throw TargetedPointerError(message: "CoreGraphics could not create a pointer event")
|
|
121
|
+
}
|
|
122
|
+
return event
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private func postPointerEvent(
|
|
126
|
+
_ event: CGEvent,
|
|
127
|
+
target: TargetedPointerTarget,
|
|
128
|
+
point: CGPoint,
|
|
129
|
+
clickState: Int64,
|
|
130
|
+
buttonNumber: Int64,
|
|
131
|
+
subtype: Int64,
|
|
132
|
+
gesturePhase: Int64,
|
|
133
|
+
clickGroup: Int64
|
|
134
|
+
) throws {
|
|
135
|
+
try SkyLightPointerBridge.shared.post(
|
|
136
|
+
event,
|
|
137
|
+
target: target,
|
|
138
|
+
localPoint: target.localPoint(for: point),
|
|
139
|
+
clickState: clickState,
|
|
140
|
+
buttonNumber: buttonNumber,
|
|
141
|
+
subtype: subtype,
|
|
142
|
+
gesturePhase: gesturePhase,
|
|
143
|
+
clickGroup: clickGroup
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
func targetedClick(
|
|
148
|
+
at point: CGPoint,
|
|
149
|
+
button: CGMouseButton,
|
|
150
|
+
count: Int,
|
|
151
|
+
target: TargetedPointerTarget
|
|
152
|
+
) throws {
|
|
153
|
+
let source = try targetedPointerSource()
|
|
154
|
+
let group = clickGroup()
|
|
155
|
+
let number = buttonNumber(button)
|
|
156
|
+
let moved = try pointerEvent(source: source, type: .mouseMoved, button: .left)
|
|
157
|
+
try postPointerEvent(
|
|
158
|
+
moved,
|
|
159
|
+
target: target,
|
|
160
|
+
point: point,
|
|
161
|
+
clickState: 0,
|
|
162
|
+
buttonNumber: 0,
|
|
163
|
+
subtype: 3,
|
|
164
|
+
gesturePhase: 2,
|
|
165
|
+
clickGroup: group
|
|
166
|
+
)
|
|
167
|
+
usleep(12_000)
|
|
168
|
+
|
|
169
|
+
let downType: CGEventType = button == .right ? .rightMouseDown : button == .center ? .otherMouseDown : .leftMouseDown
|
|
170
|
+
let upType: CGEventType = button == .right ? .rightMouseUp : button == .center ? .otherMouseUp : .leftMouseUp
|
|
171
|
+
for pair in 1...max(1, count) {
|
|
172
|
+
let down = try pointerEvent(source: source, type: downType, button: button)
|
|
173
|
+
down.setDoubleValueField(.mouseEventPressure, value: 1)
|
|
174
|
+
try postPointerEvent(
|
|
175
|
+
down,
|
|
176
|
+
target: target,
|
|
177
|
+
point: point,
|
|
178
|
+
clickState: Int64(pair),
|
|
179
|
+
buttonNumber: number,
|
|
180
|
+
subtype: 3,
|
|
181
|
+
gesturePhase: 3,
|
|
182
|
+
clickGroup: group
|
|
183
|
+
)
|
|
184
|
+
usleep(28_000)
|
|
185
|
+
|
|
186
|
+
let up = try pointerEvent(source: source, type: upType, button: button)
|
|
187
|
+
up.setDoubleValueField(.mouseEventPressure, value: 0)
|
|
188
|
+
try postPointerEvent(
|
|
189
|
+
up,
|
|
190
|
+
target: target,
|
|
191
|
+
point: point,
|
|
192
|
+
clickState: Int64(pair),
|
|
193
|
+
buttonNumber: number,
|
|
194
|
+
subtype: 3,
|
|
195
|
+
gesturePhase: 3,
|
|
196
|
+
clickGroup: group
|
|
197
|
+
)
|
|
198
|
+
if pair < count { usleep(80_000) }
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
func targetedScroll(
|
|
203
|
+
at point: CGPoint,
|
|
204
|
+
vertical: Int32,
|
|
205
|
+
horizontal: Int32,
|
|
206
|
+
target: TargetedPointerTarget
|
|
207
|
+
) throws {
|
|
208
|
+
let source = try targetedPointerSource()
|
|
209
|
+
let group = clickGroup()
|
|
210
|
+
let moved = try pointerEvent(source: source, type: .mouseMoved, button: .left)
|
|
211
|
+
try postPointerEvent(
|
|
212
|
+
moved,
|
|
213
|
+
target: target,
|
|
214
|
+
point: point,
|
|
215
|
+
clickState: 0,
|
|
216
|
+
buttonNumber: 0,
|
|
217
|
+
subtype: 0,
|
|
218
|
+
gesturePhase: 2,
|
|
219
|
+
clickGroup: group
|
|
220
|
+
)
|
|
221
|
+
usleep(12_000)
|
|
222
|
+
|
|
223
|
+
guard let event = CGEvent(
|
|
224
|
+
scrollWheelEvent2Source: source,
|
|
225
|
+
units: .line,
|
|
226
|
+
wheelCount: 2,
|
|
227
|
+
wheel1: vertical,
|
|
228
|
+
wheel2: horizontal,
|
|
229
|
+
wheel3: 0
|
|
230
|
+
) else {
|
|
231
|
+
throw TargetedPointerError(message: "CoreGraphics could not create a scroll event")
|
|
232
|
+
}
|
|
233
|
+
event.location = CGEvent(source: nil)?.location ?? .zero
|
|
234
|
+
try postPointerEvent(
|
|
235
|
+
event,
|
|
236
|
+
target: target,
|
|
237
|
+
point: point,
|
|
238
|
+
clickState: 0,
|
|
239
|
+
buttonNumber: 0,
|
|
240
|
+
subtype: 0,
|
|
241
|
+
gesturePhase: 2,
|
|
242
|
+
clickGroup: group
|
|
243
|
+
)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
func targetedDrag(
|
|
247
|
+
from: CGPoint,
|
|
248
|
+
to: CGPoint,
|
|
249
|
+
target: TargetedPointerTarget,
|
|
250
|
+
speedPxPerSecond: Double,
|
|
251
|
+
accelerationPxPerSecondSquared: Double
|
|
252
|
+
) throws {
|
|
253
|
+
let source = try targetedPointerSource()
|
|
254
|
+
let group = clickGroup()
|
|
255
|
+
let moved = try pointerEvent(source: source, type: .mouseMoved, button: .left)
|
|
256
|
+
try postPointerEvent(
|
|
257
|
+
moved,
|
|
258
|
+
target: target,
|
|
259
|
+
point: from,
|
|
260
|
+
clickState: 0,
|
|
261
|
+
buttonNumber: 0,
|
|
262
|
+
subtype: 0,
|
|
263
|
+
gesturePhase: 2,
|
|
264
|
+
clickGroup: group
|
|
265
|
+
)
|
|
266
|
+
usleep(2_000)
|
|
267
|
+
|
|
268
|
+
let down = try pointerEvent(source: source, type: .leftMouseDown, button: .left)
|
|
269
|
+
down.setDoubleValueField(.mouseEventPressure, value: 1)
|
|
270
|
+
try postPointerEvent(
|
|
271
|
+
down,
|
|
272
|
+
target: target,
|
|
273
|
+
point: from,
|
|
274
|
+
clickState: 1,
|
|
275
|
+
buttonNumber: 0,
|
|
276
|
+
subtype: 0,
|
|
277
|
+
gesturePhase: 3,
|
|
278
|
+
clickGroup: group
|
|
279
|
+
)
|
|
280
|
+
usleep(2_000)
|
|
281
|
+
|
|
282
|
+
let distance = hypot(to.x - from.x, to.y - from.y)
|
|
283
|
+
let duration = distance == 0 ? 0 : cursorMotionDuration(
|
|
284
|
+
distance: distance,
|
|
285
|
+
speed: speedPxPerSecond,
|
|
286
|
+
acceleration: accelerationPxPerSecondSquared
|
|
287
|
+
)
|
|
288
|
+
let started = ProcessInfo.processInfo.systemUptime
|
|
289
|
+
while true {
|
|
290
|
+
let elapsed = ProcessInfo.processInfo.systemUptime - started
|
|
291
|
+
let progress = duration == 0 ? 1 : min(1, elapsed / duration)
|
|
292
|
+
let fraction = cursorMotionFraction(
|
|
293
|
+
progress: progress,
|
|
294
|
+
distance: distance,
|
|
295
|
+
speed: speedPxPerSecond,
|
|
296
|
+
acceleration: accelerationPxPerSecondSquared
|
|
297
|
+
)
|
|
298
|
+
let point = cursorMotionPoint(from: from, to: to, fraction: fraction)
|
|
299
|
+
let dragged = try pointerEvent(source: source, type: .leftMouseDragged, button: .left)
|
|
300
|
+
dragged.setDoubleValueField(.mouseEventPressure, value: 1)
|
|
301
|
+
try postPointerEvent(
|
|
302
|
+
dragged,
|
|
303
|
+
target: target,
|
|
304
|
+
point: point,
|
|
305
|
+
clickState: 1,
|
|
306
|
+
buttonNumber: 0,
|
|
307
|
+
subtype: 0,
|
|
308
|
+
gesturePhase: 3,
|
|
309
|
+
clickGroup: group
|
|
310
|
+
)
|
|
311
|
+
if progress >= 1 { break }
|
|
312
|
+
usleep(8_333)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
let up = try pointerEvent(source: source, type: .leftMouseUp, button: .left)
|
|
316
|
+
up.setDoubleValueField(.mouseEventPressure, value: 0)
|
|
317
|
+
try postPointerEvent(
|
|
318
|
+
up,
|
|
319
|
+
target: target,
|
|
320
|
+
point: to,
|
|
321
|
+
clickState: 1,
|
|
322
|
+
buttonNumber: 0,
|
|
323
|
+
subtype: 0,
|
|
324
|
+
gesturePhase: 3,
|
|
325
|
+
clickGroup: group
|
|
326
|
+
)
|
|
327
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
struct WindowNumberCandidate {
|
|
2
|
+
let number: Int?
|
|
3
|
+
let title: String?
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
private func titlesMatch(_ observed: String, _ candidate: String) -> Bool {
|
|
7
|
+
if observed == candidate { return true }
|
|
8
|
+
let (shorter, longer) = observed.count < candidate.count
|
|
9
|
+
? (observed, candidate)
|
|
10
|
+
: (candidate, observed)
|
|
11
|
+
guard longer.hasPrefix(shorter), let boundary = longer.dropFirst(shorter.count).first else { return false }
|
|
12
|
+
return boundary.isWhitespace || "-–—:|([{·".contains(boundary)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
func matchedWindowNumber(
|
|
16
|
+
candidates: [WindowNumberCandidate],
|
|
17
|
+
observedTitle: String?
|
|
18
|
+
) -> Int? {
|
|
19
|
+
if candidates.count == 1 {
|
|
20
|
+
return candidates[0].number
|
|
21
|
+
}
|
|
22
|
+
guard let observedTitle, !observedTitle.isEmpty else { return nil }
|
|
23
|
+
let titled = candidates.filter { candidate in
|
|
24
|
+
guard let candidateTitle = candidate.title, !candidateTitle.isEmpty else { return false }
|
|
25
|
+
return titlesMatch(observedTitle, candidateTitle)
|
|
26
|
+
}
|
|
27
|
+
guard titled.count == 1 else { return nil }
|
|
28
|
+
return titled[0].number
|
|
29
|
+
}
|