mixdog 1.2.5 → 1.3.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/simple-icons-CC0-1.0.txt +30 -0
- package/NOTICE.md +19 -0
- package/package.json +4 -1
- package/scripts/check-model-recommendations.mjs +89 -0
- package/scripts/gate-local.mjs +7 -0
- package/scripts/lib/gate-scheduler.mjs +2 -2
- package/scripts/lib/isolated-test-env.mjs +16 -0
- package/scripts/lib/run-node-tests.mjs +5 -14
- package/scripts/provider-pingpong-live.mjs +9 -9
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +5 -4
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +17 -0
- package/src/defaults/skills/browser-use/SKILL.md +7 -1
- package/src/defaults/skills/computer-use/SKILL.md +3 -1
- package/src/defaults/skills/memory-management/SKILL.md +4 -1
- package/src/defaults/skills/setup/references/actions.md +11 -4
- package/src/defaults/skills/setup-guide/SKILL.md +175 -0
- package/src/defaults/skills/setup-guide/model-recommendations.json +333 -0
- package/src/defaults/skills/visualize/SKILL.md +3 -2
- package/src/lib/rules-builder.cjs +56 -7
- package/src/output-styles/common.md +22 -6
- package/src/output-styles/detailed.md +7 -5
- package/src/output-styles/minimal.md +7 -3
- package/src/output-styles/simple.md +2 -3
- package/src/rules/agent/AGENT.md +7 -1
- package/src/rules/agent-mode/AGENT_MODE.md +24 -0
- package/src/rules/agent-mode/MIXY.md +21 -0
- package/src/rules/agent-mode/ROUTINE.md +6 -0
- package/src/rules/lead/LEAD.md +9 -4
- package/src/rules/shared/10-tool-workflow.md +2 -1
- package/src/rules/shared/60-verification.md +4 -5
- package/src/rules/shared/70-delivery.md +3 -0
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -1
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +86 -0
- package/src/runtime/agent/orchestrator/config.mjs +6 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +77 -14
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +182 -13
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +5 -3
- package/src/runtime/agent/orchestrator/internal-agents.mjs +10 -0
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +215 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +58 -64
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +10 -1
- package/src/runtime/agent/orchestrator/mcp/client.mjs +122 -15
- package/src/runtime/agent/orchestrator/mcp/oauth-account.mjs +97 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +2 -3
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +49 -0
- package/src/runtime/agent/orchestrator/mcp/oauth-credentials.mjs +59 -9
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +32 -7
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +45 -6
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +195 -6
- package/src/runtime/agent/orchestrator/mcp/server-connectors.mjs +17 -0
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +41 -19
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +11 -5
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/catalog-deadline.mjs +163 -0
- package/src/runtime/agent/orchestrator/providers/catalog-failures.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +38 -14
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +100 -26
- package/src/runtime/agent/orchestrator/providers/lib/send-callbacks.mjs +24 -0
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +4 -0
- 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-compat-models.mjs +49 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +0 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +17 -12
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +11 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +45 -16
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-connect.mjs +196 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +74 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-login.mjs +194 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-tokens.mjs +353 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +293 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +33 -100
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/registry.mjs +41 -27
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +98 -4
- package/src/runtime/agent/orchestrator/runtime-core/context-status-shape.mjs +4 -0
- package/src/runtime/agent/orchestrator/runtime-core/extension-scopes.mjs +6 -4
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +15 -8
- package/src/runtime/agent/orchestrator/runtime-core/plugin-mcp.mjs +1 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +12 -6
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +32 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +10 -4
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +4 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +50 -20
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/agent-home.d.mts +4 -0
- package/src/runtime/agent/orchestrator/session/agent-home.mjs +33 -0
- package/src/runtime/agent/orchestrator/session/agent-mode.mjs +62 -0
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.d.mts +31 -0
- package/src/runtime/agent/orchestrator/session/agent-room-supervisor.mjs +241 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +162 -0
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +641 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +7 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +74 -13
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +102 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +8 -2
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +165 -0
- package/src/runtime/agent/orchestrator/session/human-gate/held-message.mjs +95 -0
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +221 -0
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +195 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +167 -0
- package/src/runtime/agent/orchestrator/session/lifecycle-scan.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +39 -2
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +82 -33
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +11 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +13 -3
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +6 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/manager/pending-lifecycle-epoch.mjs +0 -8
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +10 -7
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +62 -22
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +44 -16
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -5
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +81 -34
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +39 -4
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +27 -5
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +55 -8
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +3 -2
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs +58 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +24 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +32 -5
- package/src/runtime/agent/orchestrator/session/request-fork.mjs +47 -0
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +70 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +277 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/side-question.mjs +5 -43
- package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +73 -6
- package/src/runtime/agent/orchestrator/session/store/load-session.mjs +40 -0
- package/src/runtime/agent/orchestrator/session/store/save-fault.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-header.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +258 -43
- package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +325 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +84 -21
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -12
- package/src/runtime/agent/orchestrator/session/store-summary-last-message.mjs +46 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +46 -30
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +0 -4
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +144 -45
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +32 -13
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +364 -38
- package/src/runtime/agent/orchestrator/session/store.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/task-wait-control.mjs +43 -12
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +23 -6
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +44 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -6
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +13 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/benign-exit.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +40 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +37 -34
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +0 -4
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +29 -27
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/find-files-tool.mjs +28 -11
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +12 -3
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +203 -101
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +90 -41
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-delivery.mjs +199 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +12 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +165 -39
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +25 -13
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +113 -5
- package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +7 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +19 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-line-collector.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +25 -7
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-render.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +12 -5
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +61 -22
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +32 -8
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +193 -19
- package/src/runtime/agent/orchestrator/tools/builtin/shell-direct-exe.mjs +57 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +123 -32
- package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +26 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +13 -28
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +90 -11
- package/src/runtime/agent/orchestrator/tools/builtin/wait-budgets.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +54 -10
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +22 -28
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +11 -7
- package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +126 -9
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +15 -6
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +64 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +10 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promotion-results.mjs +13 -3
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +104 -55
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +39 -23
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/attachments/office-extract.mjs +11 -9
- package/src/runtime/browser-bridge/client.mjs +24 -0
- package/src/runtime/channels/lib/scheduler.mjs +40 -12
- package/src/runtime/channels/lib/schedules-db.mjs +71 -12
- package/src/runtime/channels/lib/webhook/session-dispatch.mjs +36 -16
- package/src/runtime/channels/lib/webhook.mjs +0 -1
- package/src/runtime/channels/lib/webhooks-db.mjs +100 -10
- package/src/runtime/channels/lib/worker-main.mjs +17 -20
- package/src/runtime/computer-bridge/client.mjs +28 -1
- package/src/runtime/connectors/gmail-app-password.mjs +690 -0
- package/src/runtime/connectors/google-mcp.mjs +446 -0
- package/src/runtime/memory/lib/core-memory-access.mjs +69 -0
- package/src/runtime/memory/lib/core-memory-file.mjs +16 -8
- package/src/runtime/memory/lib/core-memory-index.mjs +15 -9
- package/src/runtime/memory/lib/core-memory-management.mjs +10 -4
- package/src/runtime/memory/lib/core-memory-store.mjs +53 -30
- package/src/runtime/memory/lib/core-memory-uniqueness.mjs +10 -6
- package/src/runtime/memory/lib/embedding-tokenizer.mjs +32 -18
- package/src/runtime/memory/lib/http-router/session-routes.mjs +3 -2
- package/src/runtime/memory/lib/memory-action-handlers/core-actions.mjs +44 -14
- package/src/runtime/memory/lib/memory-schema/core-and-meta.mjs +11 -0
- package/src/runtime/memory/lib/memory.mjs +7 -1
- package/src/runtime/memory/lib/query-core-recall.mjs +9 -1
- package/src/runtime/memory/lib/query-hybrid-search.mjs +2 -0
- package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -1
- package/src/runtime/memory/lib/tool-call-handler.mjs +9 -5
- package/src/runtime/memory/tool-defs.mjs +5 -0
- package/src/runtime/office/authoring/pptx-script-normalize.mjs +11 -8
- package/src/runtime/office/core/tabular.mjs +1 -1
- package/src/runtime/office/design/library/design-template-inspect.mjs +7 -4
- package/src/runtime/office/portable/docx-formatting.mjs +1 -1
- package/src/runtime/office/portable/docx-runs.mjs +1 -1
- package/src/runtime/office/portable/docx-tracked-edits.mjs +2 -2
- package/src/runtime/office/portable/portable-docx-edits.mjs +11 -10
- package/src/runtime/office/portable/portable-docx-operations.mjs +21 -17
- package/src/runtime/office/portable/portable-docx-parts.mjs +15 -9
- package/src/runtime/office/portable/portable-docx-styles.mjs +4 -1
- package/src/runtime/office/portable/portable-docx-xml.mjs +9 -9
- package/src/runtime/office/portable/portable-opc.mjs +27 -13
- package/src/runtime/office/portable/portable-pivot.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-chart.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-charts.mjs +24 -18
- package/src/runtime/office/portable/portable-pptx-core.mjs +5 -5
- package/src/runtime/office/portable/portable-pptx-deck.mjs +8 -4
- package/src/runtime/office/portable/portable-pptx-package.mjs +7 -4
- package/src/runtime/office/portable/portable-pptx-shapes.mjs +18 -9
- package/src/runtime/office/portable/portable-sheet-parts.mjs +9 -3
- package/src/runtime/office/portable/portable-sheet-xml.mjs +5 -5
- package/src/runtime/office/portable/portable-xlsx-charts.mjs +4 -1
- package/src/runtime/office/portable/portable-xlsx-drawings.mjs +10 -6
- package/src/runtime/office/portable/portable-xlsx-operations.mjs +8 -5
- package/src/runtime/office/portable/portable-xlsx-pivot-ops.mjs +1 -1
- package/src/runtime/office/portable/portable-xlsx-reference-shift.mjs +11 -7
- package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +6 -3
- package/src/runtime/office/portable/portable-xml.mjs +1 -1
- package/src/runtime/shared/agent-avatar-sprites.mjs +445 -0
- package/src/runtime/shared/agent-avatar.d.mts +64 -0
- package/src/runtime/shared/agent-avatar.mjs +320 -0
- package/src/runtime/shared/agent-route-config.d.mts +3 -0
- package/src/runtime/shared/agent-route-config.mjs +16 -0
- package/src/runtime/shared/atomic-file.mjs +36 -14
- package/src/runtime/shared/background-tasks.mjs +60 -20
- package/src/runtime/shared/child-spawn-gate.mjs +26 -16
- package/src/runtime/shared/config.mjs +8 -11
- package/src/runtime/shared/connector-accounts.mjs +15 -0
- package/src/runtime/shared/connector-catalog.d.mts +52 -0
- package/src/runtime/shared/connector-catalog.mjs +230 -0
- package/src/runtime/shared/connector-triggers.d.mts +3 -0
- package/src/runtime/shared/connector-triggers.mjs +43 -0
- package/src/runtime/shared/file-lock.mjs +7 -1
- package/src/runtime/shared/file-permissions-worker.mjs +38 -0
- package/src/runtime/shared/file-permissions.d.mts +19 -4
- package/src/runtime/shared/file-permissions.mjs +310 -4
- package/src/runtime/shared/git-runner-worker.mjs +6 -78
- package/src/runtime/shared/google-oauth-client.mjs +24 -0
- package/src/runtime/shared/held-request-host.d.mts +12 -0
- package/src/runtime/shared/held-request-host.mjs +71 -0
- package/src/runtime/shared/llm/http-agent.mjs +7 -3
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +10 -0
- package/src/runtime/shared/llm/usage-accounting.mjs +2 -0
- package/src/runtime/shared/llm/usage-ledger-import.mjs +32 -3
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +12 -5
- package/src/runtime/shared/llm/usage-ledger-worker.mjs +1 -1
- package/src/runtime/shared/llm/usage-ledger.mjs +20 -5
- package/src/runtime/shared/memory-snapshot.mjs +5 -1
- package/src/runtime/shared/notify-trace.mjs +8 -1
- package/src/runtime/shared/plain-preview.d.mts +1 -0
- package/src/runtime/shared/plain-preview.mjs +28 -0
- package/src/runtime/shared/pristine-execution-contract.json +5 -1
- package/src/runtime/shared/process-runner-worker.mjs +7 -0
- package/src/runtime/shared/process-runner.mjs +38 -0
- package/src/runtime/shared/provider-accounts.mjs +2 -1
- package/src/runtime/shared/provider-api-key.mjs +0 -1
- package/src/runtime/shared/read-row-numbers.mjs +1 -1
- package/src/runtime/shared/resource-admission.mjs +60 -18
- package/src/runtime/shared/routine-limits.d.mts +11 -0
- package/src/runtime/shared/routine-limits.mjs +21 -0
- package/src/runtime/shared/routine-trigger.d.mts +10 -0
- package/src/runtime/shared/routine-trigger.mjs +44 -0
- package/src/runtime/shared/run-child.mjs +84 -0
- package/src/runtime/shared/schedule-model-ref.mjs +9 -10
- package/src/runtime/shared/session-activity-signal.mjs +23 -0
- package/src/runtime/shared/shell-output-summary.mjs +23 -0
- package/src/runtime/shared/singleton-owner.mjs +126 -42
- package/src/runtime/shared/slow-span.mjs +4 -12
- package/src/runtime/shared/statusline/statusline-segments.mjs +13 -1
- package/src/runtime/shared/tool-output-limit.mjs +4 -2
- package/src/runtime/shared/tool-output-marker.mjs +58 -0
- package/src/runtime/shared/transcript-metadata.mjs +10 -0
- package/src/runtime/shared/turn-changes.mjs +0 -8
- package/src/runtime/shared/usage-readout-totals.mjs +56 -0
- package/src/runtime/shared/user-data-guard.mjs +131 -34
- package/src/runtime/shared/worktrees/activity-gate.mjs +33 -8
- package/src/runtime/shared/worktrees/git-head.mjs +20 -2
- package/src/runtime/shared/worktrees/lock.mjs +3 -2
- package/src/runtime/terminal-bridge/tool-defs.mjs +1 -1
- package/src/runtime/tidy/runners/biome.mjs +3 -1
- package/src/runtime/tidy/shadow.mjs +2 -1
- package/src/runtime/web-search/index.mjs +5 -7
- package/src/runtime/web-search/lib/formatter.mjs +42 -6
- package/src/runtime/web-search/tool-defs.mjs +6 -1
- package/src/session-runtime/agent-home-delivery.mjs +459 -0
- package/src/session-runtime/agent-profile-changes.mjs +21 -0
- package/src/session-runtime/agent-room-delivery.mjs +92 -0
- package/src/session-runtime/agent-task-sessions.mjs +200 -0
- package/src/session-runtime/boot/apis.mjs +50 -18
- package/src/session-runtime/boot/facade.mjs +5 -8
- package/src/session-runtime/boot/infrastructure.mjs +28 -17
- package/src/session-runtime/boot/tools.mjs +3 -0
- package/src/session-runtime/channel-config-api.mjs +53 -5
- package/src/session-runtime/cwd-plugins/core-memory-context.mjs +36 -20
- package/src/session-runtime/cwd-plugins/plugin-status.mjs +6 -1
- package/src/session-runtime/held-requests.mjs +228 -0
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +121 -0
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +5 -1
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +31 -2
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +31 -2
- package/src/session-runtime/internal-tool-executor.mjs +2 -0
- package/src/session-runtime/lifecycle/session-catalog.mjs +9 -0
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +4 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +11 -4
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +3 -3
- package/src/session-runtime/lifecycle/shared.mjs +25 -2
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +5 -2
- package/src/session-runtime/lifecycle-api.mjs +3 -1
- package/src/session-runtime/mcp-glue/server-catalog.mjs +8 -0
- package/src/session-runtime/mcp-glue/server-input.mjs +3 -0
- package/src/session-runtime/mcp-oauth-login.mjs +112 -15
- package/src/session-runtime/model-route/set-route.mjs +14 -3
- package/src/session-runtime/owned-automation-run.mjs +229 -0
- package/src/session-runtime/provider-auth/login.mjs +10 -6
- package/src/session-runtime/provider-auth/setup.mjs +19 -2
- package/src/session-runtime/provider-catalog-cache.mjs +101 -25
- package/src/session-runtime/provider-models/catalog-load.mjs +14 -3
- package/src/session-runtime/provider-models/row-hydration.mjs +4 -0
- package/src/session-runtime/provider-models.mjs +76 -10
- package/src/session-runtime/provider-readiness.mjs +4 -0
- package/src/session-runtime/resource-api.mjs +5 -0
- package/src/session-runtime/resource-mcp-api.mjs +107 -13
- package/src/session-runtime/resource-skills-api.mjs +12 -0
- package/src/session-runtime/room-member-gate.mjs +48 -0
- package/src/session-runtime/routine-home-turn.mjs +156 -0
- package/src/session-runtime/routine-owner.mjs +48 -0
- package/src/session-runtime/schedule-session-run.mjs +30 -64
- package/src/session-runtime/services/agent-tool/close-flow.mjs +2 -1
- package/src/session-runtime/services/agent-tool/helpers.mjs +10 -0
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +10 -2
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +13 -4
- package/src/session-runtime/services/agent-tool/notify.mjs +15 -4
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +134 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/deferred-spawn.mjs +2 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +19 -4
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +2 -0
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -1
- package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +8 -3
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +4 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +44 -10
- package/src/session-runtime/services/agent-tool.mjs +20 -0
- package/src/session-runtime/services/channel-admin.mjs +93 -24
- package/src/session-runtime/services/memory-access.mjs +37 -0
- package/src/session-runtime/services/provider-admin.mjs +166 -59
- package/src/session-runtime/services/schedule-access.mjs +91 -0
- package/src/session-runtime/services/usage-dashboard-model.mjs +2 -2
- package/src/session-runtime/services/usage-dashboard.mjs +27 -69
- package/src/session-runtime/session-create/session-options.mjs +34 -7
- package/src/session-runtime/session-hooks.mjs +16 -8
- package/src/session-runtime/setup-tool/executor.mjs +68 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +72 -14
- package/src/session-runtime/setup-tool/settings-contract.mjs +8 -6
- package/src/session-runtime/setup-tool/tool-defs.mjs +8 -0
- package/src/session-runtime/skills-api.mjs +16 -1
- package/src/session-runtime/tool-policy-refresh.mjs +238 -29
- package/src/session-runtime/turn/session-ops.mjs +10 -3
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +11 -2
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +3 -0
- package/src/session-runtime/usage-stats-api.mjs +6 -1
- package/src/session-runtime/webhook-session-run.mjs +49 -67
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +239 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +556 -22
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +11 -1
- package/src/session-runtime/workflow-agents-api.mjs +4 -1
- package/src/standalone/channel-transport/http-routes.mjs +10 -9
- package/src/standalone/daemon-agent-control.mjs +1 -8
- package/src/standalone/daemon-desktop-runtime.mjs +20 -7
- package/src/standalone/daemon-owner.mjs +117 -25
- package/src/standalone/daemon-session-control.mjs +11 -2
- package/src/standalone/daemon.mjs +61 -17
- package/src/standalone/session-call-cache.mjs +6 -0
- package/src/standalone/session-protocol.mjs +28 -1
- package/src/standalone/session-service/retention/busy.mjs +7 -2
- package/src/standalone/session-service/session-calls/session-turns.mjs +9 -0
- package/src/standalone/session-service.mjs +19 -0
- package/src/standalone/session-transport/routes.mjs +7 -6
- package/src/tui/app/model-options.mjs +39 -2
- package/src/tui/app/model-picker.mjs +16 -2
- package/src/tui/app/provider-setup-picker.mjs +1 -2
- package/src/tui/app/slash-commands.mjs +20 -0
- package/src/tui/dist/index.mjs +487 -128
- package/src/tui/session/context-state.mjs +6 -1
- package/src/tui/session/notice-surface.mjs +35 -4
- package/src/tui/session/notice-text.mjs +0 -1
- package/src/tui/session/queue-helpers.mjs +2 -1
- package/src/tui/session/session-api/extensions.mjs +4 -0
- package/src/tui/session/session-api/intake/submission.mjs +12 -13
- package/src/tui/session/session-api/integrations.mjs +9 -5
- package/src/tui/session/session-api/lifecycle/session-reset.mjs +13 -3
- package/src/tui/session/session-api/lifecycle.mjs +17 -1
- package/src/tui/session/session-api/routes.mjs +48 -3
- package/src/tui/session/session-flow/drain.mjs +20 -3
- package/src/tui/session/session-flow/queue/entry-shape.mjs +2 -1
- package/src/tui/session/session-flow/queue/take-entries.mjs +3 -2
- package/src/tui/session/session-flow/steering.mjs +104 -24
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/tool-approval.mjs +26 -5
- package/src/tui/session/transcript-intake.mjs +6 -2
- package/src/tui/session/transcript-spill.mjs +5 -1
- package/src/tui/session/tui-steering-persist.mjs +65 -42
- package/src/tui/session/turn-live-call.mjs +56 -0
- package/src/tui/session/turn-stream.mjs +33 -0
- package/src/tui/session/turn.mjs +50 -7
- package/src/ui/statusline.mjs +1 -6
- package/src/ui/streaming-markdown-heal.mjs +24 -7
- package/src/vendor/statusline/bin/statusline-route.mjs +0 -1
- package/src/vendor/statusline/src/gateway/route-meta.mjs +0 -1
- package/src/workflows/default/WORKFLOW.md +9 -13
- package/src/session-runtime/automation-agents.mjs +0 -94
- package/src/session-runtime/automation-workflow.mjs +0 -59
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
// `powershell -Command "<inline>"` / `pwsh -Command "<inline>"` to
|
|
9
9
|
// `-EncodedCommand <utf16le-base64>` so the payload stays opaque to the
|
|
10
10
|
// outer shell. Other shells / non-Windows are no-op pass-through.
|
|
11
|
+
import { codeMask } from './builtin/bash-tool/bashism-rewrite.mjs';
|
|
12
|
+
|
|
11
13
|
// Match -Command "<body>" where the body may contain escaped quotes
|
|
12
14
|
// (`\"` or `""`). Stops at the first unescaped closing quote so nested
|
|
13
15
|
// patterns like `"... \"inner\" ..."` survive intact. Common PowerShell
|
|
@@ -16,49 +18,63 @@
|
|
|
16
18
|
// Single-quoted -Command '<body>' is also covered.
|
|
17
19
|
const _POWERSHELL_FLAGS_RE =
|
|
18
20
|
/\s+-(?:NoProfile|NonInteractive|WindowStyle\s+\S+|ExecutionPolicy\s+\S+|Sta|Mta|NoLogo|NoExit)/.source;
|
|
21
|
+
// What may follow the closing quote: the end of the command or a shell
|
|
22
|
+
// operator. Anything else (`pwsh -Command "a" "b"`) is more arguments, which
|
|
23
|
+
// PowerShell appends to the command text and an -EncodedCommand would drop.
|
|
24
|
+
const _POWERSHELL_TRAILING = '(?=[ \\t]*(?:$|[\\r\\n;|&<>]|\\d+>))';
|
|
19
25
|
const _POWERSHELL_DOUBLE_RE = new RegExp(
|
|
20
26
|
'\\b(powershell(?:\\.exe)?|pwsh(?:\\.exe)?)((?:' +
|
|
21
27
|
_POWERSHELL_FLAGS_RE +
|
|
22
|
-
')*)\\s+(?:-Command|-c)\\s+"((?:[^"\\\\]|\\\\.|"")+?)"
|
|
28
|
+
')*)\\s+(?:-Command|-c)\\s+"((?:[^"\\\\]|\\\\.|"")+?)"' +
|
|
29
|
+
_POWERSHELL_TRAILING,
|
|
23
30
|
'gi'
|
|
24
31
|
);
|
|
25
32
|
const _POWERSHELL_SINGLE_RE = new RegExp(
|
|
26
33
|
'\\b(powershell(?:\\.exe)?|pwsh(?:\\.exe)?)((?:' +
|
|
27
34
|
_POWERSHELL_FLAGS_RE +
|
|
28
|
-
")*)\\s+(?:-Command|-c)\\s+'((?:[^'\\\\]|\\\\.|'')+?)'
|
|
35
|
+
")*)\\s+(?:-Command|-c)\\s+'((?:[^'\\\\]|\\\\.|'')+?)'" +
|
|
36
|
+
_POWERSHELL_TRAILING,
|
|
29
37
|
'gi'
|
|
30
38
|
);
|
|
31
39
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
// One pass of one quote style. Only an invocation the outer shell itself runs
|
|
41
|
+
// is rewritten: the same text inside a string, here-string or comment (a
|
|
42
|
+
// README being written, a commit message) is data, not a command.
|
|
43
|
+
function _encodePass(command, pattern, quote) {
|
|
44
|
+
const live = codeMask(command);
|
|
45
|
+
if (!live) return command;
|
|
46
|
+
return command.replace(pattern, (match, exe, flags, body, offset) => {
|
|
47
|
+
if (!live[offset]) return match;
|
|
36
48
|
try {
|
|
37
|
-
// Unescape
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
// backslash unescape, `pwsh -Command "Get-Process \"foo\""` would
|
|
44
|
-
// base64-encode the literal backslash, breaking inside PowerShell.
|
|
45
|
-
const unescaped = _unescapePowerShellCommandBody(body);
|
|
49
|
+
// Unescape the quote the caller used to embed the body: the PowerShell
|
|
50
|
+
// doubled form (`""` / `''`) AND the bash-style backslash form (`\"` /
|
|
51
|
+
// `\'`) POSIX outer-shell wrappers commonly use. Without the backslash
|
|
52
|
+
// unescape, `pwsh -Command "Get-Process \"foo\""` would base64-encode the
|
|
53
|
+
// literal backslash. The OTHER quote is the body's own syntax and stays.
|
|
54
|
+
const unescaped = _unescapePowerShellCommandBody(body, quote);
|
|
46
55
|
const encoded = Buffer.from(unescaped, 'utf16le').toString('base64');
|
|
47
56
|
const trimmedFlags = (flags || '').replace(/\s+/g, ' ').trim();
|
|
48
57
|
return `${exe}${trimmedFlags ? ` ${trimmedFlags}` : ''} -EncodedCommand ${encoded}`;
|
|
49
58
|
} catch {
|
|
50
59
|
return match;
|
|
51
60
|
}
|
|
52
|
-
};
|
|
53
|
-
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function _maybeEncodePowerShellCommand(command) {
|
|
65
|
+
if (process.platform !== 'win32') return command;
|
|
66
|
+
if (typeof command !== 'string' || command.length === 0) return command;
|
|
67
|
+
return _encodePass(_encodePass(command, _POWERSHELL_DOUBLE_RE, '"'), _POWERSHELL_SINGLE_RE, "'");
|
|
54
68
|
}
|
|
55
69
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
// `quote` names the delimiter that wrapped the body, so only its own escapes
|
|
71
|
+
// are removed. Without it (policy scanning, which wants every reading of the
|
|
72
|
+
// body) both styles are removed.
|
|
73
|
+
function _unescapePowerShellCommandBody(body, quote) {
|
|
74
|
+
let text = String(body || '');
|
|
75
|
+
if (quote !== "'") text = text.replace(/""/g, '"').replace(/\\"/g, '"');
|
|
76
|
+
if (quote !== '"') text = text.replace(/''/g, "'").replace(/\\'/g, "'");
|
|
77
|
+
return text;
|
|
62
78
|
}
|
|
63
79
|
|
|
64
80
|
// Extract inline `powershell -Command "…"` bodies for policy scan parity
|
|
@@ -126,11 +126,15 @@ function getSnapshotScript(shellPath, snapshotFilePath, configFileExists) {
|
|
|
126
126
|
declare -f "$func" >> "$SNAPSHOT_FILE" 2>/dev/null
|
|
127
127
|
done
|
|
128
128
|
`;
|
|
129
|
+
// Options are matched on their state column: a name containing "on"
|
|
130
|
+
// (monitor, onecmd) must not turn an OFF option on. Job control (monitor)
|
|
131
|
+
// is never restored: it gives every pipeline its own process group, which
|
|
132
|
+
// the runner's group kill then cannot reach.
|
|
129
133
|
const optDump = isZsh
|
|
130
|
-
? `setopt 2>/dev/null | sed 's/^/setopt /' | head -n 1000 >> "$SNAPSHOT_FILE"`
|
|
134
|
+
? `setopt 2>/dev/null | grep -vxE '(no)?monitor' | sed 's/^/setopt /' | head -n 1000 >> "$SNAPSHOT_FILE"`
|
|
131
135
|
: `
|
|
132
136
|
shopt -p 2>/dev/null | head -n 1000 >> "$SNAPSHOT_FILE"
|
|
133
|
-
set -o 2>/dev/null |
|
|
137
|
+
set -o 2>/dev/null | awk '$2 == "on" && $1 != "monitor" {print "set -o " $1}' | head -n 1000 >> "$SNAPSHOT_FILE"
|
|
134
138
|
echo "shopt -s expand_aliases" >> "$SNAPSHOT_FILE"
|
|
135
139
|
`;
|
|
136
140
|
const aliasDump = `
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
2
|
+
"version": "0.1.11",
|
|
3
3
|
"_comment": "Synced from immutable spawn-v release assets.",
|
|
4
4
|
"assets": {
|
|
5
5
|
"darwin-arm64": {
|
|
6
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.
|
|
7
|
-
"sha256": "
|
|
6
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.11/mixdog-spawn-darwin-arm64",
|
|
7
|
+
"sha256": "6f1a7e6597dcc8785d12c5a13c42388110d9f4a2e5378ca2773172adbf50de60"
|
|
8
8
|
},
|
|
9
9
|
"darwin-x64": {
|
|
10
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.
|
|
11
|
-
"sha256": "
|
|
10
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.11/mixdog-spawn-darwin-x64",
|
|
11
|
+
"sha256": "ff755eb9848cb3ce90f3df24136bb84a52f9ff6c67002c4d764beb6d7906e6b2"
|
|
12
12
|
},
|
|
13
13
|
"linux-arm64": {
|
|
14
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.
|
|
15
|
-
"sha256": "
|
|
14
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.11/mixdog-spawn-linux-arm64",
|
|
15
|
+
"sha256": "3bc0fccde46537046d498a2b953aa92ef4afacc95c96c563ce1d6fb92d74e593"
|
|
16
16
|
},
|
|
17
17
|
"linux-x64": {
|
|
18
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.
|
|
19
|
-
"sha256": "
|
|
18
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.11/mixdog-spawn-linux-x64",
|
|
19
|
+
"sha256": "16dc4e3bf6636335c1325c88bbb5245529731525953466e761d363897b59aac7"
|
|
20
20
|
},
|
|
21
21
|
"win32-arm64": {
|
|
22
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.
|
|
23
|
-
"sha256": "
|
|
22
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.11/mixdog-spawn-win32-arm64.exe",
|
|
23
|
+
"sha256": "c2fb5499d3d44405e27c79f8db65694299d61ddf029f466df68549fc2f2c5f5c"
|
|
24
24
|
},
|
|
25
25
|
"win32-x64": {
|
|
26
|
-
"url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.
|
|
27
|
-
"sha256": "
|
|
26
|
+
"url": "https://github.com/tribgames/mixdog/releases/download/spawn-v0.1.11/mixdog-spawn-win32-x64.exe",
|
|
27
|
+
"sha256": "50531a9f033dc22eff3ec5b2a9d10441ffdfac0e50d9acf9047e4f302e5d70d9"
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -13,7 +13,10 @@ const ATTR_BOUND = 4096;
|
|
|
13
13
|
const ATTRS = `[^<>]{0,${ATTR_BOUND}}`;
|
|
14
14
|
const A = ATTRS;
|
|
15
15
|
// A regex built from a raw template; the interpolations are pattern text.
|
|
16
|
-
const re =
|
|
16
|
+
const re =
|
|
17
|
+
(flags = '') =>
|
|
18
|
+
(strings, ...values) =>
|
|
19
|
+
new RegExp(String.raw(strings, ...values), flags);
|
|
17
20
|
// The patterns the per-cell / per-run loops use are built once.
|
|
18
21
|
const V_RE = re()`<v(?:\s${A})?>([^<]*)</v>`;
|
|
19
22
|
const T_RUN_RE = re('g')`<t(?:\s${A})?>([^<]*)</t>`;
|
|
@@ -384,16 +387,12 @@ function relationshipList(xml) {
|
|
|
384
387
|
|
|
385
388
|
function sharedStringTable(xml) {
|
|
386
389
|
if (!xml) return [];
|
|
387
|
-
return [...scanElements(xml, 'si')]
|
|
388
|
-
.filter((item) => item.inner !== null)
|
|
389
|
-
.map((item) => textRuns(item.inner));
|
|
390
|
+
return [...scanElements(xml, 'si')].filter((item) => item.inner !== null).map((item) => textRuns(item.inner));
|
|
390
391
|
}
|
|
391
392
|
|
|
392
393
|
// Concatenated <t> character data of one fragment.
|
|
393
394
|
function textRuns(fragment) {
|
|
394
|
-
return [...fragment.matchAll(T_RUN_RE)]
|
|
395
|
-
.map(([, text]) => decodeXmlEntities(text))
|
|
396
|
-
.join('');
|
|
395
|
+
return [...fragment.matchAll(T_RUN_RE)].map(([, text]) => decodeXmlEntities(text)).join('');
|
|
397
396
|
}
|
|
398
397
|
|
|
399
398
|
// Excel stores a date as a day count and a percentage as a fraction, so a
|
|
@@ -421,7 +420,10 @@ function cellNumberFormats(xml) {
|
|
|
421
420
|
if (!xml) return [];
|
|
422
421
|
const custom = new Map(
|
|
423
422
|
[...xml.matchAll(re('g')`<numFmt\b(${A}?)/?>`)]
|
|
424
|
-
.map(([, attributes]) => [
|
|
423
|
+
.map(([, attributes]) => [
|
|
424
|
+
/\bnumFmtId="(\d+)"/.exec(attributes)?.[1],
|
|
425
|
+
/\bformatCode="([^"<>]*)"/.exec(attributes)?.[1],
|
|
426
|
+
])
|
|
425
427
|
.filter(([id, code]) => id !== undefined && code !== undefined)
|
|
426
428
|
.map(([id, code]) => [Number(id), decodeXmlEntities(code)])
|
|
427
429
|
);
|
|
@@ -629,7 +631,7 @@ function relatedPart(target, ownerPart) {
|
|
|
629
631
|
const base = String(ownerPart).replace(/\/[^/]+$/, '');
|
|
630
632
|
const value = String(target).replace(/^\//, '');
|
|
631
633
|
if (!value.startsWith('..')) return value.startsWith('xl/') ? value : `${base}/${value}`;
|
|
632
|
-
return value.replace(/^\.\.\//, `${base.replace(/\/[^/]+$/, '')}/`);
|
|
634
|
+
return value.replace(/^\.\.\//, () => `${base.replace(/\/[^/]+$/, '')}/`);
|
|
633
635
|
}
|
|
634
636
|
|
|
635
637
|
// A sheet's chart is its message, and it lives outside the cell grid: read as
|
|
@@ -53,6 +53,30 @@ export async function finishBrowserTurn(sessionId, turnId, { aborted = false } =
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/** Runtime-only: fill the secret the user handed the desktop for `requestId`
|
|
57
|
+
* into the page's focused password field through the host's isolated-world
|
|
58
|
+
* fill. The value never passes through here; the host answers only
|
|
59
|
+
* 'provided' or 'skipped'. */
|
|
60
|
+
export async function browserSecretInput(sessionId, requestId, { signal } = {}) {
|
|
61
|
+
const discovery = readBridgeDiscovery(DISCOVERY_FILE);
|
|
62
|
+
if (!discovery || !sessionId || !requestId) return 'skipped';
|
|
63
|
+
try {
|
|
64
|
+
const result = await requestBridge(
|
|
65
|
+
discovery,
|
|
66
|
+
JSON.stringify({ action: 'secret_input', session_id: String(sessionId), request_id: String(requestId) }),
|
|
67
|
+
signal
|
|
68
|
+
? AbortSignal.any([AbortSignal.timeout(REQUEST_TIMEOUT_MS), signal])
|
|
69
|
+
: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
70
|
+
{ sessionId, action: 'secret_input' }
|
|
71
|
+
);
|
|
72
|
+
return result.status === 200 && result.body?.ok !== false && result.body?.value?.text === 'provided'
|
|
73
|
+
? 'provided'
|
|
74
|
+
: 'skipped';
|
|
75
|
+
} catch {
|
|
76
|
+
return 'skipped';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
56
80
|
const BRIDGE_UNAVAILABLE_MESSAGE = 'browser use is unavailable; open the Mixdog desktop app and enable Browser Use';
|
|
57
81
|
|
|
58
82
|
/** Sync gate for the session tool surface (featureDisallowedTools). */
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
markFired,
|
|
13
13
|
markDone,
|
|
14
14
|
markScheduleFailure,
|
|
15
|
+
markScheduleSkipped,
|
|
15
16
|
markScheduleSuccess,
|
|
16
17
|
setDeferred,
|
|
17
18
|
setNextFire,
|
|
@@ -61,6 +62,11 @@ function isCronExpression(time) {
|
|
|
61
62
|
return false;
|
|
62
63
|
}
|
|
63
64
|
}
|
|
65
|
+
// True when this fire (started at `since`) ended in an overlap skip.
|
|
66
|
+
function skippedSince(schedule, since) {
|
|
67
|
+
const at = schedule.lastSkippedAt ? new Date(schedule.lastSkippedAt).getTime() : 0;
|
|
68
|
+
return at >= since.getTime();
|
|
69
|
+
}
|
|
64
70
|
// Records a one-shot fire that did not complete; the entry stays pending.
|
|
65
71
|
async function markOneShotFailed(schedule) {
|
|
66
72
|
schedule.lastFailedAt = new Date().toISOString();
|
|
@@ -407,6 +413,8 @@ ${prompt}`;
|
|
|
407
413
|
schedule.lastFiredAt = startedAt.toISOString();
|
|
408
414
|
this.lastFired.set(schedule.name, startedAt.toISOString());
|
|
409
415
|
const fired = await this.fireTimed(schedule, type, { awaitDispatch: true });
|
|
416
|
+
// An overlap skip is recorded as a skip, never as a failed run.
|
|
417
|
+
if (!fired && skippedSince(schedule, startedAt)) return;
|
|
410
418
|
if (!fired) {
|
|
411
419
|
schedule.lastFailedAt = new Date().toISOString();
|
|
412
420
|
await markScheduleFailure(schedule.name, new Date());
|
|
@@ -498,7 +506,7 @@ ${prompt}`;
|
|
|
498
506
|
return;
|
|
499
507
|
}
|
|
500
508
|
// Mark done ONLY after a successful fire. A false/throwing fireTimed
|
|
501
|
-
// (missing prompt
|
|
509
|
+
// (missing prompt, running guard, paused owner, dispatch error) must leave the
|
|
502
510
|
// one-shot pending so a reload/restart can retry it — never retire it.
|
|
503
511
|
try {
|
|
504
512
|
// awaitDispatch: for a one-shot we must wait for the actual LLM/relay
|
|
@@ -506,6 +514,10 @@ ${prompt}`;
|
|
|
506
514
|
// contract) would retire the entry even when schedulerLlm() later
|
|
507
515
|
// rejects. Only a resolved dispatch counts as a real fire here.
|
|
508
516
|
const fired = await this.fireTimed(schedule, type, { awaitDispatch: true });
|
|
517
|
+
if (!fired && skippedSince(schedule, now)) {
|
|
518
|
+
logSchedule(`one-shot "${schedule.name}" skipped (previous run in progress) — leaving pending for retry\n`);
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
509
521
|
if (!fired) {
|
|
510
522
|
await markOneShotFailed(schedule);
|
|
511
523
|
logSchedule(`one-shot "${schedule.name}" did not fire (skipped/guarded) — leaving pending for retry\n`);
|
|
@@ -625,20 +637,11 @@ ${prompt}`;
|
|
|
625
637
|
async fireTimedPrompt(schedule, type, prompt, { awaitDispatch = false } = {}) {
|
|
626
638
|
logSchedule(`firing ${schedule.name} (${type})\n`);
|
|
627
639
|
if (this.running.has(schedule.name)) {
|
|
628
|
-
|
|
629
|
-
// scheduler "ignoring" a fire.
|
|
630
|
-
logSchedule(`${schedule.name}: skipped — previous run still in progress\n`);
|
|
640
|
+
this.recordSkip(schedule);
|
|
631
641
|
return false;
|
|
632
642
|
}
|
|
633
643
|
if (type === 'interactive' && this.injectIntoLead(schedule, type, prompt)) return true;
|
|
634
644
|
this.running.add(schedule.name);
|
|
635
|
-
const presetId = schedule.model;
|
|
636
|
-
if (!presetId) {
|
|
637
|
-
this.running.delete(schedule.name);
|
|
638
|
-
logSchedule(`${schedule.name}: missing required "model" in schedule config — dispatch rejected\n`);
|
|
639
|
-
this.notifyFailure(schedule, 'missing "model" in schedule config — dispatch rejected');
|
|
640
|
-
return false;
|
|
641
|
-
}
|
|
642
645
|
// Cron (recurring) keeps the fire-and-forget contract: return truthy now
|
|
643
646
|
// and swallow async failures. A one-shot (awaitDispatch) instead awaits
|
|
644
647
|
// the dispatch so a rejected run propagates and the caller leaves the
|
|
@@ -676,8 +679,22 @@ ${prompt}`;
|
|
|
676
679
|
? this.scheduleRunner(schedule, { prompt })
|
|
677
680
|
: Promise.reject(new Error('schedule runner not configured'));
|
|
678
681
|
return run
|
|
679
|
-
.then((
|
|
682
|
+
.then((outcome) => {
|
|
680
683
|
this.running.delete(schedule.name);
|
|
684
|
+
// The run path found this schedule's previous run still going (a
|
|
685
|
+
// "run now" from the app) or backing off after failures in a row; it
|
|
686
|
+
// already persisted the skip.
|
|
687
|
+
if (outcome?.skipped) {
|
|
688
|
+
schedule.lastSkippedAt = new Date().toISOString();
|
|
689
|
+
const why =
|
|
690
|
+
outcome.reason === 'backoff'
|
|
691
|
+
? 'backing off after failures'
|
|
692
|
+
: outcome.reason === 'owner'
|
|
693
|
+
? `paused: ${outcome.message}`
|
|
694
|
+
: 'previous run still in progress';
|
|
695
|
+
logSchedule(`${schedule.name}: skipped — ${why}\n`);
|
|
696
|
+
return false;
|
|
697
|
+
}
|
|
681
698
|
logSchedule(`${schedule.name} done\n`);
|
|
682
699
|
return true;
|
|
683
700
|
})
|
|
@@ -693,6 +710,17 @@ ${prompt}`;
|
|
|
693
710
|
});
|
|
694
711
|
}
|
|
695
712
|
// ── Helpers ─────────────────────────────────────────────────────────
|
|
713
|
+
/** Overlap skip: the previous run of this schedule is still in progress.
|
|
714
|
+
* Logged and persisted (last_skipped_at) so a skipped fire is never
|
|
715
|
+
* invisible; `persistSkip` is injectable for tests. */
|
|
716
|
+
recordSkip(schedule) {
|
|
717
|
+
const at = new Date();
|
|
718
|
+
schedule.lastSkippedAt = at.toISOString();
|
|
719
|
+
logSchedule(`${schedule.name}: skipped — previous run still in progress\n`);
|
|
720
|
+
void Promise.resolve()
|
|
721
|
+
.then(() => (this.persistSkip ?? markScheduleSkipped)(schedule.name, at))
|
|
722
|
+
.catch((err) => process.stderr.write(`mixdog scheduler: ${schedule.name} skip record failed: ${err}\n`));
|
|
723
|
+
}
|
|
696
724
|
/** Failure notice: logged so scheduled fires never fail silently. */
|
|
697
725
|
notifyFailure(schedule, reason) {
|
|
698
726
|
logSchedule(`schedule "${schedule?.name}": ${reason}\n`);
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import { ensurePgInstance, withSchemaBootstrapLock } from '../../memory/lib/pg/adapter.mjs';
|
|
15
15
|
import { createPgSchemaDb } from '../../shared/pg-schema-db.mjs';
|
|
16
16
|
import { resolvePluginData } from '../../shared/plugin-paths.mjs';
|
|
17
|
+
import { ROUTINE_LIMITS } from '../../shared/routine-limits.mjs';
|
|
17
18
|
|
|
18
19
|
const SCHEMA = 'scheduler';
|
|
19
20
|
|
|
@@ -54,6 +55,18 @@ ALTER TABLE scheduler.schedules ADD COLUMN IF NOT EXISTS last_scheduled_at times
|
|
|
54
55
|
ALTER TABLE scheduler.schedules ADD COLUMN IF NOT EXISTS last_started_at timestamptz;
|
|
55
56
|
ALTER TABLE scheduler.schedules ADD COLUMN IF NOT EXISTS last_success_at timestamptz;
|
|
56
57
|
ALTER TABLE scheduler.schedules ADD COLUMN IF NOT EXISTS last_failed_at timestamptz;
|
|
58
|
+
ALTER TABLE scheduler.schedules ADD COLUMN IF NOT EXISTS last_skipped_at timestamptz;
|
|
59
|
+
-- The agent a schedule belongs to (its results land in that agent's home
|
|
60
|
+
-- thread). Rows from before ownership existed fill with Mixy ('lead').
|
|
61
|
+
ALTER TABLE scheduler.schedules ADD COLUMN IF NOT EXISTS owner_agent_id text NOT NULL DEFAULT 'lead';
|
|
62
|
+
-- Legacy columns model, workflow and run_as_agent are no longer read or written (kept, not dropped, to avoid a risky migration).
|
|
63
|
+
ALTER TABLE scheduler.schedules ADD COLUMN IF NOT EXISTS run_as_agent boolean NOT NULL DEFAULT false;
|
|
64
|
+
-- Failed runs in a row: a success or switching it back on resets it; at
|
|
65
|
+
-- ROUTINE_LIMITS.pauseAfterFailures the schedule switches itself off.
|
|
66
|
+
ALTER TABLE scheduler.schedules ADD COLUMN IF NOT EXISTS consecutive_failures integer NOT NULL DEFAULT 0;
|
|
67
|
+
-- Results of finished runs not yet queued for the owner's home thread, by run
|
|
68
|
+
-- id ({ state: 'pending' | 'failed', error?, at, result }).
|
|
69
|
+
ALTER TABLE scheduler.schedules ADD COLUMN IF NOT EXISTS result_delivery jsonb;
|
|
57
70
|
`;
|
|
58
71
|
|
|
59
72
|
const getDb = createPgSchemaDb({
|
|
@@ -78,9 +91,7 @@ function rowToDef(row) {
|
|
|
78
91
|
timezone: row.timezone,
|
|
79
92
|
target: row.target,
|
|
80
93
|
channelId: row.channel_id,
|
|
81
|
-
model: row.model,
|
|
82
94
|
cwd: row.cwd,
|
|
83
|
-
workflow: row.workflow,
|
|
84
95
|
attachments: row.attachments || null,
|
|
85
96
|
delivery: row.delivery || null,
|
|
86
97
|
prompt: row.prompt,
|
|
@@ -91,6 +102,10 @@ function rowToDef(row) {
|
|
|
91
102
|
lastStartedAt: row.last_started_at,
|
|
92
103
|
lastSuccessAt: row.last_success_at,
|
|
93
104
|
lastFailedAt: row.last_failed_at,
|
|
105
|
+
lastSkippedAt: row.last_skipped_at,
|
|
106
|
+
ownerAgentId: row.owner_agent_id || 'lead',
|
|
107
|
+
consecutiveFailures: Number(row.consecutive_failures) || 0,
|
|
108
|
+
resultDelivery: row.result_delivery || null,
|
|
94
109
|
nextFireAt: row.next_fire_at,
|
|
95
110
|
deferredUntil: row.deferred_until,
|
|
96
111
|
skippedUntil: row.skipped_until,
|
|
@@ -100,7 +115,7 @@ function rowToDef(row) {
|
|
|
100
115
|
}
|
|
101
116
|
|
|
102
117
|
const COLS =
|
|
103
|
-
'name, description, when_at, when_cron, timezone, target, channel_id,
|
|
118
|
+
'name, description, when_at, when_cron, timezone, target, channel_id, cwd, attachments, delivery, prompt, enabled, status, last_fired_at, last_scheduled_at, last_started_at, last_success_at, last_failed_at, last_skipped_at, owner_agent_id, consecutive_failures, result_delivery, next_fire_at, deferred_until, skipped_until, created_at, updated_at';
|
|
104
119
|
|
|
105
120
|
// ---------------------------------------------------------------------------
|
|
106
121
|
// Public API
|
|
@@ -134,30 +149,28 @@ export async function upsertSchedule(def, { dataDir } = {}) {
|
|
|
134
149
|
def.timezone ?? null,
|
|
135
150
|
def.target,
|
|
136
151
|
def.channelId ?? null,
|
|
137
|
-
def.model ?? null,
|
|
138
152
|
def.cwd ?? null,
|
|
139
|
-
def.workflow ?? null,
|
|
140
153
|
def.attachments ? JSON.stringify(def.attachments) : null,
|
|
141
154
|
def.delivery ?? null,
|
|
142
155
|
def.prompt,
|
|
143
156
|
def.enabled ?? true,
|
|
144
157
|
def.status ?? 'active',
|
|
145
158
|
def.nextFireAt ?? null,
|
|
159
|
+
def.ownerAgentId || 'lead',
|
|
146
160
|
];
|
|
147
161
|
const { rows } = await db.query(
|
|
148
162
|
`INSERT INTO scheduler.schedules
|
|
149
|
-
(name, description, when_at, when_cron, timezone, target, channel_id,
|
|
150
|
-
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15
|
|
163
|
+
(name, description, when_at, when_cron, timezone, target, channel_id, cwd, attachments, delivery, prompt, enabled, status, next_fire_at, owner_agent_id)
|
|
164
|
+
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15)
|
|
151
165
|
ON CONFLICT (name) DO UPDATE SET
|
|
166
|
+
owner_agent_id = EXCLUDED.owner_agent_id,
|
|
152
167
|
description = EXCLUDED.description,
|
|
153
168
|
when_at = EXCLUDED.when_at,
|
|
154
169
|
when_cron = EXCLUDED.when_cron,
|
|
155
170
|
timezone = EXCLUDED.timezone,
|
|
156
171
|
target = EXCLUDED.target,
|
|
157
172
|
channel_id = EXCLUDED.channel_id,
|
|
158
|
-
model = EXCLUDED.model,
|
|
159
173
|
cwd = EXCLUDED.cwd,
|
|
160
|
-
workflow = EXCLUDED.workflow,
|
|
161
174
|
attachments = EXCLUDED.attachments,
|
|
162
175
|
delivery = EXCLUDED.delivery,
|
|
163
176
|
prompt = EXCLUDED.prompt,
|
|
@@ -173,6 +186,8 @@ export async function upsertSchedule(def, { dataDir } = {}) {
|
|
|
173
186
|
last_started_at = NULL,
|
|
174
187
|
last_success_at = NULL,
|
|
175
188
|
last_failed_at = NULL,
|
|
189
|
+
last_skipped_at = NULL,
|
|
190
|
+
consecutive_failures = 0,
|
|
176
191
|
updated_at = now()
|
|
177
192
|
RETURNING ${COLS}`,
|
|
178
193
|
params
|
|
@@ -198,8 +213,16 @@ async function updateScheduleColumn(name, column, value, dataDir) {
|
|
|
198
213
|
return rowToDef(rows[0]);
|
|
199
214
|
}
|
|
200
215
|
|
|
216
|
+
/** Switching a schedule back on clears its failure streak. */
|
|
201
217
|
export async function setEnabled(name, enabled, { dataDir } = {}) {
|
|
202
|
-
|
|
218
|
+
const db = await getDb(dataDir);
|
|
219
|
+
const { rows } = await db.query(
|
|
220
|
+
`UPDATE scheduler.schedules
|
|
221
|
+
SET enabled = $2, consecutive_failures = CASE WHEN $2 THEN 0 ELSE consecutive_failures END, updated_at = now()
|
|
222
|
+
WHERE name = $1 RETURNING ${COLS}`,
|
|
223
|
+
[name, !!enabled]
|
|
224
|
+
);
|
|
225
|
+
return rowToDef(rows[0]);
|
|
203
226
|
}
|
|
204
227
|
|
|
205
228
|
export async function markFired(name, ts = new Date(), { dataDir } = {}) {
|
|
@@ -240,11 +263,47 @@ export async function claimScheduleRun(name, scheduledAt, startedAt, nextFireAt,
|
|
|
240
263
|
}
|
|
241
264
|
|
|
242
265
|
export async function markScheduleSuccess(name, ts = new Date(), { dataDir } = {}) {
|
|
243
|
-
|
|
266
|
+
const db = await getDb(dataDir);
|
|
267
|
+
const { rows } = await db.query(
|
|
268
|
+
`UPDATE scheduler.schedules SET last_success_at = $2, consecutive_failures = 0, updated_at = now()
|
|
269
|
+
WHERE name = $1 RETURNING ${COLS}`,
|
|
270
|
+
[name, ts]
|
|
271
|
+
);
|
|
272
|
+
return rowToDef(rows[0]);
|
|
244
273
|
}
|
|
245
274
|
|
|
275
|
+
/** One more failure in a row; the one reaching the pause limit switches the
|
|
276
|
+
* schedule off (claimScheduleRun admits only enabled rows). */
|
|
246
277
|
export async function markScheduleFailure(name, ts = new Date(), { dataDir } = {}) {
|
|
247
|
-
|
|
278
|
+
const db = await getDb(dataDir);
|
|
279
|
+
const { rows } = await db.query(
|
|
280
|
+
`UPDATE scheduler.schedules
|
|
281
|
+
SET last_failed_at = $2, consecutive_failures = consecutive_failures + 1,
|
|
282
|
+
enabled = enabled AND consecutive_failures + 1 < $3, updated_at = now()
|
|
283
|
+
WHERE name = $1 RETURNING ${COLS}`,
|
|
284
|
+
[name, ts, ROUTINE_LIMITS.pauseAfterFailures]
|
|
285
|
+
);
|
|
286
|
+
return rowToDef(rows[0]);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** Set (`entry`) or clear (null) the undelivered result of run `runId`. */
|
|
290
|
+
export async function recordScheduleDelivery(name, runId, entry, { dataDir } = {}) {
|
|
291
|
+
const db = await getDb(dataDir);
|
|
292
|
+
await db.query(
|
|
293
|
+
entry
|
|
294
|
+
? `UPDATE scheduler.schedules
|
|
295
|
+
SET result_delivery = COALESCE(result_delivery, '{}'::jsonb) || jsonb_build_object($2::text, $3::jsonb)
|
|
296
|
+
WHERE name = $1`
|
|
297
|
+
: `UPDATE scheduler.schedules
|
|
298
|
+
SET result_delivery = NULLIF(COALESCE(result_delivery, '{}'::jsonb) - $2::text, '{}'::jsonb)
|
|
299
|
+
WHERE name = $1`,
|
|
300
|
+
entry ? [name, runId, JSON.stringify(entry)] : [name, runId]
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** A fire skipped because the previous run of the same schedule still runs. */
|
|
305
|
+
export async function markScheduleSkipped(name, ts = new Date(), { dataDir } = {}) {
|
|
306
|
+
return updateScheduleColumn(name, 'last_skipped_at', ts, dataDir);
|
|
248
307
|
}
|
|
249
308
|
|
|
250
309
|
export async function markDone(name, { dataDir } = {}) {
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { logWebhook } from './log.mjs';
|
|
2
|
-
import { updateDeliveryStatus } from '../webhooks-db.mjs';
|
|
2
|
+
import { recordEndpointEvent, updateDeliveryStatus } from '../webhooks-db.mjs';
|
|
3
3
|
import { UNTRUSTED_MARKER, scrubFenceMarker } from './untrusted-fence.mjs';
|
|
4
4
|
|
|
5
5
|
const DISPATCH_TIMEOUT_MS = 10 * 60 * 1000;
|
|
6
6
|
|
|
7
|
+
/** The headers a run's prompt shows (and a stored event keeps). */
|
|
8
|
+
function promptHeaders(headers) {
|
|
9
|
+
return Object.fromEntries(Object.entries(headers || {}).filter(([k]) => k.startsWith('x-') || k === 'content-type'));
|
|
10
|
+
}
|
|
11
|
+
|
|
7
12
|
function buildFencedPayload(body, headers) {
|
|
8
13
|
// Trust boundary: webhook body + headers are external input and must be
|
|
9
14
|
// treated as DATA, never instructions. The directive line gives the
|
|
@@ -11,8 +16,7 @@ function buildFencedPayload(body, headers) {
|
|
|
11
16
|
const _UNTRUSTED = UNTRUSTED_MARKER;
|
|
12
17
|
const payload = scrubFenceMarker(JSON.stringify(body, null, 2));
|
|
13
18
|
const headersSummary = scrubFenceMarker(
|
|
14
|
-
Object.entries(headers)
|
|
15
|
-
.filter(([k]) => k.startsWith('x-') || k === 'content-type')
|
|
19
|
+
Object.entries(promptHeaders(headers))
|
|
16
20
|
.map(([k, v]) => `${k}: ${v}`)
|
|
17
21
|
.join('\n')
|
|
18
22
|
);
|
|
@@ -35,6 +39,14 @@ function webhookRunPrompt(instructions, body, headers) {
|
|
|
35
39
|
return { prompt: `${trusted}\n\n${buildFencedPayload(body, headers)}`, skillSelection: trusted };
|
|
36
40
|
}
|
|
37
41
|
|
|
42
|
+
/** A short label of the event for the routine marker in the bot's chat
|
|
43
|
+
* (display only, never model-visible): the sender's event type and action. */
|
|
44
|
+
function webhookEventSummary(headers, body) {
|
|
45
|
+
const field = (value) => (typeof value === 'string' ? value.trim() : '');
|
|
46
|
+
const type = field(headers?.['x-github-event']) || field(headers?.['sentry-hook-resource']) || field(body?.type);
|
|
47
|
+
return [type, field(body?.action)].filter(Boolean).join(' · ').slice(0, 120);
|
|
48
|
+
}
|
|
49
|
+
|
|
38
50
|
function trackDispatch({ name, deliveryId, dispatchP, controller }) {
|
|
39
51
|
let settled = false;
|
|
40
52
|
const timeoutHandle = setTimeout(
|
|
@@ -63,7 +75,10 @@ function trackDispatch({ name, deliveryId, dispatchP, controller }) {
|
|
|
63
75
|
{ once: true }
|
|
64
76
|
);
|
|
65
77
|
dispatchP.then(
|
|
66
|
-
() =>
|
|
78
|
+
(run) =>
|
|
79
|
+
run?.skipped
|
|
80
|
+
? finish('skipped', {}, `${name}: previous run still in progress; skipped (id=${deliveryId})`)
|
|
81
|
+
: finish('done', {}, `${name}: webhook session run dispatched (id=${deliveryId})`),
|
|
67
82
|
(err) =>
|
|
68
83
|
finish(
|
|
69
84
|
'failed',
|
|
@@ -73,8 +88,8 @@ function trackDispatch({ name, deliveryId, dispatchP, controller }) {
|
|
|
73
88
|
);
|
|
74
89
|
}
|
|
75
90
|
|
|
76
|
-
function createWebhookSessionDispatcher({
|
|
77
|
-
async function dispatchSessionRun(name,
|
|
91
|
+
function createWebhookSessionDispatcher({ getBridgeDispatch }) {
|
|
92
|
+
async function dispatchSessionRun(name, fullPrompt, deliveryId, res, extra = {}) {
|
|
78
93
|
await updateDeliveryStatus(name, deliveryId, 'processing');
|
|
79
94
|
// Session dispatch must not be allowed to hang forever — without a
|
|
80
95
|
// ceiling a stuck LLM call leaves the delivery in `processing`
|
|
@@ -88,13 +103,10 @@ function createWebhookSessionDispatcher({ getConfig, getBridgeDispatch }) {
|
|
|
88
103
|
const controller = new AbortController();
|
|
89
104
|
const dispatchP = Promise.resolve(
|
|
90
105
|
getBridgeDispatch()({
|
|
91
|
-
model: model || null,
|
|
92
106
|
prompt: fullPrompt,
|
|
93
107
|
signal: controller.signal,
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
cwd: extra.cwd || getConfig()?.cwd || null,
|
|
97
|
-
workflow: extra.workflow || null,
|
|
108
|
+
// The endpoint's project folder, named to the bot in the turn.
|
|
109
|
+
cwd: extra.cwd || null,
|
|
98
110
|
attachments: extra.attachments || null,
|
|
99
111
|
delivery: extra.delivery || null,
|
|
100
112
|
// Trusted skill-selection input: only the endpoint-authored
|
|
@@ -104,8 +116,10 @@ function createWebhookSessionDispatcher({ getConfig, getBridgeDispatch }) {
|
|
|
104
116
|
context: {
|
|
105
117
|
source: 'webhook',
|
|
106
118
|
endpoint: name,
|
|
119
|
+
// The bot whose chat the run is a turn in.
|
|
120
|
+
owner: extra.owner || null,
|
|
107
121
|
deliveryId,
|
|
108
|
-
event:
|
|
122
|
+
event: extra.event || null,
|
|
109
123
|
},
|
|
110
124
|
})
|
|
111
125
|
);
|
|
@@ -116,12 +130,18 @@ function createWebhookSessionDispatcher({ getConfig, getBridgeDispatch }) {
|
|
|
116
130
|
|
|
117
131
|
async function dispatchEndpoint({ name, body, headers, res, deliveryId, endpoint }) {
|
|
118
132
|
try {
|
|
119
|
-
const {
|
|
133
|
+
const { instructions, cwd, attachments, delivery, ownerAgentId } = endpoint;
|
|
120
134
|
const run = webhookRunPrompt(instructions, body, headers);
|
|
121
135
|
if (!getBridgeDispatch()) throw new Error(`[webhook] session dispatch requires bridgeDispatch`);
|
|
122
|
-
|
|
136
|
+
// Kept for the app's "Run now", which re-runs the latest event. Losing
|
|
137
|
+
// the record never blocks the delivery itself.
|
|
138
|
+
await recordEndpointEvent(name, { body, headers: promptHeaders(headers) }).catch((e) =>
|
|
139
|
+
logWebhook(`${name}: event record failed: ${e?.message || e}`)
|
|
140
|
+
);
|
|
141
|
+
await dispatchSessionRun(name, run.prompt, deliveryId, res, {
|
|
142
|
+
owner: ownerAgentId || null,
|
|
123
143
|
cwd: cwd || null,
|
|
124
|
-
|
|
144
|
+
event: webhookEventSummary(headers, body),
|
|
125
145
|
attachments: attachments || null,
|
|
126
146
|
delivery: delivery || null,
|
|
127
147
|
skillSelection: run.skillSelection,
|
|
@@ -137,4 +157,4 @@ function createWebhookSessionDispatcher({ getConfig, getBridgeDispatch }) {
|
|
|
137
157
|
return { dispatchEndpoint };
|
|
138
158
|
}
|
|
139
159
|
|
|
140
|
-
export { buildFencedPayload, createWebhookSessionDispatcher, webhookRunPrompt };
|
|
160
|
+
export { buildFencedPayload, createWebhookSessionDispatcher, promptHeaders, webhookEventSummary, webhookRunPrompt };
|