mixdog 1.3.4 → 1.4.0
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/LICENSES/oh-my-pi-MIT.txt +23 -0
- package/NOTICE.md +17 -2
- package/README.md +11 -0
- package/package.json +3 -11
- package/scripts/daemon-stub.mjs +1 -1
- package/scripts/embed-google-oauth-client.mjs +49 -0
- package/scripts/gate-local.mjs +4 -2
- package/scripts/lib/test-spawn-ledger.mjs +46 -1
- package/scripts/native-release-status.mjs +2 -2
- package/scripts/recall-history-cases.json +1 -1
- package/scripts/suite-health.mjs +10 -1
- package/scripts/test.mjs +12 -11
- package/src/agents/reviewer/AGENT.md +7 -11
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +25 -1
- package/src/defaults/skills/browser-use/SKILL.md +77 -17
- package/src/defaults/skills/code-tidy/SKILL.md +142 -270
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
- package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
- package/src/defaults/skills/computer-use/SKILL.md +33 -9
- package/src/defaults/skills/setup/SKILL.md +29 -2
- package/src/defaults/skills/setup/references/actions.md +117 -28
- package/src/defaults/skills/setup/references/surfaces.md +77 -35
- package/src/defaults/skills/setup-guide/SKILL.md +3 -3
- package/src/defaults/skills/visualize/SKILL.md +2 -1
- package/src/lib/keychain-cjs.cjs +359 -29
- package/src/lib/rules-builder.cjs +10 -8
- package/src/rules/agent/AGENT.md +6 -6
- package/src/rules/agent-mode/AGENT_MODE.md +10 -2
- package/src/rules/agent-mode/MIXY.md +12 -0
- package/src/rules/lead/LEAD.md +18 -20
- package/src/rules/shared/05-tool-calls.md +5 -6
- package/src/rules/shared/10-tool-workflow.md +2 -0
- package/src/rules/shared/60-verification.md +7 -5
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +193 -0
- package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
- package/src/runtime/agent/orchestrator/config.mjs +34 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +72 -67
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +54 -1
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +177 -73
- package/src/runtime/agent/orchestrator/mcp/client.mjs +25 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +31 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +16 -3
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +42 -7
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +21 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +23 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +11 -1
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +230 -137
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +64 -7
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +18 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +160 -69
- package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +64 -33
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +52 -8
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +22 -6
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +15 -4
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +17 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +142 -104
- package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +10 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +10 -217
- package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -6
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +409 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-families.mjs +187 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-identity.mjs +342 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-models.mjs +541 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-protobuf.mjs +305 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-request.mjs +558 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-schema.mjs +880 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-session.mjs +190 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-tool-args.mjs +351 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +560 -0
- package/src/runtime/agent/orchestrator/providers/devin.mjs +491 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/gemini-output-limit.mjs +46 -0
- package/src/runtime/agent/orchestrator/providers/gemini-reasoning-relay.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +7 -11
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +61 -22
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -4
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +25 -2
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +96 -5
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +23 -5
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
- package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +19 -1
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +39 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/provider-availability.mjs +19 -0
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
- package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/registry.mjs +43 -3
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
- package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/wire-protobuf-codec.mjs +368 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +12 -7
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
- package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
- package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/reaction-tool-defs.mjs +133 -0
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +23 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-profile.mjs +35 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +57 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +9 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +0 -3
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +10 -4
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +792 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +148 -25
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
- package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +47 -9
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +14 -2
- package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +18 -22
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +32 -3
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +51 -3
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +17 -3
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +14 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +23 -5
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +23 -13
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +129 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +18 -5
- package/src/runtime/agent/orchestrator/session/message-ids.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/message-reactions.mjs +89 -0
- package/src/runtime/agent/orchestrator/session/message-reactions.test-support.mjs +75 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +19 -8
- package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +127 -0
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +0 -2
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +47 -11
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
- package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
- package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
- package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-header-cache.mjs +85 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +133 -18
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +12 -2
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -14
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +84 -3
- package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
- package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +25 -2
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
- package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +25 -5
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +65 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
- package/src/runtime/browser-bridge/action-schema.mjs +13 -2
- package/src/runtime/browser-bridge/client.mjs +73 -8
- package/src/runtime/browser-bridge/input-fields.mjs +8 -9
- package/src/runtime/browser-bridge/mail-links.mjs +107 -0
- package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
- package/src/runtime/channels/lib/config.mjs +6 -61
- package/src/runtime/channels/lib/crash-log.mjs +1 -1
- package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
- package/src/runtime/channels/lib/event-queue.mjs +3 -18
- package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
- package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
- package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
- package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
- package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
- package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
- package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
- package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
- package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
- package/src/runtime/channels/lib/schedule-errors.mjs +51 -0
- package/src/runtime/channels/lib/scheduler.mjs +135 -154
- package/src/runtime/channels/lib/schedules-db.mjs +83 -11
- package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
- package/src/runtime/channels/lib/tool-dispatch.mjs +14 -2
- package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
- package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
- package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
- package/src/runtime/channels/lib/worker-main.mjs +19 -34
- package/src/runtime/computer-bridge/action-schema.mjs +42 -1
- package/src/runtime/computer-bridge/actions.mjs +9 -1
- package/src/runtime/computer-bridge/client.mjs +180 -8
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +27 -2
- package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
- package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
- package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
- package/src/runtime/connectors/gmail-app-password.mjs +172 -39
- package/src/runtime/connectors/google-mcp.mjs +10 -12
- package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
- package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
- package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
- package/src/runtime/office/com/com-adapter.mjs +17 -1
- package/src/runtime/office/com/office-com-host.ps1 +51 -1
- package/src/runtime/office/pdf/cfb-fixture.mjs +328 -0
- package/src/runtime/office/pdf/cfb-protection.mjs +311 -0
- package/src/runtime/office/pdf/document-preview.mjs +326 -8
- package/src/runtime/office/pdf/ooxml-crypto.mjs +469 -0
- package/src/runtime/office/pdf/ooxml-key-worker.mjs +14 -0
- package/src/runtime/office/portable/portable-soffice.mjs +45 -5
- package/src/runtime/session-search/session-search-db.mjs +73 -9
- package/src/runtime/session-search/session-search-ingest.mjs +110 -20
- package/src/runtime/shared/abort-race.mjs +89 -0
- package/src/runtime/shared/agent-avatar.d.mts +0 -1
- package/src/runtime/shared/agent-kind.mjs +4 -3
- package/src/runtime/shared/bot-hops.mjs +62 -2
- package/src/runtime/shared/bounded-download.mjs +8 -3
- package/src/runtime/shared/config.mjs +51 -35
- package/src/runtime/shared/connector-accounts.mjs +20 -10
- package/src/runtime/shared/connector-catalog.d.mts +33 -2
- package/src/runtime/shared/connector-catalog.mjs +166 -8
- package/src/runtime/shared/connector-triggers.mjs +22 -19
- package/src/runtime/shared/defaults-separation.mjs +2 -14
- package/src/runtime/shared/delegated-approval-host.mjs +103 -11
- package/src/runtime/shared/developer-options.mjs +32 -1
- package/src/runtime/shared/err-text.mjs +24 -15
- package/src/runtime/shared/file-permissions.d.mts +0 -8
- package/src/runtime/shared/file-permissions.mjs +0 -11
- package/src/runtime/shared/git-direct.test-support.mjs +19 -0
- package/src/runtime/shared/google-oauth-client.generated.json +4 -0
- package/src/runtime/shared/google-oauth-client.mjs +34 -9
- package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
- package/src/runtime/shared/heartbeat-interval.mjs +19 -0
- package/src/runtime/shared/idle-auto-clear-gate.mjs +104 -0
- package/src/runtime/shared/llm/anthropic-betas.mjs +7 -0
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +12 -0
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +1 -0
- package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
- package/src/runtime/shared/llm/well-formed.mjs +66 -0
- package/src/runtime/shared/mixy-presence.mjs +22 -0
- package/src/runtime/shared/orchestration.d.mts +2 -0
- package/src/runtime/shared/pg-schema-db.mjs +27 -16
- package/src/runtime/shared/profile-config.cjs +1 -1
- package/src/runtime/shared/prompt-origin.d.mts +4 -0
- package/src/runtime/shared/prompt-origin.mjs +21 -0
- package/src/runtime/shared/provider-accounts.mjs +231 -59
- package/src/runtime/shared/provider-api-key.mjs +19 -8
- package/src/runtime/shared/provider-display-name.mjs +29 -0
- package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
- package/src/runtime/shared/routine-trigger.d.mts +2 -0
- package/src/runtime/shared/routine-trigger.mjs +52 -0
- package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
- package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
- package/src/runtime/shared/session-activity-signal.mjs +34 -1
- package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
- package/src/runtime/shared/session-sidebar-host.mjs +7 -3
- package/src/runtime/shared/session-turn-prelude.mjs +18 -0
- package/src/runtime/shared/tool-execution-contract.mjs +2 -0
- package/src/runtime/shared/tool-result-summary.mjs +1 -14
- package/src/runtime/shared/transcript-metadata.mjs +38 -0
- package/src/runtime/shared/user-data-guard.mjs +30 -2
- package/src/runtime/shared/worktrees/activity-gate.mjs +12 -5
- package/src/runtime/shared/worktrees/test-support.mjs +9 -4
- package/src/runtime/terminal-bridge/client.mjs +10 -1
- package/src/runtime/visualize-bridge/client.mjs +27 -8
- package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
- package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
- package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
- package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
- package/src/session-runtime/agent-home-delivery.mjs +486 -179
- package/src/session-runtime/agent-room-delivery.mjs +28 -1
- package/src/session-runtime/agent-task-sessions.mjs +561 -199
- package/src/session-runtime/boot/apis.mjs +9 -0
- package/src/session-runtime/boot/begin.mjs +3 -2
- package/src/session-runtime/boot/infrastructure.mjs +4 -0
- package/src/session-runtime/boot/providers.mjs +3 -0
- package/src/session-runtime/boot/tools.mjs +8 -1
- package/src/session-runtime/bot-chain.mjs +32 -0
- package/src/session-runtime/bot-status.mjs +7 -4
- package/src/session-runtime/channel-config-api.mjs +63 -17
- package/src/session-runtime/config-lifecycle.mjs +6 -0
- package/src/session-runtime/connector-merge-migration.mjs +305 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +132 -28
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +2 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +45 -0
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +72 -5
- package/src/session-runtime/internal-tool-executor.mjs +4 -0
- package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
- package/src/session-runtime/lifecycle/session-catalog.mjs +3 -1
- package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
- package/src/session-runtime/lifecycle/teardown.mjs +23 -5
- package/src/session-runtime/mcp-glue/server-catalog.mjs +61 -3
- package/src/session-runtime/mcp-oauth-login.mjs +5 -3
- package/src/session-runtime/mixy-heartbeat.mjs +927 -0
- package/src/session-runtime/model-route/route-tuning.mjs +10 -6
- package/src/session-runtime/notification-bus.mjs +31 -117
- package/src/session-runtime/notification-completion-queue.mjs +54 -0
- package/src/session-runtime/notification-listeners.mjs +76 -0
- package/src/session-runtime/owned-automation-run.mjs +35 -13
- package/src/session-runtime/prewarm/channel-start.mjs +3 -7
- package/src/session-runtime/provider-auth/login.mjs +7 -0
- package/src/session-runtime/provider-models/row-hydration.mjs +13 -2
- package/src/session-runtime/resource-mcp-api.mjs +143 -224
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
- package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
- package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
- package/src/session-runtime/resource-mcp-servers.mjs +78 -0
- package/src/session-runtime/resource-mcp-store.mjs +49 -0
- package/src/session-runtime/routine-home-turn.mjs +33 -6
- package/src/session-runtime/routine-owner.mjs +40 -9
- package/src/session-runtime/schedule-session-run.mjs +7 -3
- package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +8 -12
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +7 -2
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
- package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
- package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
- package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
- package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
- package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
- package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
- package/src/session-runtime/services/channel-admin.mjs +73 -31
- package/src/session-runtime/services/channel-session-router.mjs +4 -2
- package/src/session-runtime/services/channel-worker.mjs +1 -1
- package/src/session-runtime/services/provider-admin.mjs +128 -25
- package/src/session-runtime/services/schedule-access.mjs +14 -0
- package/src/session-runtime/services/seeds.mjs +0 -28
- package/src/session-runtime/services/usage-dashboard-model.mjs +1 -0
- package/src/session-runtime/session-compaction-sync.mjs +27 -0
- package/src/session-runtime/session-create/session-options.mjs +8 -4
- package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
- package/src/session-runtime/settings-compaction-api.mjs +2 -40
- package/src/session-runtime/settings-system-api.mjs +28 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
- package/src/session-runtime/setup-tool/executor.mjs +187 -29
- package/src/session-runtime/setup-tool/extended-actions.mjs +33 -2
- package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +68 -6
- package/src/session-runtime/setup-tool/tool-defs.mjs +92 -6
- package/src/session-runtime/task-session-route.mjs +99 -0
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
- package/src/session-runtime/tool-policy/policy-stage.mjs +21 -4
- package/src/session-runtime/tool-policy/surface-helpers.mjs +2 -3
- package/src/session-runtime/tool-surface.mjs +4 -0
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +98 -21
- package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -1
- package/src/session-runtime/workspace/transitions.mjs +10 -2
- package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
- package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
- package/src/standalone/channel-transport/client-registry.mjs +24 -163
- package/src/standalone/channel-transport.mjs +1 -1
- package/src/standalone/daemon-channels-loader.mjs +10 -8
- package/src/standalone/daemon-session-control/list-page.mjs +72 -0
- package/src/standalone/daemon-session-control/request.mjs +51 -0
- package/src/standalone/daemon-session-control/room-host.mjs +57 -0
- package/src/standalone/daemon-session-control/route-control.mjs +48 -0
- package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
- package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
- package/src/standalone/daemon-session-control.mjs +161 -157
- package/src/standalone/daemon.mjs +33 -2
- package/src/standalone/session-client.mjs +7 -3
- package/src/standalone/session-protocol.mjs +10 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +6 -2
- package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
- package/src/standalone/session-service/quota-resume.mjs +3 -0
- package/src/standalone/session-service/retention/busy.mjs +65 -1
- package/src/standalone/session-service/session-calls/session-action.mjs +23 -2
- package/src/standalone/session-service/session-calls/session-turns.mjs +6 -0
- package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
- package/src/standalone/session-service.mjs +13 -0
- package/src/standalone/session-tool-output.mjs +21 -10
- package/src/tui/app/model-options.mjs +4 -27
- package/src/tui/dist/index.mjs +81 -65
- package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
- package/src/tui/session/initial-state.mjs +3 -0
- package/src/tui/session/notice-surface.mjs +23 -1
- package/src/tui/session/queue-helpers.mjs +3 -42
- package/src/tui/session/session-api/integrations.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +8 -0
- package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
- package/src/tui/session/session-api/routes-write.mjs +5 -1
- package/src/tui/session/session-api/routes.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +30 -2
- package/src/tui/session/session-flow/auto-clear.mjs +4 -33
- package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
- package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
- package/src/tui/session/session-flow/drain-retry.mjs +35 -0
- package/src/tui/session/session-flow/drain.mjs +118 -149
- package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
- package/src/tui/session/session-flow/queue/take-entries.mjs +5 -2
- package/src/tui/session/tool-approval-delegation.mjs +64 -0
- package/src/tui/session/tool-approval-request.mjs +39 -0
- package/src/tui/session/tool-approval-settle.mjs +62 -0
- package/src/tui/session/tool-approval.mjs +69 -115
- package/src/tui/session/tui-steering-persist.mjs +8 -1
- package/src/tui/session/turn-stream.mjs +36 -3
- package/src/tui/session/turn.mjs +23 -2
- package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
- package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
- package/scripts/code-graph-description-contract.mjs +0 -188
- package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
|
@@ -57,7 +57,7 @@ function* armedScheduleFires(scheduler) {
|
|
|
57
57
|
const fireAt = cronTaskNextFireAt(task);
|
|
58
58
|
if (fireAt !== null) yield { name, fireAt, kind: 'cron' };
|
|
59
59
|
}
|
|
60
|
-
const defs =
|
|
60
|
+
const defs = scheduler.schedules || [];
|
|
61
61
|
for (const name of (scheduler.oneShotTimers || new Map()).keys()) {
|
|
62
62
|
if (scheduler.shouldSkip?.(name)) continue;
|
|
63
63
|
const def = defs.find((s) => s.name === name);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// Worker/HTTP runtime-lifecycle dispatch (activate_channel_bridge /
|
|
2
|
-
// reload_config).
|
|
3
|
-
// is deleted with Discord/Telegram; only the automation lifecycle remains.
|
|
2
|
+
// reload_config). Only the automation lifecycle is dispatched here.
|
|
4
3
|
// Lifecycle functions are threaded in as a bag of lazy getters so the module
|
|
5
4
|
// reads the live file-level references at call time.
|
|
5
|
+
import { scheduleErrorFields } from './schedule-errors.mjs';
|
|
6
|
+
|
|
6
7
|
function createToolDispatch({ isChannelsDegraded, lifecycle }) {
|
|
7
8
|
const {
|
|
8
9
|
getChannelBridgeActive,
|
|
@@ -13,6 +14,7 @@ function createToolDispatch({ isChannelsDegraded, lifecycle }) {
|
|
|
13
14
|
startChannelBridge,
|
|
14
15
|
stopOwnedRuntime,
|
|
15
16
|
reloadRuntimeConfig,
|
|
17
|
+
renameSchedule,
|
|
16
18
|
} = lifecycle;
|
|
17
19
|
|
|
18
20
|
async function handleToolCall(name, args, _signal) {
|
|
@@ -82,6 +84,14 @@ function createToolDispatch({ isChannelsDegraded, lifecycle }) {
|
|
|
82
84
|
};
|
|
83
85
|
break;
|
|
84
86
|
}
|
|
87
|
+
// The scheduler's owner moves a schedule row only while no run of it
|
|
88
|
+
// can start or be in flight (Scheduler.renameLocked). Resolves the
|
|
89
|
+
// renamed row as JSON text; a refusal is an isError result.
|
|
90
|
+
case 'rename_schedule': {
|
|
91
|
+
const saved = await renameSchedule(args.name, args.def, { timingChanged: args.timingChanged === true });
|
|
92
|
+
result = { content: [{ type: 'text', text: JSON.stringify(saved) }] };
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
85
95
|
// memory — handled by memory-service.mjs MCP
|
|
86
96
|
default:
|
|
87
97
|
result = {
|
|
@@ -94,6 +104,8 @@ function createToolDispatch({ isChannelsDegraded, lifecycle }) {
|
|
|
94
104
|
result = {
|
|
95
105
|
content: [{ type: 'text', text: `${name} failed: ${msg}` }],
|
|
96
106
|
isError: true,
|
|
107
|
+
// A schedule refusal keeps its code and public name; nothing else crosses.
|
|
108
|
+
...scheduleErrorFields(err),
|
|
97
109
|
};
|
|
98
110
|
}
|
|
99
111
|
return result;
|
|
@@ -26,8 +26,7 @@ CREATE SCHEMA IF NOT EXISTS webhooks;
|
|
|
26
26
|
CREATE TABLE IF NOT EXISTS webhooks.endpoints (
|
|
27
27
|
name text PRIMARY KEY,
|
|
28
28
|
description text NOT NULL DEFAULT '',
|
|
29
|
-
|
|
30
|
-
role text NOT NULL DEFAULT '',
|
|
29
|
+
role text NOT NULL DEFAULT '',
|
|
31
30
|
model text,
|
|
32
31
|
parser text,
|
|
33
32
|
secret text,
|
|
@@ -87,14 +86,13 @@ const getDb = createPgSchemaDb({
|
|
|
87
86
|
// The stored payload itself is never projected here (readEndpointLastPayload
|
|
88
87
|
// is its only read path); rows carry a presence flag.
|
|
89
88
|
const ENDPOINT_COLS =
|
|
90
|
-
'name, description,
|
|
89
|
+
'name, description, parser, secret, cwd, attachments, delivery, instructions, enabled, owner_agent_id, last_event_at, last_success_at, last_failed_at, last_skipped_at, consecutive_failures, result_delivery, (last_payload IS NOT NULL) AS has_last_payload, created_at, updated_at';
|
|
91
90
|
|
|
92
91
|
function rowToEndpoint(row) {
|
|
93
92
|
if (!row) return null;
|
|
94
93
|
return {
|
|
95
94
|
name: row.name,
|
|
96
95
|
description: row.description,
|
|
97
|
-
channelId: row.channel_id,
|
|
98
96
|
parser: row.parser,
|
|
99
97
|
cwd: row.cwd,
|
|
100
98
|
attachments: row.attachments || null,
|
|
@@ -180,7 +178,6 @@ export async function upsertEndpoint(def, { dataDir } = {}) {
|
|
|
180
178
|
const params = [
|
|
181
179
|
def.name,
|
|
182
180
|
def.description ?? '',
|
|
183
|
-
def.channelId ?? null,
|
|
184
181
|
'',
|
|
185
182
|
def.parser ?? null,
|
|
186
183
|
def.secret ?? null,
|
|
@@ -195,13 +192,12 @@ export async function upsertEndpoint(def, { dataDir } = {}) {
|
|
|
195
192
|
// not the definition.
|
|
196
193
|
const { rows } = await db.query(
|
|
197
194
|
`INSERT INTO webhooks.endpoints
|
|
198
|
-
(name, description,
|
|
199
|
-
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11
|
|
195
|
+
(name, description, role, parser, secret, cwd, attachments, delivery, instructions, enabled, owner_agent_id)
|
|
196
|
+
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11)
|
|
200
197
|
ON CONFLICT (name) DO UPDATE SET
|
|
201
198
|
owner_agent_id = EXCLUDED.owner_agent_id,
|
|
202
199
|
description = EXCLUDED.description,
|
|
203
|
-
|
|
204
|
-
role = EXCLUDED.role,
|
|
200
|
+
role = EXCLUDED.role,
|
|
205
201
|
parser = EXCLUDED.parser,
|
|
206
202
|
secret = EXCLUDED.secret,
|
|
207
203
|
cwd = EXCLUDED.cwd,
|
|
@@ -102,7 +102,6 @@ export function runWorkerBootstrap({
|
|
|
102
102
|
// Publish owner identity immediately so the SessionStart shim's
|
|
103
103
|
// owner_lead_alive() sees a live owner and uses the full connect budget
|
|
104
104
|
// instead of the 5s no-owner grace (fixes missing recap/core on restart).
|
|
105
|
-
// providerReady intentionally omitted — readiness stays gated until connect.
|
|
106
105
|
try {
|
|
107
106
|
refreshActiveInstance(instanceId);
|
|
108
107
|
} catch (e) {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
|
-
import { loadConfig,
|
|
4
|
+
import { loadConfig, DATA_DIR } from './config.mjs';
|
|
5
5
|
import { resolveVoiceRuntime } from './voice-runtime-fetcher.mjs';
|
|
6
6
|
import { whisperThreadCount } from './voice-transcription.mjs';
|
|
7
7
|
import { ensureReady, stopVoiceWhisperServer } from './whisper-server.mjs';
|
|
8
8
|
import { ensurePrivateRuntimeRoot, resolveRuntimeRoot } from '../../shared/runtime-root.mjs';
|
|
9
9
|
import { Scheduler } from './scheduler.mjs';
|
|
10
|
-
import {
|
|
10
|
+
import { renameSchedule as renameScheduleRow } from './schedules-db.mjs';
|
|
11
11
|
import { stripSoftWarns } from '../../agent/orchestrator/tool-loop-guard.mjs';
|
|
12
12
|
import { JsonStateFile } from './state-file.mjs';
|
|
13
13
|
import { writeJsonAtomicSync } from '../../shared/atomic-file.mjs';
|
|
@@ -93,7 +93,6 @@ if (isMixdogDebug()) {
|
|
|
93
93
|
);
|
|
94
94
|
}
|
|
95
95
|
let config = await loadConfig();
|
|
96
|
-
let provider = createProvider(config);
|
|
97
96
|
const INSTANCE_ID = makeInstanceId();
|
|
98
97
|
const TERMINAL_LEAD_PID = getTerminalLeadPid();
|
|
99
98
|
runWorkerBootstrap({
|
|
@@ -128,22 +127,13 @@ let _reloadDebounce = null;
|
|
|
128
127
|
const STATUS_FILE = getStatusPath(INSTANCE_ID);
|
|
129
128
|
const statusState = new JsonStateFile(STATUS_FILE, {});
|
|
130
129
|
statusState.ensure();
|
|
131
|
-
const scheduler = new Scheduler(config.
|
|
130
|
+
const scheduler = new Scheduler(config.schedules ?? []);
|
|
132
131
|
// A schedule fire is a turn in its owner bot's chat; the runner belongs to the
|
|
133
132
|
// session-runtime layer, so this worker entry injects it (lazy, like webhooks).
|
|
134
133
|
scheduler.setScheduleRunner(async (schedule, opts) => {
|
|
135
134
|
const { runScheduleSession } = await import('../../../session-runtime/schedule-session-run.mjs');
|
|
136
135
|
return runScheduleSession(schedule, opts);
|
|
137
136
|
});
|
|
138
|
-
// Register the pending-dispatch probe so the scheduler treats an in-flight
|
|
139
|
-
// bridge dispatch as "active" regardless of user-inbound silence.
|
|
140
|
-
scheduler.setPendingCheck(() => {
|
|
141
|
-
try {
|
|
142
|
-
return dispatchHasPending(DATA_DIR);
|
|
143
|
-
} catch {
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
137
|
let webhookServer = null;
|
|
148
138
|
let eventPipeline = null;
|
|
149
139
|
let bridgeRuntimeConnected = false;
|
|
@@ -157,10 +147,6 @@ const { startAutomationRuntime, startOwnedRuntime, stopOwnedRuntime, reloadRunti
|
|
|
157
147
|
setConfig: (v) => {
|
|
158
148
|
config = v;
|
|
159
149
|
},
|
|
160
|
-
getProvider: () => provider,
|
|
161
|
-
setProvider: (v) => {
|
|
162
|
-
provider = v;
|
|
163
|
-
},
|
|
164
150
|
getBridgeRuntimeConnected: () => bridgeRuntimeConnected,
|
|
165
151
|
setBridgeRuntimeConnected: (v) => {
|
|
166
152
|
bridgeRuntimeConnected = v;
|
|
@@ -184,7 +170,7 @@ const { startAutomationRuntime, startOwnedRuntime, stopOwnedRuntime, reloadRunti
|
|
|
184
170
|
wireWebhookHandlers,
|
|
185
171
|
wireEventQueueHandlers,
|
|
186
172
|
});
|
|
187
|
-
function injectAndRecord(
|
|
173
|
+
function injectAndRecord(content, options) {
|
|
188
174
|
// Strip soft-warn marker blocks (Tool-loop / Repeated-input / legacy
|
|
189
175
|
// Repeated-tool / Mixed-tool / Tool-budget / Same-file multi-chunk /
|
|
190
176
|
// Bash file-lookup / Iteration / 0-match advisory) from anywhere in the
|
|
@@ -198,22 +184,14 @@ function injectAndRecord(channelId, _name, content, options) {
|
|
|
198
184
|
const now = new Date();
|
|
199
185
|
const timeLabel = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')} `;
|
|
200
186
|
const sourceLabel = options?.type ? `${timeLabel}: ${options.type}` : timeLabel;
|
|
201
|
-
const meta = {
|
|
187
|
+
const meta = { user: sourceLabel, user_id: 'system', ts };
|
|
202
188
|
if (options?.instruction) meta.instruction = options.instruction;
|
|
203
189
|
if (options?.type) meta.type = options.type;
|
|
204
190
|
// `silent_to_agent` — lifecycle status pings (worker/iter/started echoes)
|
|
205
|
-
// must NOT land in Lead's context window
|
|
206
|
-
// surface them is retired, so silent pings are dropped entirely.
|
|
191
|
+
// must NOT land in Lead's context window, so silent pings are dropped.
|
|
207
192
|
if (options?.silent_to_agent === true) return;
|
|
208
193
|
sendNotifyToParent('notifications/claude/channel', { content, meta });
|
|
209
194
|
}
|
|
210
|
-
scheduler.setInjectHandler((channelId, name, content, options) => {
|
|
211
|
-
injectAndRecord(channelId, name, content, options);
|
|
212
|
-
});
|
|
213
|
-
// Interactive schedule fires may only inject while this process
|
|
214
|
-
// actually holds the live bridge seat; otherwise the scheduler falls back to
|
|
215
|
-
// the visible-session run so the fire is never lost.
|
|
216
|
-
scheduler.setInjectReadyCheck(() => bridgeRuntimeConnected && currentOwnerState().owned);
|
|
217
195
|
function wireWebhookHandlers() {
|
|
218
196
|
if (!webhookServer) return;
|
|
219
197
|
webhookServer.setEventPipeline(eventPipeline);
|
|
@@ -236,8 +214,8 @@ function wireWebhookHandlers() {
|
|
|
236
214
|
}
|
|
237
215
|
function wireEventQueueHandlers(eventQueue) {
|
|
238
216
|
if (!eventQueue) return;
|
|
239
|
-
eventQueue.setInjectHandler((
|
|
240
|
-
injectAndRecord(
|
|
217
|
+
eventQueue.setInjectHandler((_name, content, options) => {
|
|
218
|
+
injectAndRecord(content, options);
|
|
241
219
|
});
|
|
242
220
|
// Defensive ownership probe: the queue tick should only run in the active
|
|
243
221
|
// owner process. Non-owner instances see bridgeRuntimeConnected=false and
|
|
@@ -261,9 +239,17 @@ const { handleToolCall } = createToolDispatch({
|
|
|
261
239
|
},
|
|
262
240
|
writeBridgeState,
|
|
263
241
|
notifyRemoteAcquired,
|
|
264
|
-
startChannelBridge: () => start({
|
|
242
|
+
startChannelBridge: () => start({ bridge: true }),
|
|
265
243
|
stopOwnedRuntime,
|
|
266
244
|
reloadRuntimeConfig,
|
|
245
|
+
// Rename and re-arm under one reservation: the scheduler is reloaded from
|
|
246
|
+
// the renamed row (timers and one-shots of the old name cleared) before
|
|
247
|
+
// the name is released for fires.
|
|
248
|
+
renameSchedule: (name, def, opts) =>
|
|
249
|
+
scheduler.renameLocked(name, () => renameScheduleRow(name, def, opts), {
|
|
250
|
+
newName: def.name,
|
|
251
|
+
reload: reloadRuntimeConfig,
|
|
252
|
+
}),
|
|
267
253
|
},
|
|
268
254
|
});
|
|
269
255
|
function ensureConfigWatcher() {
|
|
@@ -279,7 +265,7 @@ function ensureConfigWatcher() {
|
|
|
279
265
|
} catch {}
|
|
280
266
|
}
|
|
281
267
|
async function start(options = {}) {
|
|
282
|
-
if (options?.
|
|
268
|
+
if (options?.bridge === false) {
|
|
283
269
|
channelBridgeActive = false;
|
|
284
270
|
writeBridgeState(false);
|
|
285
271
|
await startAutomationRuntime();
|
|
@@ -299,7 +285,7 @@ async function start(options = {}) {
|
|
|
299
285
|
}
|
|
300
286
|
// Hot-reload config on file change (schedules/webhooks/events).
|
|
301
287
|
// Cross-process edits invalidate the raw config cache before the debounced
|
|
302
|
-
// reload so both
|
|
288
|
+
// reload so both bridge and automation-only daemon modes stay current.
|
|
303
289
|
ensureConfigWatcher();
|
|
304
290
|
// Pre-warm the whisper-server manager once at owner startup so the first
|
|
305
291
|
// voice transcription does not pay cold-start cost. Non-blocking: failures
|
|
@@ -352,7 +338,6 @@ if (_isWorkerMode && process.send && process.env.MIXDOG_DAEMON_HOST !== '1') {
|
|
|
352
338
|
clearServerPid,
|
|
353
339
|
instanceId: INSTANCE_ID,
|
|
354
340
|
statusState,
|
|
355
|
-
getProvider: () => provider,
|
|
356
341
|
getConfig: () => config,
|
|
357
342
|
handleMemoryCallResponse,
|
|
358
343
|
handleToolCall,
|
|
@@ -35,8 +35,13 @@ const ACTIONS = [
|
|
|
35
35
|
'menu',
|
|
36
36
|
'clipboard',
|
|
37
37
|
'launch',
|
|
38
|
+
'saved_login',
|
|
38
39
|
];
|
|
39
40
|
|
|
41
|
+
// Which value of a saved login saved_login types (the host checks the focused
|
|
42
|
+
// field's kind before typing it).
|
|
43
|
+
const SAVED_LOGIN_FIELDS = ['username', 'password'];
|
|
44
|
+
|
|
40
45
|
const windowTarget = {
|
|
41
46
|
window_id: {
|
|
42
47
|
type: 'string',
|
|
@@ -347,6 +352,28 @@ export const COMPUTER_ACTION_CONTRACTS = [
|
|
|
347
352
|
['app']
|
|
348
353
|
)
|
|
349
354
|
),
|
|
355
|
+
branch(
|
|
356
|
+
'saved_login',
|
|
357
|
+
input(
|
|
358
|
+
{
|
|
359
|
+
...windowTarget,
|
|
360
|
+
...appTarget,
|
|
361
|
+
savedAccount: {
|
|
362
|
+
type: 'string',
|
|
363
|
+
minLength: 1,
|
|
364
|
+
description:
|
|
365
|
+
"Fallback sign-in in the user's own browser; prefer its existing session/SSO or Browser Use's saved sign-in. Saved login (username or masked label; a miss lists the site's labels) written after host checks into the focused field of a Chrome/Edge HTTPS page. The site receives it. A password is kept from you and its browser's pixels are withheld this turn, but a page that redisplays it can expose it, and other programs of the same Windows user are outside this protection; a username is not hidden. On refusal hand the secret to the user (ask_user secret, surface computer).",
|
|
366
|
+
},
|
|
367
|
+
field: {
|
|
368
|
+
type: 'string',
|
|
369
|
+
enum: SAVED_LOGIN_FIELDS,
|
|
370
|
+
description:
|
|
371
|
+
"username (text field) or password (password field). One-time codes, passkeys, security keys and app approvals are the user's step: ask_user takeover.",
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
['savedAccount', 'field']
|
|
375
|
+
)
|
|
376
|
+
),
|
|
350
377
|
];
|
|
351
378
|
|
|
352
379
|
// A JSON Schema 2020-12 object root with no root combinator (Anthropic
|
|
@@ -396,7 +423,7 @@ for (const actionBranch of COMPUTER_ACTION_CONTRACTS) {
|
|
|
396
423
|
// Actions that drive one exact window. They carry exactly one window target:
|
|
397
424
|
// the exact window_id, or an app label the host resolves to one window and
|
|
398
425
|
// refuses when it matches more than one.
|
|
399
|
-
const WINDOW_TARGET_ACTIONS = new Set(['act', 'window', 'menu', 'verify']);
|
|
426
|
+
const WINDOW_TARGET_ACTIONS = new Set(['act', 'window', 'menu', 'verify', 'saved_login']);
|
|
400
427
|
// The host command each window operation becomes; every other operation is a
|
|
401
428
|
// window_state change carrying the operation as its state.
|
|
402
429
|
const WINDOW_OPERATION_ACTIONS = Object.freeze({
|
|
@@ -564,6 +591,11 @@ function launchError(input) {
|
|
|
564
591
|
return null;
|
|
565
592
|
}
|
|
566
593
|
|
|
594
|
+
function savedLoginError(input) {
|
|
595
|
+
if (!String(input.savedAccount || '').trim()) return 'Computer Use saved_login savedAccount must not be empty';
|
|
596
|
+
return null;
|
|
597
|
+
}
|
|
598
|
+
|
|
567
599
|
function listError(input) {
|
|
568
600
|
if (hasOwn(input, 'limit') && input.kind !== 'history') {
|
|
569
601
|
return 'Computer Use list limit applies to kind="history"';
|
|
@@ -584,6 +616,7 @@ const ACTION_RULES = {
|
|
|
584
616
|
window: windowError,
|
|
585
617
|
clipboard: clipboardError,
|
|
586
618
|
launch: launchError,
|
|
619
|
+
saved_login: savedLoginError,
|
|
587
620
|
};
|
|
588
621
|
|
|
589
622
|
export function validateComputerToolArgs(rawArgs) {
|
|
@@ -686,6 +719,14 @@ export function toComputerHostCommand(rawArgs) {
|
|
|
686
719
|
command.action = inputValue.operation === 'write' ? 'clipboard_write' : 'clipboard_read';
|
|
687
720
|
delete command.operation;
|
|
688
721
|
break;
|
|
722
|
+
case 'saved_login':
|
|
723
|
+
// Always foreground: the value goes to the field focused in the
|
|
724
|
+
// browser window the host verified, never through window messages.
|
|
725
|
+
command.action = 'fill_saved_login';
|
|
726
|
+
command.saved_account = inputValue.savedAccount;
|
|
727
|
+
command.delivery = 'foreground';
|
|
728
|
+
delete command.savedAccount;
|
|
729
|
+
break;
|
|
689
730
|
default:
|
|
690
731
|
command.action = args.action;
|
|
691
732
|
}
|
|
@@ -29,6 +29,8 @@ action('input_recovery_state', nativeRead);
|
|
|
29
29
|
action('input_idle_state', nativeRead);
|
|
30
30
|
action('ocr_image', nativeRead);
|
|
31
31
|
action('ocr_status', nativeRead);
|
|
32
|
+
// Host-internal: whether a saved-login owner's runtime process has ended.
|
|
33
|
+
action('process_fate', nativeRead);
|
|
32
34
|
action('release_session', { retainNativeRefs: true });
|
|
33
35
|
action('release_cursor_theme', { retainNativeRefs: true });
|
|
34
36
|
// Handing held input, focus and pointer back changes no target's content, so a
|
|
@@ -98,8 +100,14 @@ for (const name of [
|
|
|
98
100
|
});
|
|
99
101
|
}
|
|
100
102
|
action('clipboard_write', { foreground: true });
|
|
103
|
+
// A saved login written into the focused field of the user's browser window:
|
|
104
|
+
// an input bound to a fresh observation, always on the foreground lane, with no
|
|
105
|
+
// automatic capture (the reply never carries the field it filled).
|
|
106
|
+
action('fill_saved_login', { observationBound: true, foreground: true, policy: 'act' });
|
|
101
107
|
action('sequence', { policy: 'act' });
|
|
102
|
-
|
|
108
|
+
// turn_settle: the runtime's settlement of one agent turn (turn_id), which
|
|
109
|
+
// alone retires a saved-login fill's protection (desktop secret-input.ts).
|
|
110
|
+
for (const name of ['execution_end', 'session_release', 'session_abort', 'turn_settle']) {
|
|
103
111
|
action(name, { lifecycle: true, observeOnly: true });
|
|
104
112
|
}
|
|
105
113
|
export const COMPUTER_ACTIONS = Object.freeze(catalogue);
|
|
@@ -25,6 +25,8 @@ import { MAX_COMPUTER_REQUEST_BYTES, readComputerBridgeJson, validateComputerRep
|
|
|
25
25
|
import { computerActionHas } from './actions.mjs';
|
|
26
26
|
import { linuxCaptureFallback, linuxComputerPreflight } from './linux-readiness.mjs';
|
|
27
27
|
import { continuePendingComputerWork, isPendingComputerWork } from './pending-continuation.mjs';
|
|
28
|
+
import { randomUUID } from 'node:crypto';
|
|
29
|
+
import { request as httpRequest } from 'node:http';
|
|
28
30
|
|
|
29
31
|
export { canonicalComputerResultText };
|
|
30
32
|
|
|
@@ -53,6 +55,18 @@ const pendingComputerSessionReleases = new Map();
|
|
|
53
55
|
// explicit release, so shutdown needs the full set.
|
|
54
56
|
const hostBoundComputerSessions = new Set();
|
|
55
57
|
const activeComputerExecutions = new Set();
|
|
58
|
+
// Per session, the newest agent turn that sent a saved-login fill whose
|
|
59
|
+
// settlement the desktop has not yet accepted. Aborts never clear it.
|
|
60
|
+
const savedLoginTurns = new Map();
|
|
61
|
+
/** This runtime process as the owner of its saved-login fills: the desktop
|
|
62
|
+
* keeps a fill's protection until its turn settles or this owner is gone
|
|
63
|
+
* (apps/desktop/src/main/secret-input.ts SavedLoginTurn). */
|
|
64
|
+
export const SAVED_LOGIN_OWNER_ID = randomUUID();
|
|
65
|
+
// The owner connection: one held POST /owner (owner id and this process id)
|
|
66
|
+
// to the bridge it was opened on. A close only detaches it on the desktop;
|
|
67
|
+
// the desktop retires this owner early only when the OS proves this process
|
|
68
|
+
// ended. The socket never keeps the process alive.
|
|
69
|
+
let savedLoginOwner = null;
|
|
56
70
|
const BRIDGE_UNAVAILABLE_MESSAGE =
|
|
57
71
|
'computer use is unavailable; open the Mixdog desktop app and enable Computer Use in settings';
|
|
58
72
|
|
|
@@ -269,7 +283,15 @@ async function executeComputerToolInner(rawArgs, context, note) {
|
|
|
269
283
|
command = fallback.command;
|
|
270
284
|
note.text = fallback.note;
|
|
271
285
|
}
|
|
272
|
-
|
|
286
|
+
// A saved-login fill names its agent turn: the desktop keeps the fill's
|
|
287
|
+
// protection until that turn's settlement (settleSavedLoginTurn).
|
|
288
|
+
const turnId = Number(context?.turnId) || 0;
|
|
289
|
+
const savedLoginTurn = command.action === 'fill_saved_login' && sessionId && turnId > 0 ? turnId : 0;
|
|
290
|
+
const encoded = JSON.stringify({
|
|
291
|
+
...command,
|
|
292
|
+
...(sessionId ? { session_id: sessionId } : {}),
|
|
293
|
+
...(savedLoginTurn ? { turn_id: savedLoginTurn, runtime_id: SAVED_LOGIN_OWNER_ID } : {}),
|
|
294
|
+
});
|
|
273
295
|
if (Buffer.byteLength(encoded) > MAX_COMPUTER_REQUEST_BYTES) {
|
|
274
296
|
return computerErrorResult('Error: computer request exceeds byte limit; no input was dispatched');
|
|
275
297
|
}
|
|
@@ -286,7 +308,14 @@ async function executeComputerToolInner(rawArgs, context, note) {
|
|
|
286
308
|
}
|
|
287
309
|
const releaseError = await awaitPendingSessionRelease(sessionId, args, context);
|
|
288
310
|
if (releaseError) return releaseError;
|
|
311
|
+
if (savedLoginTurn) {
|
|
312
|
+
const ownerError = await savedLoginOwnerError(discovery, sessionId, args, context);
|
|
313
|
+
if (ownerError) return ownerError;
|
|
314
|
+
}
|
|
289
315
|
trackComputerSession(sessionId, command);
|
|
316
|
+
// Recorded before the request leaves: the fill may arm its protection even
|
|
317
|
+
// when its reply is lost, so the turn's settlement is owed regardless.
|
|
318
|
+
if (savedLoginTurn) savedLoginTurns.set(sessionId, Math.max(savedLoginTurns.get(sessionId) || 0, savedLoginTurn));
|
|
290
319
|
const posted = await postWithBridgeRecovery(discovery, command, encoded, sessionId, context);
|
|
291
320
|
if (!posted.response) return posted;
|
|
292
321
|
const { bridge, response } = posted;
|
|
@@ -362,7 +391,7 @@ async function settlePendingComputerWork(value, command, bridge, sessionId, cont
|
|
|
362
391
|
}
|
|
363
392
|
}
|
|
364
393
|
|
|
365
|
-
async function sendComputerSessionControl(sessionId, action, timeoutMs) {
|
|
394
|
+
async function sendComputerSessionControl(sessionId, action, timeoutMs, extra = {}) {
|
|
366
395
|
const discovery = readBridgeDiscovery(DISCOVERY_FILE);
|
|
367
396
|
if (!discovery) return false;
|
|
368
397
|
try {
|
|
@@ -371,6 +400,7 @@ async function sendComputerSessionControl(sessionId, action, timeoutMs) {
|
|
|
371
400
|
{
|
|
372
401
|
action,
|
|
373
402
|
session_id: sessionId,
|
|
403
|
+
...extra,
|
|
374
404
|
},
|
|
375
405
|
{ timeoutMs }
|
|
376
406
|
);
|
|
@@ -381,12 +411,40 @@ async function sendComputerSessionControl(sessionId, action, timeoutMs) {
|
|
|
381
411
|
}
|
|
382
412
|
}
|
|
383
413
|
|
|
414
|
+
/** Runtime-only, at request time: bind `requestId` to the exact window and
|
|
415
|
+
* field ref the agent named (desktop secret-input.ts bindComputerSecret).
|
|
416
|
+
* Answers 'bound' or 'no_field'; no desktop or an unknown answer is 'blocked'. */
|
|
417
|
+
export async function computerSecretBind(sessionId, requestId, { ref = '', windowId = '', signal } = {}) {
|
|
418
|
+
const discovery = readBridgeDiscovery(DISCOVERY_FILE);
|
|
419
|
+
if (!discovery || !sessionId || !requestId) return 'blocked';
|
|
420
|
+
try {
|
|
421
|
+
const response = await postComputerCommand(
|
|
422
|
+
discovery,
|
|
423
|
+
{
|
|
424
|
+
action: 'secret_bind',
|
|
425
|
+
session_id: String(sessionId),
|
|
426
|
+
request_id: String(requestId),
|
|
427
|
+
ref: String(ref),
|
|
428
|
+
window_id: String(windowId),
|
|
429
|
+
},
|
|
430
|
+
{ signal }
|
|
431
|
+
);
|
|
432
|
+
const body = await readComputerBridgeJson(response);
|
|
433
|
+
const text = response.ok && body?.ok === true ? body.value?.text : '';
|
|
434
|
+
return ['bound', 'no_field'].includes(text) ? text : 'blocked';
|
|
435
|
+
} catch {
|
|
436
|
+
return 'blocked';
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
384
440
|
/** Runtime-only: type the secret the user handed the desktop for `requestId`
|
|
385
|
-
* into the
|
|
386
|
-
* here; the host answers only
|
|
441
|
+
* into the window and field it was bound to (computerSecretBind) once. The
|
|
442
|
+
* value never passes through here; the host answers only the outcome
|
|
443
|
+
* ('entered', 'no_field', 'page_changed', 'blocked', 'expired'); no desktop
|
|
444
|
+
* or an unknown answer is 'blocked'. */
|
|
387
445
|
export async function computerSecretInput(sessionId, requestId, { ref = '', windowId = '', signal } = {}) {
|
|
388
446
|
const discovery = readBridgeDiscovery(DISCOVERY_FILE);
|
|
389
|
-
if (!discovery || !sessionId || !requestId) return '
|
|
447
|
+
if (!discovery || !sessionId || !requestId) return 'blocked';
|
|
390
448
|
try {
|
|
391
449
|
const response = await postComputerCommand(
|
|
392
450
|
discovery,
|
|
@@ -400,9 +458,10 @@ export async function computerSecretInput(sessionId, requestId, { ref = '', wind
|
|
|
400
458
|
{ signal }
|
|
401
459
|
);
|
|
402
460
|
const body = await readComputerBridgeJson(response);
|
|
403
|
-
|
|
461
|
+
const text = response.ok && body?.ok === true ? body.value?.text : '';
|
|
462
|
+
return ['entered', 'no_field', 'page_changed', 'blocked', 'expired'].includes(text) ? text : 'blocked';
|
|
404
463
|
} catch {
|
|
405
|
-
return '
|
|
464
|
+
return 'blocked';
|
|
406
465
|
}
|
|
407
466
|
}
|
|
408
467
|
|
|
@@ -423,12 +482,125 @@ async function abortComputerSession(sessionId) {
|
|
|
423
482
|
* desktop back, keeping the warm worker and observation refs for a possible follow-up. */
|
|
424
483
|
export async function endComputerExecution(sessionId) {
|
|
425
484
|
const id = String(sessionId || '').trim();
|
|
426
|
-
if (!id
|
|
485
|
+
if (!id) return false;
|
|
486
|
+
await settleSavedLoginTurn(id);
|
|
487
|
+
if (!activeComputerExecutions.has(id)) return false;
|
|
427
488
|
const ended = await sendComputerSessionControl(id, 'execution_end', EXECUTION_END_TIMEOUT_MS);
|
|
428
489
|
if (ended) activeComputerExecutions.delete(id);
|
|
429
490
|
return ended;
|
|
430
491
|
}
|
|
431
492
|
|
|
493
|
+
/** Agent-turn settlement for a session that filled a saved login: tell the
|
|
494
|
+
* desktop the turn is over so that fill's protection can retire. Separate
|
|
495
|
+
* from input cleanup and independent of any abort; a settlement the desktop
|
|
496
|
+
* did not accept stays owed and is sent again at the session's next one.
|
|
497
|
+
* `endedTurnId` is the turn that ended when the caller knows it (the
|
|
498
|
+
* session's terminal state); otherwise the newest owed turn is the one
|
|
499
|
+
* ending (the lead's turn settlement). */
|
|
500
|
+
async function settleSavedLoginTurn(sessionId, endedTurnId = 0) {
|
|
501
|
+
const owed = savedLoginTurns.get(sessionId);
|
|
502
|
+
if (!owed) return;
|
|
503
|
+
if (endedTurnId > 0 && owed > endedTurnId) return;
|
|
504
|
+
const accepted = await sendComputerSessionControl(sessionId, 'turn_settle', EXECUTION_END_TIMEOUT_MS, {
|
|
505
|
+
turn_id: owed,
|
|
506
|
+
runtime_id: SAVED_LOGIN_OWNER_ID,
|
|
507
|
+
});
|
|
508
|
+
if (accepted && savedLoginTurns.get(sessionId) === owed) savedLoginTurns.delete(sessionId);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/** A session's agent turn reached its terminal state (done, error or
|
|
512
|
+
* cancelled; manager/runtime-liveness.mjs, for lead and sub-agent sessions
|
|
513
|
+
* alike): settle its saved-login fills. */
|
|
514
|
+
export async function finishComputerTurn(sessionId, turnId) {
|
|
515
|
+
const id = String(sessionId || '').trim();
|
|
516
|
+
if (!id || !(Number(turnId) > 0)) return;
|
|
517
|
+
await settleSavedLoginTurn(id, Number(turnId));
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Returns the error result that ends a saved-login call whose owner connection
|
|
521
|
+
// is not attached, or null to proceed. Nothing was sent in any of these cases.
|
|
522
|
+
async function savedLoginOwnerError(discovery, sessionId, args, context) {
|
|
523
|
+
let attached;
|
|
524
|
+
try {
|
|
525
|
+
attached = await attachSavedLoginOwner(discovery, context.signal);
|
|
526
|
+
} catch (error) {
|
|
527
|
+
if (context.signal?.aborted) return cancelledComputerResult(sessionId, false);
|
|
528
|
+
return computerErrorResult(
|
|
529
|
+
formatComputerToolError(
|
|
530
|
+
`saved_login_unavailable: the desktop did not answer the owner attachment (${error.name}); no input was sent`,
|
|
531
|
+
args
|
|
532
|
+
)
|
|
533
|
+
);
|
|
534
|
+
}
|
|
535
|
+
if (attached) return null;
|
|
536
|
+
return computerErrorResult(
|
|
537
|
+
formatComputerToolError(
|
|
538
|
+
'saved_login_unavailable: the desktop did not accept this runtime as the owner of its saved-login fills; no input was sent',
|
|
539
|
+
args
|
|
540
|
+
)
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/** Open (or reuse) this runtime's owner connection to `discovery`'s bridge:
|
|
545
|
+
* true once the desktop answered it, false when it refused or is unreachable.
|
|
546
|
+
* The shared handshake is bounded by the bridge request timeout (rejecting
|
|
547
|
+
* with its TimeoutError and resetting the shared state); each caller's wait
|
|
548
|
+
* also ends on its own `signal` without closing the shared connection. */
|
|
549
|
+
function attachSavedLoginOwner(discovery, signal) {
|
|
550
|
+
const current = savedLoginOwner;
|
|
551
|
+
if (current && current.port === discovery.port && current.token === discovery.token) {
|
|
552
|
+
return waitForComputerRelease(current.attached, signal);
|
|
553
|
+
}
|
|
554
|
+
current?.request.destroy();
|
|
555
|
+
const owner = { port: discovery.port, token: discovery.token, request: null, attached: null };
|
|
556
|
+
owner.attached = new Promise((resolve, reject) => {
|
|
557
|
+
const body = JSON.stringify({ runtime_id: SAVED_LOGIN_OWNER_ID, pid: process.pid });
|
|
558
|
+
const handshake = AbortSignal.timeout(REQUEST_TIMEOUT_MS);
|
|
559
|
+
const forget = () => {
|
|
560
|
+
handshake.removeEventListener('abort', onHandshakeTimeout);
|
|
561
|
+
if (savedLoginOwner === owner) savedLoginOwner = null;
|
|
562
|
+
resolve(false);
|
|
563
|
+
};
|
|
564
|
+
// Rejects first, so the callers see the timeout; forgetting at once lets
|
|
565
|
+
// the next fill attach afresh instead of waiting on the closing socket.
|
|
566
|
+
function onHandshakeTimeout() {
|
|
567
|
+
reject(handshake.reason);
|
|
568
|
+
forget();
|
|
569
|
+
owner.request.destroy();
|
|
570
|
+
}
|
|
571
|
+
handshake.addEventListener('abort', onHandshakeTimeout, { once: true });
|
|
572
|
+
owner.request = httpRequest(
|
|
573
|
+
{
|
|
574
|
+
host: '127.0.0.1',
|
|
575
|
+
port: discovery.port,
|
|
576
|
+
path: '/owner',
|
|
577
|
+
method: 'POST',
|
|
578
|
+
agent: false,
|
|
579
|
+
headers: { ...computerCommandHeaders(discovery), 'content-length': Buffer.byteLength(body) },
|
|
580
|
+
},
|
|
581
|
+
(response) => {
|
|
582
|
+
response.once('close', forget);
|
|
583
|
+
response.once('error', forget);
|
|
584
|
+
if (response.statusCode !== 200) {
|
|
585
|
+
response.resume();
|
|
586
|
+
forget();
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
response.once('data', () => {
|
|
590
|
+
handshake.removeEventListener('abort', onHandshakeTimeout);
|
|
591
|
+
resolve(true);
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
);
|
|
595
|
+
owner.request.once('socket', (socket) => socket.unref());
|
|
596
|
+
owner.request.once('error', forget);
|
|
597
|
+
owner.request.once('close', forget);
|
|
598
|
+
owner.request.end(body);
|
|
599
|
+
});
|
|
600
|
+
savedLoginOwner = owner;
|
|
601
|
+
return waitForComputerRelease(owner.attached, signal);
|
|
602
|
+
}
|
|
603
|
+
|
|
432
604
|
function cancelDeferredComputerSessionRelease(sessionId) {
|
|
433
605
|
const id = String(sessionId || '').trim();
|
|
434
606
|
if (!id) return false;
|
|
@@ -74,13 +74,13 @@ export const COMPUTER_CORE_ACTION_SCHEMA = {
|
|
|
74
74
|
text: {
|
|
75
75
|
type: 'string',
|
|
76
76
|
maxLength: 30_000,
|
|
77
|
-
description: `Literal text; foreground cap ${MAX_COMPUTER_FOREGROUND_TEXT_CHARS} UTF-16 code units per action.`,
|
|
77
|
+
description: `Literal text; foreground cap ${MAX_COMPUTER_FOREGROUND_TEXT_CHARS} UTF-16 code units per action. Never a password or one-time code, even one shown on screen: saved_login or ask_user.`,
|
|
78
78
|
},
|
|
79
79
|
value: {
|
|
80
80
|
type: 'string',
|
|
81
81
|
maxLength: 30_000,
|
|
82
82
|
description:
|
|
83
|
-
'set_value replacement for an element that advertises set_value; writes the control directly, without focus or keystrokes.',
|
|
83
|
+
'set_value replacement for an element that advertises set_value; writes the control directly, without focus or keystrokes. Never a password or one-time code, even one shown on screen: saved_login or ask_user.',
|
|
84
84
|
},
|
|
85
85
|
keys: {
|
|
86
86
|
type: 'string',
|