mixdog 1.2.6 → 1.3.1
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 +71 -9
- package/package.json +4 -1
- package/scripts/check-model-recommendations.mjs +89 -0
- package/scripts/gate-local.mjs +7 -0
- package/scripts/lib/isolated-test-env.mjs +16 -0
- package/src/agents/reviewer/AGENT.md +4 -2
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +10 -0
- package/src/defaults/skills/browser-use/SKILL.md +5 -0
- package/src/defaults/skills/memory-management/SKILL.md +4 -1
- package/src/defaults/skills/setup/references/actions.md +14 -4
- package/src/defaults/skills/setup-guide/SKILL.md +178 -0
- package/src/defaults/skills/setup-guide/model-recommendations.json +333 -0
- package/src/lib/rules-builder.cjs +55 -6
- package/src/output-styles/common.md +13 -8
- package/src/rules/agent/AGENT.md +4 -0
- package/src/rules/agent-mode/AGENT_MODE.md +24 -0
- package/src/rules/agent-mode/MIXY.md +28 -0
- package/src/rules/agent-mode/ROUTINE.md +6 -0
- package/src/rules/lead/LEAD.md +7 -3
- package/src/rules/shared/70-delivery.md +3 -0
- package/src/runtime/agent/orchestrator/agent-runtime/room-supervisor-completion.mjs +86 -0
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +77 -14
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +241 -14
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +4 -2
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +216 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -4
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +10 -1
- package/src/runtime/agent/orchestrator/mcp/client.mjs +115 -11
- package/src/runtime/agent/orchestrator/mcp/oauth-account.mjs +97 -0
- 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/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +7 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +10 -3
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/auto-effort.mjs +7 -8
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/lib/tool-call-wire-ids.mjs +65 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-retry-profile.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +17 -12
- package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/openai-responses-input.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +14 -2
- package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +17 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +96 -1
- 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 +14 -0
- 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 +21 -5
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +40 -7
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +52 -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-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 +166 -0
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +650 -0
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +7 -1
- 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 +192 -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/loop/compact-policy.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +108 -6
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +74 -15
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +9 -1
- 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 +49 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +18 -8
- 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 +3 -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/pending-lifecycle-epoch.mjs +0 -8
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +44 -16
- package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +50 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +22 -5
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +39 -4
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +33 -24
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +58 -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/turn-checkpoint.mjs +7 -1
- 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/mixy-name.mjs +27 -0
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +32 -5
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +86 -0
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +329 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +28 -9
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +16 -2
- 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-visibility.mjs +0 -4
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +58 -10
- package/src/runtime/agent/orchestrator/session/transcript-restore/user-text.mjs +92 -15
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +12 -0
- package/src/runtime/agent/orchestrator/tools/builtin/native-search-client.mjs +113 -5
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +4 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +25 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +3 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +75 -57
- package/src/runtime/attachments/store.mjs +6 -0
- 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/effort-judge/judge-client.mjs +1 -1
- package/src/runtime/effort-judge/model-manifest.json +7 -7
- 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/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/tool-call-handler.mjs +2 -0
- package/src/runtime/memory/tool-defs.mjs +5 -0
- 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-kind.mjs +152 -0
- package/src/runtime/shared/agent-route-config.d.mts +4 -0
- package/src/runtime/shared/agent-route-config.mjs +30 -0
- package/src/runtime/shared/agent-store.mjs +132 -0
- package/src/runtime/shared/atomic-file.mjs +14 -1
- package/src/runtime/shared/bot-split-migration.mjs +457 -0
- package/src/runtime/shared/config-patch.mjs +20 -1
- package/src/runtime/shared/config.mjs +8 -1
- package/src/runtime/shared/connector-accounts.mjs +15 -0
- package/src/runtime/shared/connector-catalog.d.mts +51 -0
- package/src/runtime/shared/connector-catalog.mjs +228 -0
- package/src/runtime/shared/connector-triggers.d.mts +3 -0
- package/src/runtime/shared/connector-triggers.mjs +45 -0
- package/src/runtime/shared/err-text.mjs +3 -1
- package/src/runtime/shared/error-presentation.mjs +91 -6
- package/src/runtime/shared/google-oauth-client.mjs +24 -0
- package/src/runtime/shared/handoff-artifacts.d.mts +20 -0
- package/src/runtime/shared/handoff-artifacts.mjs +61 -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/provider-model-identities.mjs +6 -1
- package/src/runtime/shared/llm/usage-accounting.mjs +7 -1
- package/src/runtime/shared/model-route-fallback.mjs +79 -7
- package/src/runtime/shared/plain-preview.d.mts +1 -0
- package/src/runtime/shared/plain-preview.mjs +33 -0
- 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/schedule-model-ref.mjs +9 -10
- package/src/runtime/shared/sensitive-path-rules.d.mts +15 -0
- package/src/runtime/shared/sensitive-path-rules.mjs +256 -0
- package/src/runtime/shared/slow-span.mjs +4 -12
- package/src/runtime/shared/statusline/statusline-segments.mjs +13 -1
- 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 +58 -0
- package/src/runtime/shared/user-data-guard.mjs +119 -38
- package/src/session-runtime/agent-home-delivery.mjs +826 -0
- package/src/session-runtime/agent-profile-changes.mjs +21 -0
- package/src/session-runtime/agent-room-delivery.mjs +133 -0
- package/src/session-runtime/agent-task-sessions.mjs +460 -0
- package/src/session-runtime/boot/apis.mjs +63 -18
- package/src/session-runtime/boot/facade.mjs +5 -8
- package/src/session-runtime/boot/infrastructure.mjs +28 -17
- package/src/session-runtime/boot/providers.mjs +14 -4
- package/src/session-runtime/boot/tools.mjs +3 -0
- package/src/session-runtime/channel-config-api.mjs +53 -5
- package/src/session-runtime/config-lifecycle.mjs +43 -2
- 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/handoff-attachments.mjs +593 -0
- 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 +56 -3
- 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/resume.mjs +4 -0
- package/src/session-runtime/lifecycle/shared.mjs +6 -0
- 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/route-persist.mjs +2 -2
- package/src/session-runtime/model-route/route-tuning.mjs +7 -1
- package/src/session-runtime/model-route/set-route.mjs +35 -4
- package/src/session-runtime/native-web-search.mjs +2 -2
- package/src/session-runtime/new-session-config.mjs +6 -1
- package/src/session-runtime/owned-automation-run.mjs +229 -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/route-resolution.mjs +5 -11
- 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/helpers.mjs +30 -1
- package/src/session-runtime/services/agent-tool/send-flow.mjs +11 -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 +4 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +5 -8
- package/src/session-runtime/services/agent-tool/tool-def.mjs +7 -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 +74 -39
- package/src/session-runtime/services/schedule-access.mjs +91 -0
- 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 +79 -6
- package/src/session-runtime/setup-tool/extended-actions.mjs +90 -20
- package/src/session-runtime/setup-tool/settings-contract.mjs +14 -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 +249 -29
- package/src/session-runtime/turn/session-ops.mjs +8 -1
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +10 -2
- package/src/session-runtime/turn/turn-run/turn-prepare.mjs +14 -0
- 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 +650 -25
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +67 -7
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +11 -4
- 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/daemon-agent-control.mjs +1 -8
- package/src/standalone/daemon-session-control.mjs +21 -4
- package/src/standalone/daemon.mjs +31 -5
- package/src/standalone/session-protocol.mjs +27 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +46 -3
- package/src/standalone/session-service/agent-tree.mjs +4 -3
- package/src/standalone/session-service/session-calls/session-turns.mjs +28 -0
- package/src/standalone/session-service.mjs +19 -0
- package/src/tui/app/slash-commands.mjs +20 -0
- package/src/tui/dist/index.mjs +234 -95
- package/src/tui/session/context-state.mjs +6 -1
- package/src/tui/session/notice-surface.mjs +34 -4
- 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 +5 -0
- package/src/tui/session/session-api/integrations.mjs +8 -0
- 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 +61 -5
- package/src/tui/session/session-flow/drain.mjs +12 -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 +58 -24
- package/src/tui/session/tool-approval.mjs +26 -5
- package/src/tui/session/transcript-intake.mjs +8 -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 +64 -0
- package/src/tui/session/turn.mjs +34 -8
- package/src/session-runtime/automation-agents.mjs +0 -94
- package/src/session-runtime/automation-workflow.mjs +0 -59
|
@@ -7,10 +7,10 @@ import { promptContentText } from './queue-helpers.mjs';
|
|
|
7
7
|
// Restore window for persisted busy-input steering rows. Rows older than this
|
|
8
8
|
// are leftovers of a session that ended long ago — restoring them into a fresh
|
|
9
9
|
// TUI boot reads as a surprise self-injection (user report), so they are
|
|
10
|
-
// discarded
|
|
10
|
+
// discarded when the mirror is read instead.
|
|
11
11
|
const STALE_STEERING_RESTORE_TTL_MS = 30 * 60 * 1000;
|
|
12
12
|
|
|
13
|
-
// Serialize this UI process's own steering writes so append→drop→
|
|
13
|
+
// Serialize this UI process's own steering writes so append→drop→read keep
|
|
14
14
|
// their issue order even though each now waits on the lock asynchronously.
|
|
15
15
|
// Cross-process mutual exclusion still comes from the shared lock protocol;
|
|
16
16
|
// this chain only orders same-process operations that were previously
|
|
@@ -59,23 +59,40 @@ function newSteeringPersistId() {
|
|
|
59
59
|
return `ts_${Date.now().toString(36)}_${randomBytes(4).toString('hex')}`;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
// What the accepted input runs: its executable content (attachment
|
|
63
|
+
// references), the pasted-attachment links and transcript metadata it was
|
|
64
|
+
// submitted with, and its run options. Callbacks and live queue state never
|
|
65
|
+
// reach the spool.
|
|
66
|
+
function persistedQueuePayload(entry) {
|
|
67
|
+
const out = {};
|
|
68
|
+
if (typeof entry.content === 'string' || Array.isArray(entry.content)) out.content = entry.content;
|
|
69
|
+
for (const field of ['pastedImages', 'pastedTexts', 'transcriptMeta']) {
|
|
70
|
+
const value = entry[field];
|
|
71
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) out[field] = value;
|
|
72
|
+
}
|
|
73
|
+
for (const field of ['mode', 'priority', 'context']) {
|
|
74
|
+
if (typeof entry[field] === 'string' && entry[field]) out[field] = entry[field];
|
|
66
75
|
}
|
|
76
|
+
if (entry.skipSlashCommands === true) out.skipSlashCommands = true;
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function normalizeTuiSteeringQueueEntry(entry) {
|
|
81
|
+
if (typeof entry === 'string') entry = { text: entry };
|
|
67
82
|
if (!entry || typeof entry !== 'object') return null;
|
|
68
83
|
if (typeof entry.text === 'string' && entry.text.trim()) {
|
|
69
84
|
const text = entry.text.trim();
|
|
70
|
-
|
|
85
|
+
// A row of an older build may have no id; it gets one here, under the
|
|
86
|
+
// shard lock, so every later read and drop names the same row.
|
|
87
|
+
const id = typeof entry.id === 'string' && entry.id.trim() ? entry.id.trim() : newSteeringPersistId();
|
|
71
88
|
const submissionId =
|
|
72
89
|
typeof entry.submissionId === 'string' && entry.submissionId.trim() ? entry.submissionId.trim() : null;
|
|
73
90
|
const submittedAt = Number(entry.submittedAt);
|
|
74
|
-
if (!id) return text;
|
|
75
91
|
const at = Number(entry.at);
|
|
76
92
|
return {
|
|
77
93
|
id,
|
|
78
94
|
text,
|
|
95
|
+
...persistedQueuePayload(entry),
|
|
79
96
|
...(Number.isFinite(at) && at > 0 ? { at } : {}),
|
|
80
97
|
...(submissionId ? { submissionId } : {}),
|
|
81
98
|
...(Number.isFinite(submittedAt) && submittedAt > 0 ? { submittedAt } : {}),
|
|
@@ -131,24 +148,15 @@ function entryPersistText(entry) {
|
|
|
131
148
|
return text;
|
|
132
149
|
}
|
|
133
150
|
|
|
134
|
-
|
|
135
|
-
const persistId = entry?.steeringPersistId;
|
|
136
|
-
if (persistId) {
|
|
137
|
-
return Boolean(row && typeof row === 'object' && row.id === persistId);
|
|
138
|
-
}
|
|
139
|
-
const text = entryPersistText(entry);
|
|
140
|
-
if (!text) return false;
|
|
141
|
-
return row === text;
|
|
142
|
-
}
|
|
143
|
-
|
|
151
|
+
// Every stored row has an id (normalize assigns one), so a row is named by it.
|
|
144
152
|
function removePersistRow(q, entry) {
|
|
145
|
-
const idx = q.findIndex((row) =>
|
|
153
|
+
const idx = q.findIndex((row) => row.id === entry?.steeringPersistId);
|
|
146
154
|
if (idx >= 0) q.splice(idx, 1);
|
|
147
155
|
}
|
|
148
156
|
|
|
149
157
|
// Consistency-required: a dropped append loses a user's queued steering
|
|
150
158
|
// message, so we async-wait for the lock (never try-once). Returns a promise;
|
|
151
|
-
// fire-and-forget at call sites is fine — _serialize keeps append/drop/
|
|
159
|
+
// fire-and-forget at call sites is fine — _serialize keeps append/drop/read
|
|
152
160
|
// in issue order and the write never blocks the render loop.
|
|
153
161
|
export function appendTuiSteeringPersist(leadSessionId, entry) {
|
|
154
162
|
const text = entryPersistText(entry);
|
|
@@ -158,13 +166,22 @@ export function appendTuiSteeringPersist(leadSessionId, entry) {
|
|
|
158
166
|
if (!entry.steeringPersistId) entry.steeringPersistId = newSteeringPersistId();
|
|
159
167
|
const submissionId = typeof entry.id === 'string' && entry.id.trim() ? entry.id.trim() : null;
|
|
160
168
|
const submittedAt = Number(entry.submittedAt);
|
|
161
|
-
const
|
|
169
|
+
const identity = {
|
|
162
170
|
id: entry.steeringPersistId,
|
|
163
171
|
text,
|
|
164
172
|
at: Date.now(),
|
|
165
173
|
...(submissionId ? { submissionId } : {}),
|
|
166
174
|
...(Number.isFinite(submittedAt) && submittedAt > 0 ? { submittedAt } : {}),
|
|
167
175
|
};
|
|
176
|
+
// A JSON snapshot taken now: the lock wait below must not let a later
|
|
177
|
+
// edit of the live entry change what was accepted. A payload JSON cannot
|
|
178
|
+
// carry still leaves the input itself durable.
|
|
179
|
+
let record;
|
|
180
|
+
try {
|
|
181
|
+
record = JSON.parse(JSON.stringify({ ...identity, ...persistedQueuePayload(entry) }));
|
|
182
|
+
} catch {
|
|
183
|
+
record = identity;
|
|
184
|
+
}
|
|
168
185
|
return _serialize(key, async () => {
|
|
169
186
|
try {
|
|
170
187
|
await updatePendingShard(key, (raw) => {
|
|
@@ -225,30 +242,27 @@ export function _steeringPersistChainCount() {
|
|
|
225
242
|
return _persistChains.size;
|
|
226
243
|
}
|
|
227
244
|
|
|
228
|
-
function
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
submissionId: typeof row.submissionId === 'string' ? row.submissionId : null,
|
|
237
|
-
submittedAt: Number.isFinite(Number(row.submittedAt)) ? Number(row.submittedAt) : null,
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
return null;
|
|
245
|
+
function persistedRowToRestore(row) {
|
|
246
|
+
return {
|
|
247
|
+
...persistedQueuePayload(row),
|
|
248
|
+
text: row.text,
|
|
249
|
+
steeringPersistId: row.id,
|
|
250
|
+
submissionId: typeof row.submissionId === 'string' ? row.submissionId : null,
|
|
251
|
+
submittedAt: Number.isFinite(Number(row.submittedAt)) ? Number(row.submittedAt) : null,
|
|
252
|
+
};
|
|
241
253
|
}
|
|
242
254
|
|
|
243
255
|
// Consistency-required (restores queued messages after boot/command). Async
|
|
244
256
|
// lock wait, serialized on _persistChain so it never reorders against a
|
|
245
257
|
// pending append/drop and never blocks the render loop. Returns a promise of
|
|
246
|
-
// the
|
|
247
|
-
|
|
258
|
+
// the stored rows; call sites await it. A read never consumes: a row stays
|
|
259
|
+
// durable until the queue commits, reclaims or closes it (drop), so a
|
|
260
|
+
// restart before then restores it again.
|
|
261
|
+
export function readTuiSteeringPersist(leadSessionId) {
|
|
248
262
|
const key = tuiSteeringSessionKey(leadSessionId);
|
|
249
263
|
if (!key) return Promise.resolve([]);
|
|
250
264
|
return _serialize(key, async () => {
|
|
251
|
-
let
|
|
265
|
+
let restored = [];
|
|
252
266
|
let droppedStale = 0;
|
|
253
267
|
try {
|
|
254
268
|
await updatePendingShard(key, (raw) => {
|
|
@@ -262,18 +276,27 @@ export function drainTuiSteeringPersist(leadSessionId) {
|
|
|
262
276
|
if (stale) droppedStale += 1;
|
|
263
277
|
return !stale;
|
|
264
278
|
});
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
279
|
+
restored = fresh.map(persistedRowToRestore);
|
|
280
|
+
// Write only to drop stale rows or to keep the ids normalize gave
|
|
281
|
+
// rows of an older build.
|
|
282
|
+
const stored = Array.isArray(raw?.sessions?.[key]) ? raw.sessions[key] : [];
|
|
283
|
+
if (droppedStale === 0 && stored.every((row) => typeof row?.id === 'string' && row.id.trim())) {
|
|
284
|
+
return undefined;
|
|
285
|
+
}
|
|
286
|
+
if (fresh.length > 0) next.sessions[key] = fresh;
|
|
287
|
+
else deleteSessionBucket(next, key);
|
|
268
288
|
next.updatedAt = Date.now();
|
|
269
289
|
return next;
|
|
270
290
|
});
|
|
271
291
|
} catch (err) {
|
|
272
|
-
|
|
292
|
+
// An id assigned to an older row that never reached disk names nothing.
|
|
293
|
+
restored = [];
|
|
294
|
+
droppedStale = 0;
|
|
295
|
+
writeSteeringDiagnostic(`steering-queue read failed sessionId=${leadSessionId}: ${err?.message || err}`);
|
|
273
296
|
}
|
|
274
297
|
if (droppedStale > 0) {
|
|
275
298
|
writeSteeringDiagnostic(`dropped ${droppedStale} stale steering row(s) sessionId=${leadSessionId}`);
|
|
276
299
|
}
|
|
277
|
-
return
|
|
300
|
+
return restored;
|
|
278
301
|
});
|
|
279
302
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tui/session/turn-live-call.mjs — the live decode speed of the model call
|
|
3
|
+
* that is streaming right now (`spinner.liveCall`), for the desktop composer's
|
|
4
|
+
* usage readout.
|
|
5
|
+
*
|
|
6
|
+
* Providers report a call's exact output tokens only when it ends (the usage
|
|
7
|
+
* delta), so mid-stream the count is the runtime's own token estimate of the
|
|
8
|
+
* text and reasoning streamed so far (token-estimate.mjs, measured against a
|
|
9
|
+
* real tokenizer at +6.5% aggregate bias). The clock starts when the provider
|
|
10
|
+
* request starts (markLiveCallRequestStart), the wait for the first token
|
|
11
|
+
* included, the same span as the persisted speed and the usage ledger; with no
|
|
12
|
+
* request-start mark it starts at the first visible text/reasoning token.
|
|
13
|
+
*
|
|
14
|
+
* Published at most every LIVE_CALL_PUBLISH_MS with its own sample time, so the
|
|
15
|
+
* reader divides tokens by (sample time - start) and a pause between samples
|
|
16
|
+
* never skews the figure. A tool call's arguments stream without text the
|
|
17
|
+
* runtime can count: once the call turns to one, the live figure is withdrawn
|
|
18
|
+
* until the next call rather than decaying against tokens nobody counted. The
|
|
19
|
+
* call's usage delta ends it.
|
|
20
|
+
*/
|
|
21
|
+
import { estimateTokens } from '../../runtime/agent/orchestrator/session/token-estimate.mjs';
|
|
22
|
+
|
|
23
|
+
export const LIVE_CALL_PUBLISH_MS = 250;
|
|
24
|
+
|
|
25
|
+
function publish({ getState, set }, liveCall) {
|
|
26
|
+
const spinner = getState().spinner;
|
|
27
|
+
if (spinner) set({ spinner: { ...spinner, liveCall } });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** The provider request of the next call started: its clock starts here. */
|
|
31
|
+
export function markLiveCallRequestStart(stream, now = Date.now()) {
|
|
32
|
+
stream.liveCallRequestAt = now;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** A text or reasoning chunk of the streaming call arrived. */
|
|
36
|
+
export function noteLiveCallText(stream, chunk, now = Date.now()) {
|
|
37
|
+
const text = String(chunk ?? '');
|
|
38
|
+
if (!text || stream.liveCallWithdrawn) return;
|
|
39
|
+
const call = stream.liveCall || { startedAt: stream.liveCallRequestAt ?? now, text: '', publishedAt: 0 };
|
|
40
|
+
stream.liveCall = call;
|
|
41
|
+
call.text += text;
|
|
42
|
+
if (call.publishedAt && now - call.publishedAt < LIVE_CALL_PUBLISH_MS) return;
|
|
43
|
+
call.publishedAt = now;
|
|
44
|
+
publish(stream, { startedAt: call.startedAt, outputTokens: estimateTokens(call.text), at: now });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The call turned to a tool call (withdraw until the next call) or was reset. */
|
|
48
|
+
export function withdrawLiveCall(stream) {
|
|
49
|
+
stream.liveCallWithdrawn = true;
|
|
50
|
+
endLiveCall(stream);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** The call ended (its usage delta landed): the next call starts fresh. */
|
|
54
|
+
export function endLiveCall(stream) {
|
|
55
|
+
const had = Boolean(stream.liveCall) || Boolean(stream.getState().spinner?.liveCall);
|
|
56
|
+
stream.liveCall = null;
|
|
57
|
+
if (had) publish(stream, null);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function startNextLiveCall(stream) {
|
|
61
|
+
stream.liveCallWithdrawn = false;
|
|
62
|
+
stream.liveCallRequestAt = null;
|
|
63
|
+
endLiveCall(stream);
|
|
64
|
+
}
|
package/src/tui/session/turn.mjs
CHANGED
|
@@ -54,6 +54,13 @@ import {
|
|
|
54
54
|
startLiveTail,
|
|
55
55
|
} from './turn-tool-cards.mjs';
|
|
56
56
|
import { startQuietWatch } from './turn-quiet.mjs';
|
|
57
|
+
import {
|
|
58
|
+
endLiveCall,
|
|
59
|
+
markLiveCallRequestStart,
|
|
60
|
+
noteLiveCallText,
|
|
61
|
+
startNextLiveCall,
|
|
62
|
+
withdrawLiveCall,
|
|
63
|
+
} from './turn-live-call.mjs';
|
|
57
64
|
|
|
58
65
|
// A usage limit is exactly a spent quota, a plan-gated feature or a billing
|
|
59
66
|
// refusal; overloads, rate limits and server faults recover by waiting.
|
|
@@ -203,8 +210,9 @@ function steeringItemExtras(steeringMeta) {
|
|
|
203
210
|
? { messageId: steeringMeta.messageId }
|
|
204
211
|
: {}),
|
|
205
212
|
// Queue mode + execution provenance: a task notification is rendered as
|
|
206
|
-
// a tool card, never as an injected user bubble.
|
|
207
|
-
|
|
213
|
+
// a tool card, never as an injected user bubble. Anything else is a
|
|
214
|
+
// message the model read inside its running turn (the row's read mark).
|
|
215
|
+
...(steeringMeta?.mode === 'task-notification' ? { mode: 'task-notification' } : { steered: true }),
|
|
208
216
|
...(steeringMeta?.execution && typeof steeringMeta.execution === 'object'
|
|
209
217
|
? { execution: steeringMeta.execution }
|
|
210
218
|
: {}),
|
|
@@ -336,10 +344,15 @@ export function applyCompactEvent(ctx, event) {
|
|
|
336
344
|
set({ ...routeState(), stats: { ...getState().stats } });
|
|
337
345
|
}
|
|
338
346
|
|
|
339
|
-
function applyTurnUsageDelta(
|
|
347
|
+
function applyTurnUsageDelta(ctx, delta) {
|
|
348
|
+
const { turn, getState, set, syncContextStats } = ctx;
|
|
340
349
|
const stats = { ...getState().stats };
|
|
341
350
|
applyUsageDelta(stats, delta);
|
|
342
351
|
set({ stats });
|
|
352
|
+
// The call is over: the composer's live speed gives way to the session's
|
|
353
|
+
// figure, which this delta's exact usage has just joined.
|
|
354
|
+
startNextLiveCall(ctx.stream);
|
|
355
|
+
// Publishes the session's persisted usage totals (stats.usageReadout) too.
|
|
343
356
|
syncContextStats({ allowEstimated: true });
|
|
344
357
|
const inputTokens = Math.max(0, getState().stats.inputTokens - turn.inputBaseline);
|
|
345
358
|
const outputTokens = Math.max(0, getState().stats.outputTokens - turn.outputBaseline);
|
|
@@ -369,7 +382,6 @@ function turnHandlers(ctx) {
|
|
|
369
382
|
},
|
|
370
383
|
drainSteering: (_sessionId, drainOptions) =>
|
|
371
384
|
isCurrentTurn() ? drainPendingSteering({ ...drainOptions, turnEpoch: ctx.turn.epoch }) : [],
|
|
372
|
-
onStreamDelta: () => {},
|
|
373
385
|
onSteerMessage: (text, steeringMeta = {}) => {
|
|
374
386
|
if (isCurrentTurn()) injectSteerMessage(ctx, text, steeringMeta);
|
|
375
387
|
},
|
|
@@ -422,6 +434,9 @@ export function toolHandlers(ctx) {
|
|
|
422
434
|
export function streamHandlers(ctx) {
|
|
423
435
|
const { isCurrentTurn, stream } = ctx;
|
|
424
436
|
return {
|
|
437
|
+
onProviderSendStarted: () => {
|
|
438
|
+
if (isCurrentTurn()) markLiveCallRequestStart(stream);
|
|
439
|
+
},
|
|
425
440
|
onStageChange: async (stage, detail = null) => {
|
|
426
441
|
if (!isCurrentTurn()) return;
|
|
427
442
|
// A runtime notice (e.g. a tool the provider left out of the request)
|
|
@@ -441,8 +456,13 @@ export function streamHandlers(ctx) {
|
|
|
441
456
|
// prompt — the runtime would rewind it while the host skipped the requeue.
|
|
442
457
|
if (textChunk.trim()) ctx.markPromptCommitted();
|
|
443
458
|
appendTextDelta(stream, textChunk);
|
|
459
|
+
noteLiveCallText(stream, textChunk);
|
|
460
|
+
},
|
|
461
|
+
onTextReset: (reset = {}) => {
|
|
462
|
+
if (!isCurrentTurn()) return false;
|
|
463
|
+
endLiveCall(stream);
|
|
464
|
+
return resetStreamedText(stream, reset);
|
|
444
465
|
},
|
|
445
|
-
onTextReset: (reset = {}) => (isCurrentTurn() ? resetStreamedText(stream, reset) : false),
|
|
446
466
|
onAssistantText: (text, detail) => {
|
|
447
467
|
const full = String(text ?? '');
|
|
448
468
|
if (!full.trim() || !isCurrentTurn()) return;
|
|
@@ -454,7 +474,9 @@ export function streamHandlers(ctx) {
|
|
|
454
474
|
appendAssistantText(stream, full, { committed: detail?.committed === true });
|
|
455
475
|
},
|
|
456
476
|
onReasoningDelta: (chunk) => {
|
|
457
|
-
if (isCurrentTurn())
|
|
477
|
+
if (!isCurrentTurn()) return;
|
|
478
|
+
appendReasoningDelta(stream, String(chunk ?? ''));
|
|
479
|
+
noteLiveCallText(stream, chunk);
|
|
458
480
|
},
|
|
459
481
|
// A provider output item started. A tool call ends the text before it
|
|
460
482
|
// (a preamble settles at the call's start, not after its arguments or
|
|
@@ -462,8 +484,10 @@ export function streamHandlers(ctx) {
|
|
|
462
484
|
// commentary or final answer.
|
|
463
485
|
onStreamItemStart: (detail) => {
|
|
464
486
|
if (!isCurrentTurn()) return;
|
|
465
|
-
if (detail?.kind === 'tool')
|
|
466
|
-
|
|
487
|
+
if (detail?.kind === 'tool') {
|
|
488
|
+
withdrawLiveCall(stream);
|
|
489
|
+
settleSegmentBeforeToolCall(ctx);
|
|
490
|
+
} else if (detail?.kind === 'text') noteAssistantPhase(stream, detail.phase);
|
|
467
491
|
},
|
|
468
492
|
};
|
|
469
493
|
}
|
|
@@ -725,6 +749,7 @@ export function createRunTurn(bag) {
|
|
|
725
749
|
try {
|
|
726
750
|
const { result, session } = await runtime.ask(userText, {
|
|
727
751
|
id: turn.submittedIds[0],
|
|
752
|
+
submissionIds: turn.submittedIds,
|
|
728
753
|
submittedAt: options.submittedAt,
|
|
729
754
|
promptSource: options.promptSource,
|
|
730
755
|
retryFailedTurn: options.retryFailedTurn === true,
|
|
@@ -732,6 +757,7 @@ export function createRunTurn(bag) {
|
|
|
732
757
|
retryAttemptId: options.retryAttemptId,
|
|
733
758
|
transcriptMeta: turn.transcriptMeta,
|
|
734
759
|
context: options.context || null,
|
|
760
|
+
...(typeof options.skillSelection === 'string' ? { skillSelection: options.skillSelection } : {}),
|
|
735
761
|
...turnHandlers(ctx),
|
|
736
762
|
...toolHandlers(ctx),
|
|
737
763
|
...streamHandlers(ctx),
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent delegation for automation sessions (schedules, webhooks). They run
|
|
3
|
-
* headless in the daemon, so no session runtime registers tools for them or
|
|
4
|
-
* receives their agents' completions. The daemon's canonical agent control is
|
|
5
|
-
* exposed under a dedicated internal-tool scope instead, and the completions of
|
|
6
|
-
* the agents a run starts come back here, where the run turns them into the
|
|
7
|
-
* conversation's next turn — what a Lead in a window does when one arrives.
|
|
8
|
-
*/
|
|
9
|
-
import { setInternalToolsProvider } from '../runtime/agent/orchestrator/internal-tools.mjs';
|
|
10
|
-
import { AGENT_TOOL } from './services/agent-tool/tool-def.mjs';
|
|
11
|
-
|
|
12
|
-
export const AUTOMATION_TOOL_SCOPE = 'automation';
|
|
13
|
-
// How long a run waits for the next result of an agent it started; past it the
|
|
14
|
-
// run ends with the conversation as it stands.
|
|
15
|
-
const AGENT_RESULT_WAIT_MS = 60 * 60_000;
|
|
16
|
-
|
|
17
|
-
const runs = new Map(); // sessionId → { pending: Set<taskId>, ready: string[], wake }
|
|
18
|
-
|
|
19
|
-
function resultText(result) {
|
|
20
|
-
return typeof result === 'string' ? result : JSON.stringify(result ?? '');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** Registers the agent tool for automation sessions; returns its disposer. */
|
|
24
|
-
export function registerAutomationAgentTool(executeAgentControl) {
|
|
25
|
-
return setInternalToolsProvider({
|
|
26
|
-
scopeId: AUTOMATION_TOOL_SCOPE,
|
|
27
|
-
tools: [AGENT_TOOL],
|
|
28
|
-
async executor(_name, args, callerCtx = {}) {
|
|
29
|
-
const result = await executeAgentControl(args, {
|
|
30
|
-
callerCwd: callerCtx.callerCwd,
|
|
31
|
-
invocationSource: 'model-tool',
|
|
32
|
-
callerSessionId: callerCtx.callerSessionId || null,
|
|
33
|
-
clientHostPid: process.pid,
|
|
34
|
-
signal: callerCtx.signal,
|
|
35
|
-
});
|
|
36
|
-
// A spawn/send acknowledgement ("agent task: <id>", "status: running")
|
|
37
|
-
// is a result still to come for this run.
|
|
38
|
-
const text = resultText(result);
|
|
39
|
-
const taskId = /agent task: ([\w.:-]+)/.exec(text)?.[1];
|
|
40
|
-
const run = runs.get(String(callerCtx.callerSessionId || ''));
|
|
41
|
-
if (run && taskId && /status: running/.test(text)) run.pending.add(taskId);
|
|
42
|
-
return result;
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** Hands an agent completion to the automation run that started the task; false when none did. */
|
|
48
|
-
export function deliverAutomationCompletion(sessionId, text, meta = {}) {
|
|
49
|
-
const run = runs.get(String(sessionId || ''));
|
|
50
|
-
const taskId = String(meta?.execution_id || '');
|
|
51
|
-
if (!run?.pending.has(taskId)) return false;
|
|
52
|
-
// The header-only preview precedes the body-carrying completion.
|
|
53
|
-
if (meta?.model_visible === false) return true;
|
|
54
|
-
run.pending.delete(taskId);
|
|
55
|
-
run.ready.push(String(text || ''));
|
|
56
|
-
run.wake?.();
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Ask options for a follow-up turn fed by agent results: the runtime reporting
|
|
61
|
-
// worker output, not the user — stored as a task notification and never a
|
|
62
|
-
// source of explicit skill selection.
|
|
63
|
-
export const AUTOMATION_RESULT_TURN_OPTS = Object.freeze({ promptSource: 'task-notification' });
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Runs an automation conversation to its end: the first turn, then one more
|
|
67
|
-
* turn per batch of agent results while agents it started are still out.
|
|
68
|
-
* `nextTurn(text, askOpts)` receives AUTOMATION_RESULT_TURN_OPTS as the
|
|
69
|
-
* results' provenance. Resolves with the last turn's result.
|
|
70
|
-
*/
|
|
71
|
-
export async function runAutomationTurns(sessionId, firstTurn, nextTurn, { waitMs = AGENT_RESULT_WAIT_MS } = {}) {
|
|
72
|
-
const run = { pending: new Set(), ready: [], wake: null };
|
|
73
|
-
runs.set(sessionId, run);
|
|
74
|
-
try {
|
|
75
|
-
let result = await firstTurn();
|
|
76
|
-
while (run.pending.size > 0 || run.ready.length > 0) {
|
|
77
|
-
if (run.ready.length === 0) {
|
|
78
|
-
const arrived = await new Promise((resolve) => {
|
|
79
|
-
const timer = setTimeout(() => resolve(false), waitMs);
|
|
80
|
-
run.wake = () => {
|
|
81
|
-
clearTimeout(timer);
|
|
82
|
-
resolve(true);
|
|
83
|
-
};
|
|
84
|
-
});
|
|
85
|
-
run.wake = null;
|
|
86
|
-
if (!arrived) break;
|
|
87
|
-
}
|
|
88
|
-
result = await nextTurn(run.ready.splice(0).join('\n\n'), { ...AUTOMATION_RESULT_TURN_OPTS });
|
|
89
|
-
}
|
|
90
|
-
return result;
|
|
91
|
-
} finally {
|
|
92
|
-
runs.delete(sessionId);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve a stored automation workflow id (schedule/webhook row) into
|
|
3
|
-
* createSession options: the workflow summary meta plus the WORKFLOW.md
|
|
4
|
-
* context block, exactly like a desktop New task session gets for the
|
|
5
|
-
* active workflow. An empty/unknown id resolves to the default pack via
|
|
6
|
-
* loadWorkflowPack's fallback; resolution failures degrade to no workflow
|
|
7
|
-
* context (the session still runs with the base lead ruleset).
|
|
8
|
-
*/
|
|
9
|
-
import { createWorkflowHelpers } from '../runtime/agent/orchestrator/runtime-core/workflow.mjs';
|
|
10
|
-
import { STANDALONE_ROOT, STANDALONE_DATA_DIR } from './runtime-paths.mjs';
|
|
11
|
-
import { readMarkdownDocument, normalizeAgentPermissionOrNone } from '../runtime/shared/markdown-frontmatter.mjs';
|
|
12
|
-
import { IMPLICIT_APPROVAL_MODE } from '../runtime/agent/orchestrator/session/approval-mode.mjs';
|
|
13
|
-
import { loadConfig } from '../runtime/agent/orchestrator/config.mjs';
|
|
14
|
-
import { configuredOrchestrationMode } from '../runtime/shared/orchestration.mjs';
|
|
15
|
-
import { AUTOMATION_TOOL_SCOPE } from './automation-agents.mjs';
|
|
16
|
-
|
|
17
|
-
let _helpers = null;
|
|
18
|
-
function helpers() {
|
|
19
|
-
if (!_helpers) {
|
|
20
|
-
_helpers = createWorkflowHelpers({
|
|
21
|
-
rootDir: STANDALONE_ROOT,
|
|
22
|
-
dataDir: STANDALONE_DATA_DIR,
|
|
23
|
-
readMarkdownDocument,
|
|
24
|
-
normalizeAgentPermissionOrNone,
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
return _helpers;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Non-interactive createSession opts, plus workflow context when the id resolves. */
|
|
31
|
-
export function automationWorkflowOpts(workflowId) {
|
|
32
|
-
const config = loadConfig({ secrets: false });
|
|
33
|
-
// The user's orchestration setting governs an automation exactly as it does a
|
|
34
|
-
// New task: a workflow id alone never turns delegation on, and the agent
|
|
35
|
-
// tool reaches the run through the automation tool scope.
|
|
36
|
-
const baseOpts = {
|
|
37
|
-
approvalMode: IMPLICIT_APPROVAL_MODE,
|
|
38
|
-
orchestrationMode: configuredOrchestrationMode(config),
|
|
39
|
-
mcpScopeId: AUTOMATION_TOOL_SCOPE,
|
|
40
|
-
};
|
|
41
|
-
const id = String(workflowId || '').trim();
|
|
42
|
-
if (!id) return baseOpts;
|
|
43
|
-
try {
|
|
44
|
-
const h = helpers();
|
|
45
|
-
const pack = h.loadWorkflowPack(undefined, id);
|
|
46
|
-
if (!pack) return baseOpts;
|
|
47
|
-
// The whole config, so disabled agents and the orchestration mode are the
|
|
48
|
-
// user's, with only the active workflow swapped for the automation's own.
|
|
49
|
-
const resolved = h.activeWorkflowContext({ ...config, workflow: { ...config.workflow, active: id } }, undefined);
|
|
50
|
-
return {
|
|
51
|
-
...baseOpts,
|
|
52
|
-
workflow: resolved.summary,
|
|
53
|
-
workflowContext: resolved.context,
|
|
54
|
-
orchestrationMode: resolved.orchestrationMode,
|
|
55
|
-
};
|
|
56
|
-
} catch {
|
|
57
|
-
return baseOpts;
|
|
58
|
-
}
|
|
59
|
-
}
|