mixdog 1.4.0 → 1.4.2
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/package.json +3 -2
- package/scripts/build-shipped-history.mjs +115 -33
- package/scripts/check-voice-runtime-inputs.mjs +25 -0
- package/scripts/gate-local.mjs +183 -63
- package/scripts/latest-guard.mjs +21 -9
- package/scripts/lib/gate-scheduler.mjs +138 -32
- package/scripts/lib/gate-timing-reporter.mjs +16 -0
- package/scripts/lib/isolated-test-env.mjs +10 -5
- package/scripts/lib/run-node-tests.mjs +91 -66
- package/scripts/lib/scoped-temp.d.mts +16 -0
- package/scripts/lib/scoped-temp.mjs +124 -0
- package/scripts/lib/stale-temp.mjs +44 -0
- package/scripts/lib/test-failure-records.mjs +14 -1
- package/scripts/lib/test-failure-summary.mjs +16 -4
- package/scripts/lib/test-spawn-ledger.mjs +12 -3
- package/scripts/post-release-check.mjs +1 -6
- package/scripts/pptx-kit-index.mjs +17 -5
- package/scripts/suite-health.mjs +115 -24
- package/scripts/test-data-dir.mjs +10 -7
- package/scripts/test.mjs +9 -14
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/explore/AGENT.md +22 -0
- package/src/agents/explore/agent.json +6 -0
- package/src/app.mjs +4 -0
- package/src/cli.mjs +7 -0
- package/src/defaults/agents.json +7 -0
- package/src/defaults/shipped-history.json +23 -2
- package/src/defaults/skills/browser-use/SKILL.md +10 -5
- package/src/defaults/skills/code-tidy/SKILL.md +71 -102
- package/src/defaults/skills/code-tidy/references/agent-cleanup.md +66 -114
- package/src/defaults/skills/code-tidy/references/cleanup-report.md +19 -35
- package/src/defaults/skills/code-tidy/references/dead-code.md +3 -9
- package/src/defaults/skills/code-tidy/references/test-suite-slop.md +16 -27
- package/src/defaults/skills/computer-use/SKILL.md +16 -4
- package/src/defaults/skills/goal-management/SKILL.md +1 -1
- package/src/defaults/skills/setup/references/actions.md +12 -6
- package/src/defaults/skills/setup/references/surfaces.md +2 -2
- package/src/defaults/skills/setup-guide/SKILL.md +5 -2
- package/src/defaults/skills/setup-guide/model-recommendations.json +13 -0
- package/src/defaults/skills/skill-creator/SKILL.md +85 -190
- package/src/defaults/skills/skill-creator/references/design.md +70 -162
- package/src/defaults/skills/skill-creator/references/evaluation.md +33 -92
- package/src/defaults/skills/test-suite/SKILL.md +194 -0
- package/src/defaults/skills/test-suite/references/case-management.md +51 -0
- package/src/defaults/skills/test-suite/references/flaky-policy.md +39 -0
- package/src/defaults/skills/test-suite/references/reliability.md +49 -0
- package/src/defaults/skills/test-suite/references/suite-design.md +78 -0
- package/src/defaults/skills/test-suite/scripts/inventory.mjs +335 -0
- package/src/defaults/skills/visualize/SKILL.md +6 -2
- package/src/lib/rules-builder.cjs +35 -42
- package/src/output-styles/common.md +2 -2
- package/src/output-styles/simple.md +1 -1
- package/src/rules/agent/AGENT.md +5 -4
- package/src/rules/lead/LEAD.md +12 -7
- package/src/rules/shared/10-tool-workflow.md +3 -1
- package/src/rules/shared/20-research.md +3 -6
- package/src/rules/shared/40-editing.md +1 -0
- package/src/rules/shared/45-destructive.md +0 -2
- package/src/rules/shared/50-execution.md +2 -0
- package/src/rules/shared/60-verification.md +10 -9
- package/src/rules/shared/70-delivery.md +8 -9
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/abort-link.mjs +5 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +10 -1
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +156 -24
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +13 -0
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +4 -1
- package/src/runtime/agent/orchestrator/cache-break-trace.mjs +2 -0
- package/src/runtime/agent/orchestrator/config.mjs +12 -7
- package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +8 -8
- package/src/runtime/agent/orchestrator/context/role-instructions.mjs +5 -26
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +3 -1
- package/src/runtime/agent/orchestrator/internal-agents.mjs +3 -14
- package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +122 -12
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +5 -3
- package/src/runtime/agent/orchestrator/mcp/client-config.mjs +13 -2
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +152 -58
- package/src/runtime/agent/orchestrator/mcp/client.mjs +51 -18
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +88 -54
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +42 -26
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +54 -8
- package/src/runtime/agent/orchestrator/providers/anthropic-api-recovery.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +37 -31
- package/src/runtime/agent/orchestrator/providers/anthropic-api-transport.mjs +8 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens-recovery.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +31 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/initial-status.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +6 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-turn-result.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/command-code-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/command-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +40 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider-keys.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/custom-provider.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +14 -7
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/devin.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/gemini-response.mjs +2 -2
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +248 -41
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-prefix-trace.mjs +76 -11
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +45 -6
- package/src/runtime/agent/orchestrator/providers/lib/first-output-window.mjs +58 -0
- package/src/runtime/agent/orchestrator/providers/lib/listen-on.mjs +14 -0
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +0 -18
- package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +138 -6
- package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +1 -10
- package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/model-cache.mjs +100 -33
- package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/oauth-secret-fields.fixtures.mjs +45 -0
- 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 +9 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +14 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +4 -2
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream-common.mjs +5 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +16 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events/output-items.mjs +5 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +13 -3
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +13 -2
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-watchdogs.mjs +81 -42
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +8 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +160 -31
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +22 -12
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-watchdogs.mjs +49 -22
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/registry.mjs +45 -2
- package/src/runtime/agent/orchestrator/providers/vertex-ai-auth.mjs +622 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-maas.mjs +185 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai-models.mjs +445 -0
- package/src/runtime/agent/orchestrator/providers/vertex-ai.mjs +567 -0
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +41 -13
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +8 -6
- package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +7 -3
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +6 -1
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +14 -5
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -0
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +5 -2
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +30 -5
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +171 -37
- package/src/runtime/agent/orchestrator/session/cache/scoped-cache.mjs +1 -3
- package/src/runtime/agent/orchestrator/session/cache-warm.mjs +102 -12
- package/src/runtime/agent/orchestrator/session/catalog-db/schema.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +1 -8
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/compact/observation-supersession.mjs +103 -23
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +160 -36
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/conversation-import/claude.mjs +164 -23
- package/src/runtime/agent/orchestrator/session/conversation-import/codex.mjs +139 -19
- package/src/runtime/agent/orchestrator/session/conversation-import/convert.mjs +38 -7
- package/src/runtime/agent/orchestrator/session/conversation-import/imported-session.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/conversation-import/turns.mjs +100 -22
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +4 -3
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -6
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +33 -3
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/provider-tool-exclusions.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +23 -4
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +39 -21
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +13 -8
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +50 -28
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +30 -13
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +63 -6
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +35 -13
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +24 -14
- package/src/runtime/agent/orchestrator/session/manager/session-scratch-environment.mjs +70 -0
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +0 -3
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +10 -6
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/turn-interruption.mjs +56 -29
- package/src/runtime/agent/orchestrator/session/manager/turn-reap.mjs +125 -0
- package/src/runtime/agent/orchestrator/session/mixy-name.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +30 -7
- package/src/runtime/agent/orchestrator/session/restart-prefix-parity.fixture.mjs +154 -0
- package/src/runtime/agent/orchestrator/session/store/session-delete.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/store-summary-fields.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +37 -8
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +252 -39
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +163 -64
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +164 -4
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +142 -18
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +61 -2
- package/src/runtime/agent/orchestrator/stall-policy.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +4 -2
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +46 -20
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +67 -31
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +25 -13
- package/src/runtime/agent/orchestrator/tools/builtin/lib/scoped-search-flight.mjs +9 -5
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +58 -20
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-stream.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-dispatch.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-publication.mjs +23 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-snapshot.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +1 -8
- package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +20 -15
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +96 -20
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +59 -10
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch/federation.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/isolated-test-env.mjs +4 -3
- package/src/runtime/agent/orchestrator/tools/lib/native-spawn-client.mjs +99 -2
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +103 -13
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +49 -15
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-spawn.mjs +45 -27
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +34 -10
- package/src/runtime/agent/orchestrator/tools/lib/shell-warm-standby.mjs +28 -4
- package/src/runtime/agent/orchestrator/tools/lib/wait-until-fixture.mjs +26 -0
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/channels/lib/webhook/signature.mjs +4 -1
- package/src/runtime/channels/lib/whisper-port.mjs +29 -11
- package/src/runtime/channels/lib/whisper-server.mjs +10 -1
- package/src/runtime/computer-bridge/action-schema.mjs +2 -2
- package/src/runtime/computer-bridge/core-actions.mjs +2 -2
- package/src/runtime/computer-bridge/error-recovery.mjs +5 -4
- package/src/runtime/computer-bridge/linux-action-capabilities.mjs +24 -5
- package/src/runtime/computer-bridge/linux-readiness.d.mts +7 -2
- package/src/runtime/connectors/connector-accounts-mcp.mjs +236 -103
- package/src/runtime/connectors/gmail-app-password.mjs +3 -3
- package/src/runtime/explore/explorer.mjs +93 -0
- package/src/runtime/explore/tool-defs.mjs +35 -0
- package/src/runtime/explore/tool.mjs +123 -0
- package/src/runtime/local-provider/server-process.mjs +2 -1
- package/src/runtime/media/adapters/gemini-video.mjs +4 -1
- package/src/runtime/media/adapters/xai-media.mjs +2 -1
- package/src/runtime/memory/index.mjs +4 -0
- package/src/runtime/memory/lib/embedding-provider.mjs +4 -1
- package/src/runtime/memory/lib/embedding-worker.mjs +10 -3
- package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +1 -7
- package/src/runtime/memory/lib/memory-chunk-quality.mjs +1 -6
- package/src/runtime/office/authoring/pdf-author-action.mjs +1 -6
- package/src/runtime/office/design/design-art-direction.mjs +29 -27
- package/src/runtime/office/pdf/pdf-writer.mjs +6 -1
- package/src/runtime/office/portable/portable-snapshot-docx.mjs +7 -1
- package/src/runtime/office/portable/portable-snapshot-shared.mjs +6 -1
- package/src/runtime/office/quality/assurance-rendered.mjs +9 -2
- package/src/runtime/office/quality/assurance-structure-docx.mjs +4 -2
- package/src/runtime/office/quality/design-review.mjs +1 -5
- package/src/runtime/office/quality/document-brief.mjs +1 -5
- package/src/runtime/office/quality/forced-break-pages.mjs +9 -6
- package/src/runtime/office/quality/quality-pipeline.mjs +1 -1
- package/src/runtime/shared/agent-route-config.mjs +17 -2
- package/src/runtime/shared/atomic-file.mjs +103 -2
- package/src/runtime/shared/background-tasks.mjs +15 -6
- package/src/runtime/shared/bot-owned-work.mjs +56 -0
- package/src/runtime/shared/connector-accounts.mjs +5 -5
- package/src/runtime/shared/connector-catalog.d.mts +11 -4
- package/src/runtime/shared/connector-catalog.mjs +60 -52
- package/src/runtime/shared/custom-provider-keys.mjs +20 -0
- package/src/runtime/shared/defaults-separation.mjs +1 -4
- package/src/runtime/shared/fetch-safe-listen.d.mts +16 -0
- package/src/runtime/shared/fetch-safe-listen.mjs +50 -0
- package/src/runtime/shared/file-has-data.mjs +26 -2
- package/src/runtime/shared/file-lock.mjs +13 -15
- package/src/runtime/shared/git-launch.d.mts +9 -0
- package/src/runtime/shared/git-launch.mjs +213 -0
- package/src/runtime/shared/git-runner-worker.mjs +2 -1
- package/src/runtime/shared/handoff-artifacts.d.mts +2 -1
- package/src/runtime/shared/handoff-artifacts.mjs +18 -8
- package/src/runtime/shared/idle-auto-clear-gate.mjs +29 -7
- package/src/runtime/shared/llm/cost.mjs +11 -2
- package/src/runtime/shared/llm/http-agent.mjs +313 -29
- package/src/runtime/shared/llm/model-catalog-projection.mjs +3 -2
- package/src/runtime/shared/llm/model-catalog.mjs +46 -6
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +3 -0
- package/src/runtime/shared/llm/system-proxy.mjs +452 -0
- package/src/runtime/shared/loopback-listener.mjs +25 -2
- package/src/runtime/shared/model-route-chain.d.mts +7 -2
- package/src/runtime/shared/model-route-chain.mjs +22 -4
- package/src/runtime/shared/open-url.mjs +10 -0
- package/src/runtime/shared/provider-accounts.mjs +52 -2
- package/src/runtime/shared/session-activity-signal.mjs +14 -0
- package/src/runtime/shared/session-scratch.mjs +37 -0
- package/src/runtime/shared/staged-install-worker.mjs +5 -0
- package/src/runtime/shared/staged-update.mjs +47 -2
- package/src/runtime/shared/tool-card-model/agent-surface.mjs +1 -3
- package/src/runtime/shared/tool-card-model/card-status.mjs +15 -2
- package/src/runtime/shared/tool-result-summary.mjs +1 -1
- package/src/runtime/shared/tool-surface.mjs +113 -36
- package/src/runtime/shared/tool-work-units.mjs +6 -0
- package/src/runtime/shared/turn-snapshot-store.mjs +13 -6
- package/src/runtime/shared/turn-worktree-snapshot.mjs +414 -54
- package/src/runtime/shared/worktrees/activity-gate.mjs +215 -318
- package/src/runtime/shared/worktrees/activity-ledger-worker.mjs +56 -0
- package/src/runtime/shared/worktrees/activity-ledger.mjs +391 -0
- package/src/runtime/shared/worktrees/branch-management.mjs +9 -3
- package/src/runtime/shared/worktrees/contract.mjs +4 -1
- package/src/runtime/shared/worktrees/git.mjs +72 -0
- package/src/runtime/shared/worktrees/manager.mjs +285 -168
- package/src/runtime/shared/worktrees/test-support.mjs +6 -10
- package/src/runtime/tidy/install.mjs +95 -15
- package/src/runtime/tidy/languages.mjs +17 -15
- package/src/runtime/tidy/process.mjs +7 -4
- package/src/runtime/tidy/resolve.mjs +19 -16
- package/src/runtime/tidy/runners/biome.mjs +3 -3
- package/src/runtime/tidy/tool.mjs +1 -1
- package/src/runtime/tidy/worktree.mjs +10 -6
- package/src/runtime/visualize-bridge/client.mjs +6 -1
- package/src/runtime/visualize-bridge/tool-defs.mjs +7 -2
- package/src/runtime/web-search/index.mjs +1 -1
- package/src/session-runtime/agent-home-delivery.mjs +41 -0
- package/src/session-runtime/agent-task-sessions.mjs +458 -312
- package/src/session-runtime/agent-tool-routing.mjs +8 -41
- package/src/session-runtime/boot/tools.mjs +7 -1
- package/src/session-runtime/bot-status.mjs +107 -101
- package/src/session-runtime/bot-target.mjs +38 -0
- package/src/session-runtime/channel-config-api.mjs +6 -1
- package/src/session-runtime/connector-merge-migration.mjs +18 -15
- package/src/session-runtime/conversation-import/codex-titles.mjs +88 -0
- package/src/session-runtime/conversation-import/discovery.mjs +401 -36
- package/src/session-runtime/conversation-import/service.mjs +35 -8
- package/src/session-runtime/handoff-attachments.mjs +82 -31
- package/src/session-runtime/held-requests.mjs +3 -1
- package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +12 -13
- package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +1 -0
- package/src/session-runtime/internal-tool-executor/feature-tools.mjs +2 -0
- package/src/session-runtime/internal-tool-executor/knowledge-tools.mjs +8 -0
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +4 -1
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +145 -112
- package/src/session-runtime/lifecycle/cold-heir.mjs +11 -6
- package/src/session-runtime/lifecycle/session-catalog.mjs +9 -1
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +6 -1
- package/src/session-runtime/lifecycle/teardown.mjs +1 -1
- package/src/session-runtime/mcp-glue/server-catalog.mjs +16 -10
- package/src/session-runtime/mcp-glue/server-input.mjs +4 -1
- package/src/session-runtime/mixy-heartbeat.mjs +1 -1
- package/src/session-runtime/model-route/set-route.mjs +11 -2
- package/src/session-runtime/provider-auth/login.mjs +2 -2
- package/src/session-runtime/provider-catalog-cache.mjs +82 -36
- package/src/session-runtime/provider-models/catalog-load.mjs +23 -6
- package/src/session-runtime/provider-models.mjs +4 -2
- package/src/session-runtime/resource-mcp-api.mjs +98 -35
- package/src/session-runtime/resource-mcp-connector-accounts.mjs +44 -31
- package/src/session-runtime/resource-mcp-secrets.mjs +28 -11
- package/src/session-runtime/resource-mcp-servers.mjs +5 -4
- package/src/session-runtime/resource-recall-api.mjs +6 -1
- package/src/session-runtime/runtime-feature-gates.mjs +5 -1
- package/src/session-runtime/services/agent-tool/execute.mjs +14 -9
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +20 -4
- package/src/session-runtime/services/agent-tool/model-select.mjs +48 -7
- package/src/session-runtime/services/agent-tool/render.mjs +71 -17
- package/src/session-runtime/services/agent-tool/send-flow.mjs +10 -2
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-prep.mjs +8 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +4 -1
- package/src/session-runtime/services/agent-tool/spawn-preset.mjs +6 -2
- package/src/session-runtime/services/agent-tool/tool-def.mjs +9 -9
- package/src/session-runtime/services/agent-watchdog-registry.mjs +32 -4
- package/src/session-runtime/services/channel-worker/daemon-spawn.mjs +2 -0
- package/src/session-runtime/services/daemon-candidate.mjs +4 -1
- package/src/session-runtime/services/memory-runtime-proxy/daemon-spawn.mjs +4 -0
- package/src/session-runtime/services/plugin-admin.mjs +10 -6
- package/src/session-runtime/services/provider-admin.mjs +283 -11
- package/src/session-runtime/session-turn-api.mjs +2 -0
- package/src/session-runtime/settings-builtin-tools-api.mjs +4 -1
- package/src/session-runtime/settings-system-api.mjs +1 -1
- package/src/session-runtime/setup-tool/agent-settings-actions.mjs +13 -3
- package/src/session-runtime/setup-tool/connector-widen-approval.mjs +96 -0
- package/src/session-runtime/setup-tool/executor.mjs +6 -2
- package/src/session-runtime/setup-tool/tool-defs.mjs +2 -1
- package/src/session-runtime/tool-policy/policy-stage.mjs +1 -0
- package/src/session-runtime/turn/agent-ops.mjs +23 -0
- package/src/session-runtime/workflow-agents-api/agent-connectors.mjs +49 -11
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +5 -1
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +25 -5
- package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -3
- package/src/session-runtime/workspace/activity-guards.mjs +176 -0
- package/src/session-runtime/workspace/session-view.mjs +149 -0
- package/src/session-runtime/workspace/side-checkouts.mjs +203 -0
- package/src/session-runtime/workspace/transition-runner.mjs +188 -0
- package/src/session-runtime/workspace/transitions.mjs +108 -1041
- package/src/session-runtime/workspace/workspace-merge.mjs +132 -0
- package/src/session-runtime/workspace/worktree-intents.mjs +242 -0
- package/src/session-runtime/workspace/worktree-maintenance.mjs +80 -0
- package/src/session-runtime/workspace/worktree-setup.mjs +85 -0
- package/src/session-runtime/workspace/worktree-tool.mjs +73 -56
- package/src/standalone/daemon-desktop-runtime.mjs +2 -0
- package/src/standalone/daemon-session-control.mjs +169 -138
- package/src/standalone/daemon.mjs +7 -0
- package/src/standalone/desktop-service-registry.mjs +9 -0
- package/src/standalone/local-session-runtime.mjs +5 -1
- package/src/standalone/session-client/daemon-unavailable.mjs +3 -0
- package/src/standalone/session-client.mjs +5 -1
- package/src/standalone/session-frame-stream.mjs +83 -11
- package/src/standalone/session-protocol.mjs +4 -0
- package/src/standalone/session-service/agent-tree/agent-turns.mjs +16 -12
- package/src/standalone/session-service/agent-tree.mjs +45 -9
- package/src/standalone/session-service/projection/transcript-window.mjs +700 -64
- package/src/standalone/session-service/session-calls/session-action.mjs +10 -3
- package/src/standalone/session-service/session-calls/session-views.mjs +160 -104
- package/src/standalone/session-service/stored-reader.mjs +127 -40
- package/src/standalone/session-transport/client-registry/client-grace.mjs +12 -9
- package/src/tui/App.jsx +154 -164
- package/src/tui/app/app-view/floating-panel.jsx +10 -4
- package/src/tui/app/app-view/text-entry-labels.mjs +1 -0
- package/src/tui/app/clipboard.mjs +21 -10
- package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +1 -3
- package/src/tui/app/model-picker/route-selection.mjs +5 -6
- package/src/tui/app/prompt-handlers/use-prompt-history-nav.mjs +1 -1
- package/src/tui/app/prompt-handlers/use-prompt-interrupt.mjs +3 -0
- package/src/tui/app/prompt-submit/provider-prompts.mjs +3 -1
- package/src/tui/app/provider-setup/api-key-actions.mjs +31 -1
- package/src/tui/app/provider-setup/oauth-actions.mjs +58 -21
- package/src/tui/app/provider-setup/provider-items.mjs +8 -2
- package/src/tui/app/provider-setup-picker.mjs +29 -18
- package/src/tui/app/shell-layout/row-budgets.mjs +12 -10
- package/src/tui/app/slash-commands.mjs +1 -0
- package/src/tui/app/slash-dispatch/session-commands.mjs +46 -0
- package/src/tui/app/slash-dispatch.mjs +1 -1
- package/src/tui/app/use-btw-panel.mjs +29 -0
- package/src/tui/app/use-context-panel-refresh.mjs +31 -0
- package/src/tui/app/use-model-catalog-cache.mjs +13 -10
- package/src/tui/app/use-mouse-input.mjs +11 -0
- package/src/tui/app/use-onboarding-start.mjs +8 -3
- package/src/tui/app/use-panel-transition.mjs +10 -1
- package/src/tui/app/use-pasted-buffers.mjs +28 -20
- package/src/tui/app/use-prompt-draft-flow.mjs +7 -0
- package/src/tui/app/use-prompt-layout-rows.mjs +3 -3
- package/src/tui/app/use-prompt-queue-history.mjs +3 -2
- package/src/tui/app/use-selection-focus.mjs +11 -2
- package/src/tui/app/use-selection-geometry.mjs +18 -9
- package/src/tui/app/use-selection-paint.mjs +4 -4
- package/src/tui/app/use-selection-stitch.mjs +3 -3
- package/src/tui/app/use-slash-palette.mjs +62 -0
- package/src/tui/app/use-terminal-chrome.mjs +2 -2
- package/src/tui/app/use-transcript-activity.mjs +47 -32
- package/src/tui/app/use-transcript-follow.mjs +12 -4
- package/src/tui/app/use-transcript-scroll.mjs +46 -17
- package/src/tui/app/use-transcript-swap-reset.mjs +27 -0
- package/src/tui/app/use-transcript-window/geometry.mjs +19 -5
- package/src/tui/app/use-transcript-window/instance-state.mjs +4 -0
- package/src/tui/app/use-transcript-window/selection-shift.mjs +5 -1
- package/src/tui/app/use-transcript-window.mjs +21 -11
- package/src/tui/app/use-tui-ready.mjs +18 -0
- package/src/tui/app/use-welcome-prompt-hint.mjs +5 -0
- package/src/tui/app/use-workflow-tab-cycle.mjs +5 -3
- package/src/tui/components/Picker.jsx +27 -3
- package/src/tui/components/QuestionPanel.jsx +13 -4
- package/src/tui/components/SignInUrl.jsx +68 -0
- package/src/tui/components/TextEntryPanel.jsx +76 -46
- package/src/tui/components/sign-in-url-layout.mjs +24 -0
- package/src/tui/dist/index.mjs +1963 -1361
- package/src/tui/session/goal-turn-state.mjs +6 -2
- package/src/tui/session/session-api/controls.mjs +4 -0
- package/src/tui/session/session-api/extensions.mjs +8 -0
- package/src/tui/session/session-api/intake/abort.mjs +2 -1
- package/src/tui/session/session-api/intake.mjs +2 -0
- package/src/tui/session/session-api/integrations.mjs +2 -2
- package/src/tui/session/session-api/routes-agent-definitions.mjs +1 -0
- package/src/tui/session/session-api/settings.mjs +2 -2
- package/src/tui/session/session-flow/queue/take-entries.mjs +11 -0
- package/src/tui/session/transcript-spill/spill-writer.mjs +15 -0
- package/src/tui/session/transcript-spill.mjs +92 -4
- package/src/tui/session/transcript-store.mjs +2 -0
- package/src/ui/statusline-agents.mjs +1 -3
- package/src/defaults/skills/skill-creator/references/source-review.md +0 -94
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Codex CLI rollout (`rollout-*.jsonl`) → raw import turns. Kept: the first
|
|
3
3
|
* `session_meta` (foreign id, cwd), user/assistant `message` items as text and
|
|
4
|
-
* tool calls as
|
|
4
|
+
* tool calls as tool notes. Dropped: developer/system
|
|
5
5
|
* messages, Codex's own wrapper user messages, tool outputs, reasoning,
|
|
6
6
|
* event_msg, token counts and turn_context.
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
IMAGE_OMITTED_TEXT,
|
|
10
|
+
IMPORT_WARNING_IMAGE_OMITTED,
|
|
11
|
+
isWholeElement,
|
|
12
|
+
stringOrNull,
|
|
13
|
+
textPart,
|
|
14
|
+
toolNote,
|
|
15
|
+
} from './turns.mjs';
|
|
9
16
|
|
|
10
17
|
// User-role envelopes Codex injects itself (environment, instructions, abort
|
|
11
18
|
// notices, plugin hints, shell-command echoes, image wrappers).
|
|
@@ -17,6 +24,7 @@ const CODEX_ENVELOPE_TAGS = [
|
|
|
17
24
|
'user_shell_command',
|
|
18
25
|
'subagent_notification',
|
|
19
26
|
'skills_instructions',
|
|
27
|
+
'external_codex_apps_open_page',
|
|
20
28
|
];
|
|
21
29
|
const TOOL_CALL_TYPES = new Set(['function_call', 'custom_tool_call', 'local_shell_call']);
|
|
22
30
|
|
|
@@ -29,6 +37,17 @@ export function isCodexEnvelopeText(text) {
|
|
|
29
37
|
return /^<image\b[^>]*>$/.test(trimmed) || trimmed === '</image>';
|
|
30
38
|
}
|
|
31
39
|
|
|
40
|
+
// Codex shows a user message after the last of these headings: what precedes it
|
|
41
|
+
// is context the app adds for the model (IDE state, mentioned files, response
|
|
42
|
+
// annotations, an earlier request it already carries).
|
|
43
|
+
const USER_REQUEST_HEADING = '## My request for Codex:';
|
|
44
|
+
|
|
45
|
+
/** A user text part as Codex displays it. */
|
|
46
|
+
function codexUserDisplayText(text) {
|
|
47
|
+
const at = text.lastIndexOf(USER_REQUEST_HEADING);
|
|
48
|
+
return at < 0 ? text : text.slice(at + USER_REQUEST_HEADING.length).trim();
|
|
49
|
+
}
|
|
50
|
+
|
|
32
51
|
function messageParts(payload, warnings) {
|
|
33
52
|
const content = typeof payload.content === 'string' ? [{ type: 'text', text: payload.content }] : payload.content;
|
|
34
53
|
if (!Array.isArray(content)) return [];
|
|
@@ -41,8 +60,8 @@ function messageParts(payload, warnings) {
|
|
|
41
60
|
continue;
|
|
42
61
|
}
|
|
43
62
|
if (typeof item.text !== 'string') continue;
|
|
44
|
-
if (payload.role
|
|
45
|
-
parts.push(textPart(item.text));
|
|
63
|
+
if (payload.role !== 'user') parts.push(textPart(item.text));
|
|
64
|
+
else if (!isCodexEnvelopeText(item.text)) parts.push(textPart(codexUserDisplayText(item.text)));
|
|
46
65
|
}
|
|
47
66
|
return parts;
|
|
48
67
|
}
|
|
@@ -52,7 +71,30 @@ function toolName(payload) {
|
|
|
52
71
|
return payload.type === 'local_shell_call' ? 'local_shell' : '';
|
|
53
72
|
}
|
|
54
73
|
|
|
55
|
-
|
|
74
|
+
// `session_meta.thread_source` values Codex gives threads it runs for itself.
|
|
75
|
+
const INTERNAL_THREAD_SOURCES = {
|
|
76
|
+
subagent: 'subagent',
|
|
77
|
+
guardian_review: 'guardianReview',
|
|
78
|
+
memory_consolidation: 'internal',
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* What kind of Codex-internal record a `session_meta` payload marks, else null
|
|
83
|
+
* for a conversation the user had. Markers are Codex's own: `thread_source`
|
|
84
|
+
* (`subagent`, `guardian_review`, `memory_consolidation`) and a `source` of the
|
|
85
|
+
* form `{ subagent: … }` (spawned agent, review, compact; `{ other: "guardian" }`
|
|
86
|
+
* is the approval reviewer) or `{ internal: … }`. Other sources (cli, vscode,
|
|
87
|
+
* exec, mcp, custom) and features (automation, voice chat) are the user's.
|
|
88
|
+
*/
|
|
89
|
+
function codexInternalKind(payload) {
|
|
90
|
+
const byThread = INTERNAL_THREAD_SOURCES[payload?.thread_source];
|
|
91
|
+
if (byThread) return byThread;
|
|
92
|
+
const source = payload?.source;
|
|
93
|
+
if (!source || typeof source !== 'object') return null;
|
|
94
|
+
if ('subagent' in source) return source.subagent?.other === 'guardian' ? 'guardianReview' : 'subagent';
|
|
95
|
+
if ('internal' in source) return source.internal === 'guardian' ? 'guardianReview' : 'internal';
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
56
98
|
// Rough fixed cost of one retained turn object, so tiny turns still count.
|
|
57
99
|
const ENTRY_OVERHEAD_BYTES = 64;
|
|
58
100
|
|
|
@@ -67,6 +109,8 @@ export function createCodexReducer() {
|
|
|
67
109
|
let recognized = false;
|
|
68
110
|
let foreignSessionId = null;
|
|
69
111
|
let cwd = null;
|
|
112
|
+
let internalKind = null;
|
|
113
|
+
let historyBase = null;
|
|
70
114
|
let metaSeen = false;
|
|
71
115
|
let chars = 0;
|
|
72
116
|
let metadataBytes = 0;
|
|
@@ -86,15 +130,19 @@ export function createCodexReducer() {
|
|
|
86
130
|
get metadataBytes() {
|
|
87
131
|
return metadataBytes;
|
|
88
132
|
},
|
|
89
|
-
|
|
133
|
+
/** `inherited` records come from a history base: its session metadata is not this thread's. */
|
|
134
|
+
push(record, inherited = false) {
|
|
90
135
|
const payload = record?.payload && typeof record.payload === 'object' ? record.payload : null;
|
|
91
136
|
if (!payload) return;
|
|
92
137
|
if (record.type === 'session_meta') {
|
|
138
|
+
if (inherited) return;
|
|
93
139
|
recognized = true;
|
|
94
140
|
if (!metaSeen) {
|
|
95
141
|
metaSeen = true;
|
|
96
142
|
foreignSessionId = stringOrNull(payload.id) || stringOrNull(payload.session_id);
|
|
97
143
|
cwd = stringOrNull(payload.cwd);
|
|
144
|
+
internalKind = codexInternalKind(payload);
|
|
145
|
+
if (payload.history_base && typeof payload.history_base === 'object') historyBase = payload.history_base;
|
|
98
146
|
}
|
|
99
147
|
return;
|
|
100
148
|
}
|
|
@@ -108,23 +156,95 @@ export function createCodexReducer() {
|
|
|
108
156
|
}
|
|
109
157
|
},
|
|
110
158
|
result() {
|
|
111
|
-
return { recognized, foreignSessionId, cwd, rawTurns, warnings };
|
|
159
|
+
return { recognized, foreignSessionId, cwd, internalKind, historyBase, rawTurns, warnings };
|
|
112
160
|
},
|
|
113
161
|
};
|
|
114
162
|
}
|
|
115
163
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
164
|
+
// ── bounded-prefix `session_meta` scan ───────────────────────────────────────
|
|
165
|
+
// Index after the string starting at `i`, or -1 when the text ends inside it.
|
|
166
|
+
function scanString(text, i) {
|
|
167
|
+
for (let j = i + 1; j < text.length; j++) {
|
|
168
|
+
if (text[j] === '\\') j++;
|
|
169
|
+
else if (text[j] === '"') return j + 1;
|
|
170
|
+
}
|
|
171
|
+
return -1;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Index after the JSON value starting at `i`, or -1 when the text ends inside it.
|
|
175
|
+
function scanValue(text, i) {
|
|
176
|
+
if (text[i] === '"') return scanString(text, i);
|
|
177
|
+
if (text[i] === '{' || text[i] === '[') {
|
|
178
|
+
let depth = 0;
|
|
179
|
+
for (let j = i; j < text.length; j++) {
|
|
180
|
+
if (text[j] === '"') {
|
|
181
|
+
j = scanString(text, j) - 1;
|
|
182
|
+
if (j < 0) return -1;
|
|
183
|
+
} else if (text[j] === '{' || text[j] === '[') depth++;
|
|
184
|
+
else if ((text[j] === '}' || text[j] === ']') && --depth === 0) return j + 1;
|
|
185
|
+
}
|
|
186
|
+
return -1;
|
|
187
|
+
}
|
|
188
|
+
const literal = /[^,}\]\s]+/y;
|
|
189
|
+
literal.lastIndex = i;
|
|
190
|
+
literal.exec(text);
|
|
191
|
+
return literal.lastIndex < text.length ? literal.lastIndex : -1;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Complete top-level values (raw JSON text) of the record object and of its
|
|
196
|
+
* `payload` object in a possibly cut-off line. Nested values are never
|
|
197
|
+
* inspected, so a key inside custom metadata is not mistaken for a payload field.
|
|
198
|
+
*/
|
|
199
|
+
function recordFields(text) {
|
|
200
|
+
const top = {};
|
|
201
|
+
const payload = {};
|
|
202
|
+
const walk = (start, target, descend) => {
|
|
203
|
+
let j = start + 1;
|
|
204
|
+
for (;;) {
|
|
205
|
+
while (/[\s,]/.test(text[j] ?? '')) j++;
|
|
206
|
+
if (text[j] !== '"') return;
|
|
207
|
+
const keyEnd = scanString(text, j);
|
|
208
|
+
if (keyEnd < 0) return;
|
|
209
|
+
const key = JSON.parse(text.slice(j, keyEnd));
|
|
210
|
+
j = keyEnd;
|
|
211
|
+
while (/\s/.test(text[j] ?? '')) j++;
|
|
212
|
+
if (text[j] !== ':') return;
|
|
213
|
+
j++;
|
|
214
|
+
while (/\s/.test(text[j] ?? '')) j++;
|
|
215
|
+
if (descend && key === 'payload' && text[j] === '{') return walk(j, payload, false);
|
|
216
|
+
const end = scanValue(text, j);
|
|
217
|
+
if (end < 0) return;
|
|
218
|
+
target[key] = text.slice(j, end);
|
|
219
|
+
j = end;
|
|
127
220
|
}
|
|
128
221
|
};
|
|
129
|
-
|
|
222
|
+
const open = text.indexOf('{');
|
|
223
|
+
if (open >= 0) walk(open, top, true);
|
|
224
|
+
return { top, payload };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const jsonOrNull = (raw) => {
|
|
228
|
+
try {
|
|
229
|
+
return raw === undefined ? null : JSON.parse(raw);
|
|
230
|
+
} catch {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* id/cwd/internal kind of a `session_meta` first line cut off by a bounded
|
|
237
|
+
* prefix read, from the payload fields that arrived whole. A marker that did
|
|
238
|
+
* not arrive whole leaves the record unclassified (`internalKind: null`).
|
|
239
|
+
*/
|
|
240
|
+
export function codexMetaFromTruncatedLine(line) {
|
|
241
|
+
const { top, payload } = recordFields(String(line || ''));
|
|
242
|
+
if (jsonOrNull(top.type) !== 'session_meta') return null;
|
|
243
|
+
const field = (name) => stringOrNull(jsonOrNull(payload[name]));
|
|
244
|
+
const meta = { thread_source: field('thread_source'), source: jsonOrNull(payload.source) };
|
|
245
|
+
return {
|
|
246
|
+
foreignSessionId: field('id') || field('session_id'),
|
|
247
|
+
cwd: field('cwd'),
|
|
248
|
+
internalKind: codexInternalKind(meta),
|
|
249
|
+
};
|
|
130
250
|
}
|
|
@@ -6,7 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { createClaudeReducer } from './claude.mjs';
|
|
8
8
|
import { createCodexReducer } from './codex.mjs';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
IMPORT_ERROR_INTERNAL,
|
|
11
|
+
IMPORT_WARNING_HISTORY_PARTIAL,
|
|
12
|
+
IMPORT_WARNING_MALFORMED,
|
|
13
|
+
conversationTitle,
|
|
14
|
+
normalizeTurns,
|
|
15
|
+
} from './turns.mjs';
|
|
10
16
|
|
|
11
17
|
export const IMPORT_SOURCES = Object.freeze(['codex', 'claude']);
|
|
12
18
|
/** A line or converted transcript beyond the import limits fails the file. */
|
|
@@ -35,7 +41,9 @@ const transcriptChars = (turns) => turns.reduce((total, turn) => total + turn.te
|
|
|
35
41
|
* (an over-long line or file). `result()` may be called repeatedly and also
|
|
36
42
|
* holds the normalized turns to `maxTranscriptChars`.
|
|
37
43
|
* `errorCode` is null for an importable result, else one of `empty` |
|
|
38
|
-
* `malformed` | `unsupported` | `
|
|
44
|
+
* `malformed` | `unsupported` | `internalRecord` (the source app's own
|
|
45
|
+
* subagent/review record; `internalKind` names it) | `tooLarge` (whose turns
|
|
46
|
+
* are not returned).
|
|
39
47
|
*/
|
|
40
48
|
export function createConversationConverter(
|
|
41
49
|
source,
|
|
@@ -47,18 +55,37 @@ export function createConversationConverter(
|
|
|
47
55
|
) {
|
|
48
56
|
if (!isImportSource(source)) throw new TypeError('source must be codex or claude.');
|
|
49
57
|
const reducer = source === 'codex' ? createCodexReducer() : createClaudeReducer();
|
|
50
|
-
let lines = 0;
|
|
51
58
|
let records = 0;
|
|
52
59
|
let malformed = 0;
|
|
53
60
|
let tooLarge = false;
|
|
61
|
+
let historyPartial = null;
|
|
54
62
|
return {
|
|
63
|
+
/** True while every message seen so far is a Claude sidechain message. */
|
|
64
|
+
get sidechainOnly() {
|
|
65
|
+
return reducer.sidechainOnly === true;
|
|
66
|
+
},
|
|
55
67
|
markTooLarge() {
|
|
56
68
|
tooLarge = true;
|
|
57
69
|
},
|
|
58
|
-
|
|
70
|
+
/** A history base could not be followed in full; `warning` names why. */
|
|
71
|
+
markHistoryPartial(warning = IMPORT_WARNING_HISTORY_PARTIAL) {
|
|
72
|
+
historyPartial = warning;
|
|
73
|
+
},
|
|
74
|
+
/** Feed a line for the stored title only (Claude Code's tail window); other sources ignore it. */
|
|
75
|
+
pushTitleLine(raw) {
|
|
76
|
+
let value;
|
|
77
|
+
try {
|
|
78
|
+
value = JSON.parse(String(raw).trim());
|
|
79
|
+
} catch {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (value && typeof value === 'object') reducer.pushTitle?.(value);
|
|
83
|
+
},
|
|
84
|
+
/** `inherited` lines belong to a history base followed ahead of this file's own lines. */
|
|
85
|
+
pushLine(raw, { inherited = false } = {}) {
|
|
59
86
|
if (tooLarge) return false;
|
|
60
87
|
let line = String(raw);
|
|
61
|
-
if (
|
|
88
|
+
if (line.charCodeAt(0) === 0xfeff) line = line.slice(1);
|
|
62
89
|
if (line.endsWith('\r')) line = line.slice(0, -1);
|
|
63
90
|
if (!line.trim()) return true;
|
|
64
91
|
let value;
|
|
@@ -73,7 +100,7 @@ export function createConversationConverter(
|
|
|
73
100
|
return true;
|
|
74
101
|
}
|
|
75
102
|
records += 1;
|
|
76
|
-
reducer.push(value);
|
|
103
|
+
reducer.push(value, inherited);
|
|
77
104
|
if (
|
|
78
105
|
reducer.chars > maxTranscriptChars ||
|
|
79
106
|
reducer.entries > maxRetainedEntries ||
|
|
@@ -90,8 +117,10 @@ export function createConversationConverter(
|
|
|
90
117
|
if (transcriptChars(turns) > maxTranscriptChars) tooLarge = true;
|
|
91
118
|
const warnings = new Set(parsed.warnings);
|
|
92
119
|
if (malformed) warnings.add(IMPORT_WARNING_MALFORMED);
|
|
120
|
+
if (historyPartial) warnings.add(historyPartial);
|
|
93
121
|
let errorCode = null;
|
|
94
122
|
if (tooLarge) errorCode = IMPORT_ERROR_TOO_LARGE;
|
|
123
|
+
else if (parsed.internalKind) errorCode = IMPORT_ERROR_INTERNAL;
|
|
95
124
|
else if (!records) errorCode = malformed ? 'malformed' : 'empty';
|
|
96
125
|
else if (!parsed.recognized) errorCode = 'unsupported';
|
|
97
126
|
else if (!turns.length) errorCode = 'empty';
|
|
@@ -100,8 +129,10 @@ export function createConversationConverter(
|
|
|
100
129
|
errorCode,
|
|
101
130
|
foreignSessionId: parsed.foreignSessionId,
|
|
102
131
|
cwd: parsed.cwd,
|
|
132
|
+
internalKind: parsed.internalKind,
|
|
133
|
+
historyBase: parsed.historyBase ?? null,
|
|
103
134
|
turns: tooLarge ? [] : turns,
|
|
104
|
-
title: conversationTitle(turns),
|
|
135
|
+
title: parsed.storedTitle || conversationTitle(turns),
|
|
105
136
|
messageCount: tooLarge ? 0 : turns.length,
|
|
106
137
|
warnings: [...warnings],
|
|
107
138
|
};
|
|
@@ -70,6 +70,9 @@ export function importedTranscriptMessages(turns, importedAt) {
|
|
|
70
70
|
content: turn.text,
|
|
71
71
|
meta: {
|
|
72
72
|
source: IMPORTED_MESSAGE_SOURCE,
|
|
73
|
+
// Where the text holds a run of tool use, and which tools: the desktop
|
|
74
|
+
// draws each run as a native activity row.
|
|
75
|
+
...(turn.toolRuns?.length ? { importedToolRuns: turn.toolRuns } : {}),
|
|
73
76
|
transcript: { messageId: newTranscriptMessageId(), at: turn.at || importedAt },
|
|
74
77
|
},
|
|
75
78
|
}));
|
|
@@ -9,6 +9,18 @@
|
|
|
9
9
|
export const IMPORT_WARNING_IMAGE_OMITTED = 'imageOmitted';
|
|
10
10
|
export const IMPORT_WARNING_MALFORMED = 'malformed';
|
|
11
11
|
export const IMPORT_WARNING_CWD_MISSING = 'cwdMissing';
|
|
12
|
+
/** The conversation continues a history stored in another file that was not followed. */
|
|
13
|
+
export const IMPORT_WARNING_HISTORY_PARTIAL = 'historyPartial';
|
|
14
|
+
/** Earlier history was left out because following it would pass the import size limit. */
|
|
15
|
+
export const IMPORT_WARNING_HISTORY_SIZE_LIMIT = 'historySizeLimit';
|
|
16
|
+
/** Earlier history was left out because its file is missing or could not be read. */
|
|
17
|
+
export const IMPORT_WARNING_HISTORY_UNAVAILABLE = 'historyUnavailable';
|
|
18
|
+
|
|
19
|
+
/** A compressed rollout needs a Node.js runtime with zstd; used as the failure code and as the warning of an unreadable base. */
|
|
20
|
+
export const IMPORT_ERROR_NEEDS_NEWER_NODE = 'needsNewerNode';
|
|
21
|
+
|
|
22
|
+
/** Failure code of a record the source app writes for its own use (not a conversation). */
|
|
23
|
+
export const IMPORT_ERROR_INTERNAL = 'internalRecord';
|
|
12
24
|
|
|
13
25
|
/** Stands in for an image the importer does not carry over. */
|
|
14
26
|
export const IMAGE_OMITTED_TEXT = '[image omitted]';
|
|
@@ -17,14 +29,54 @@ export const IMPORTED_USER_STUB_TEXT = '[Imported conversation continues from an
|
|
|
17
29
|
|
|
18
30
|
const TITLE_MAX_CHARS = 100;
|
|
19
31
|
|
|
20
|
-
/**
|
|
32
|
+
/** Note for a tool call: its name only, never its arguments. A run of notes
|
|
33
|
+
* becomes one compact line in the text and one structured entry in `toolRuns`. */
|
|
21
34
|
export function toolNote(name) {
|
|
22
|
-
const clean =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
35
|
+
const clean =
|
|
36
|
+
String(name || '')
|
|
37
|
+
.replace(/\s+/g, ' ')
|
|
38
|
+
.trim() || 'unknown';
|
|
39
|
+
return { text: `[ran tool: ${clean}]`, note: true, tool: clean };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Longest model-facing run line, and the longest tool name shown in it. */
|
|
43
|
+
const TOOL_RUN_LINE_MAX_CHARS = 400;
|
|
44
|
+
const TOOL_RUN_NAME_MAX_CHARS = 40;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Model-facing line for one run of tool notes: `[ran tools: shell ×6, Read ×2]`.
|
|
48
|
+
* Bounded: names are clipped, and tools that do not fit are counted as
|
|
49
|
+
* `, +N more`. Deterministic in `tools`, so a stored line can be re-derived.
|
|
50
|
+
*/
|
|
51
|
+
export function toolRunLine(tools) {
|
|
52
|
+
const entries = tools.map(({ name, count }) => {
|
|
53
|
+
const chars = Array.from(String(name));
|
|
54
|
+
const shown =
|
|
55
|
+
chars.length > TOOL_RUN_NAME_MAX_CHARS ? `${chars.slice(0, TOOL_RUN_NAME_MAX_CHARS - 1).join('')}…` : name;
|
|
56
|
+
return `${shown} ×${count}`;
|
|
57
|
+
});
|
|
58
|
+
const omittedSuffix = (omitted) => (omitted > 0 ? `, +${omitted} more` : '');
|
|
59
|
+
let body = '';
|
|
60
|
+
let shownCount = 0;
|
|
61
|
+
for (const entry of entries) {
|
|
62
|
+
const next = shownCount ? `${body}, ${entry}` : entry;
|
|
63
|
+
const length = `[ran tools: ${next}${omittedSuffix(entries.length - shownCount - 1)}]`.length;
|
|
64
|
+
if (shownCount && length > TOOL_RUN_LINE_MAX_CHARS) break;
|
|
65
|
+
body = next;
|
|
66
|
+
shownCount += 1;
|
|
67
|
+
}
|
|
68
|
+
return `[ran tools: ${body}${omittedSuffix(entries.length - shownCount)}]`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function toolRunCounts(notes) {
|
|
72
|
+
const counts = new Map();
|
|
73
|
+
for (const note of notes) counts.set(note.tool, (counts.get(note.tool) || 0) + 1);
|
|
74
|
+
return [...counts].map(([name, count]) => ({ name, count }));
|
|
26
75
|
}
|
|
27
76
|
|
|
77
|
+
/** A trimmed non-blank string, else null. */
|
|
78
|
+
export const stringOrNull = (value) => (typeof value === 'string' && value.trim() ? value.trim() : null);
|
|
79
|
+
|
|
28
80
|
export function textPart(text) {
|
|
29
81
|
return { text: String(text), note: false };
|
|
30
82
|
}
|
|
@@ -42,18 +94,31 @@ export function timestampMs(value) {
|
|
|
42
94
|
return Number.isFinite(ms) && ms > 0 ? ms : null;
|
|
43
95
|
}
|
|
44
96
|
|
|
45
|
-
//
|
|
97
|
+
// Each run of consecutive tool notes collapses into one compact line; every
|
|
98
|
+
// boundary is a blank line. `toolRuns` locates those lines in `text`.
|
|
46
99
|
function joinParts(parts) {
|
|
47
|
-
|
|
48
|
-
let previous = null;
|
|
100
|
+
const blocks = [];
|
|
49
101
|
for (const part of parts) {
|
|
50
102
|
const piece = String(part.text || '').trim();
|
|
51
103
|
if (!piece) continue;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
104
|
+
const last = blocks[blocks.length - 1];
|
|
105
|
+
if (part.note && last?.notes) last.notes.push(part);
|
|
106
|
+
else blocks.push(part.note ? { notes: [part] } : { text: piece });
|
|
107
|
+
}
|
|
108
|
+
let text = '';
|
|
109
|
+
const toolRuns = [];
|
|
110
|
+
for (const block of blocks) {
|
|
111
|
+
if (text) text += '\n\n';
|
|
112
|
+
if (block.notes) {
|
|
113
|
+
const tools = toolRunCounts(block.notes);
|
|
114
|
+
const line = toolRunLine(tools);
|
|
115
|
+
toolRuns.push({ start: text.length, end: text.length + line.length, tools });
|
|
116
|
+
text += line;
|
|
117
|
+
} else {
|
|
118
|
+
text += block.text;
|
|
119
|
+
}
|
|
55
120
|
}
|
|
56
|
-
return { text,
|
|
121
|
+
return { text, toolRuns };
|
|
57
122
|
}
|
|
58
123
|
|
|
59
124
|
/**
|
|
@@ -72,9 +137,15 @@ export function normalizeTurns(rawTurns) {
|
|
|
72
137
|
else merged.push({ role: raw.role, parts: [...parts], at: timestampMs(raw.at) });
|
|
73
138
|
}
|
|
74
139
|
const turns = merged.map(({ role, parts, at }) => {
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
if (
|
|
140
|
+
const joined = joinParts(parts);
|
|
141
|
+
const turn = { role, text: joined.text, at };
|
|
142
|
+
if (joined.toolRuns.length) turn.toolRuns = joined.toolRuns;
|
|
143
|
+
// A carried-over compaction summary never names the conversation; a slash
|
|
144
|
+
// command only when no typed prompt does.
|
|
145
|
+
if (parts.some((part) => part.summary || part.command)) {
|
|
146
|
+
turn.titleText = joinParts(parts.filter((part) => !part.summary && !part.command)).text;
|
|
147
|
+
}
|
|
148
|
+
if (parts.some((part) => part.command)) turn.commandText = joinParts(parts.filter((part) => part.command)).text;
|
|
78
149
|
return turn;
|
|
79
150
|
});
|
|
80
151
|
if (turns[0]?.role === 'assistant') {
|
|
@@ -83,19 +154,26 @@ export function normalizeTurns(rawTurns) {
|
|
|
83
154
|
return turns;
|
|
84
155
|
}
|
|
85
156
|
|
|
86
|
-
const
|
|
87
|
-
(
|
|
157
|
+
const textLines = (text) =>
|
|
158
|
+
String(text ?? '')
|
|
88
159
|
.split('\n')
|
|
89
160
|
.map((value) => value.replace(/\s+/g, ' ').trim())
|
|
90
161
|
.filter(Boolean);
|
|
91
162
|
|
|
163
|
+
const titleLines = (turn) => textLines(turn.titleText ?? turn.text);
|
|
164
|
+
|
|
165
|
+
/** First non-empty line of a title text, whitespace-normalized, ≤100 chars. */
|
|
166
|
+
export function titleFromText(text) {
|
|
167
|
+
const line = textLines(text)[0];
|
|
168
|
+
if (!line) return null;
|
|
169
|
+
return Array.from(line).slice(0, TITLE_MAX_CHARS).join('').trim() || null;
|
|
170
|
+
}
|
|
171
|
+
|
|
92
172
|
/** First line of the first genuine user turn, whitespace-normalized, ≤100 chars
|
|
93
|
-
* (an image marker only when the turn has no text line). */
|
|
173
|
+
* (an image marker only when the turn has no text line), else the first slash command. */
|
|
94
174
|
export function conversationTitle(turns) {
|
|
95
175
|
const first = turns.find((turn) => turn.role === 'user' && !turn.stub && titleLines(turn).length);
|
|
96
|
-
if (!first) return
|
|
176
|
+
if (!first) return titleFromText(turns.find((turn) => turn.role === 'user' && turn.commandText)?.commandText);
|
|
97
177
|
const lines = titleLines(first);
|
|
98
|
-
|
|
99
|
-
if (!line) return null;
|
|
100
|
-
return Array.from(line).slice(0, TITLE_MAX_CHARS).join('').trim() || null;
|
|
178
|
+
return titleFromText(lines.find((value) => value !== IMAGE_OMITTED_TEXT) || lines[0]);
|
|
101
179
|
}
|
|
@@ -39,9 +39,10 @@ export function createEagerDispatcher({
|
|
|
39
39
|
repeatFailLimit,
|
|
40
40
|
});
|
|
41
41
|
const barriers = createEagerBarriers({ cwd });
|
|
42
|
-
// A capped
|
|
43
|
-
// (loop/turn-limits.mjs).
|
|
44
|
-
const
|
|
42
|
+
// A turn capped by calls or time runs its calls in order, so none past its
|
|
43
|
+
// cap starts early (loop/turn-limits.mjs).
|
|
44
|
+
const limits = turnLimitsOf(opts);
|
|
45
|
+
const capped = limits !== null && (limits.maxToolCalls !== Infinity || limits.wrapUpAt !== Infinity);
|
|
45
46
|
const execute = (call, entry) =>
|
|
46
47
|
executeToolFn(call.name, call.arguments, cwd, sessionId, sessionRef, {
|
|
47
48
|
toolCallId: call.id,
|
|
@@ -7,12 +7,19 @@
|
|
|
7
7
|
// secret — the user types a value into a target field; the request names
|
|
8
8
|
// the target and the field label, never a value;
|
|
9
9
|
// takeover — the user does a step themselves and says "done";
|
|
10
|
-
// permission — the user picks one of the offered scopes
|
|
10
|
+
// permission — the user picks one of the offered scopes;
|
|
11
|
+
// connector — a bot asks for more authority on one connector tool of its
|
|
12
|
+
// own: the card names the tool, its current level and the one
|
|
13
|
+
// asked for, and the person picks the level (`scope`: one of
|
|
14
|
+
// `choices`) or denies. Answered once, never remembered.
|
|
11
15
|
// A response is one of HUMAN_RESPONSES plus a `remember` scope; a policy lists
|
|
12
16
|
// the scopes it allows and can leave out `always`. Nothing here ever carries a
|
|
13
17
|
// secret value: a decision that names one is stripped to its verdict.
|
|
14
18
|
|
|
15
|
-
const HUMAN_REQUEST_KINDS = Object.freeze(['approval', 'outbound', 'secret', 'takeover', 'permission']);
|
|
19
|
+
const HUMAN_REQUEST_KINDS = Object.freeze(['approval', 'outbound', 'secret', 'takeover', 'permission', 'connector']);
|
|
20
|
+
/** The levels a connector card may raise a tool to. */
|
|
21
|
+
export const CONNECTOR_WIDEN_LEVELS = Object.freeze(['needs_approval', 'auto']);
|
|
22
|
+
const CONNECTOR_LEVELS = ['disabled', ...CONNECTOR_WIDEN_LEVELS];
|
|
16
23
|
const HUMAN_RESPONSES = Object.freeze(['approve', 'deny', 'edit-and-approve', 'provide-secret', 'skip', 'done']);
|
|
17
24
|
const REMEMBER_SCOPES = Object.freeze(['once', 'agent', 'always']);
|
|
18
25
|
export const SECRET_REQUEST_TIMEOUT_MS = 120_000;
|
|
@@ -36,6 +43,7 @@ const RESPONSES_BY_KIND = Object.freeze({
|
|
|
36
43
|
secret: ['provide-secret', 'skip'],
|
|
37
44
|
takeover: ['done', 'deny'],
|
|
38
45
|
permission: ['approve', 'deny'],
|
|
46
|
+
connector: ['approve', 'deny'],
|
|
39
47
|
});
|
|
40
48
|
const GRANTING_RESPONSES = new Set(['approve', 'edit-and-approve', 'provide-secret', 'done']);
|
|
41
49
|
const TEXT_LIMIT = 200;
|
|
@@ -89,12 +97,15 @@ function rememberScopes(value) {
|
|
|
89
97
|
return ['once', ...new Set(listed.filter((scope) => scope !== 'once'))];
|
|
90
98
|
}
|
|
91
99
|
|
|
92
|
-
/** The kind-specific fields of a request, whitelisted
|
|
93
|
-
*
|
|
100
|
+
/** The kind-specific fields of a request, whitelisted, plus the connector
|
|
101
|
+
* `account` a tool call is bound to (any kind; the card names it). Spread
|
|
102
|
+
* onto the presented request; `args` is replaced for a secret so no value
|
|
103
|
+
* rides it. */
|
|
94
104
|
export function humanRequestFields(input = {}) {
|
|
105
|
+
const bound = text(input?.account) ? { account: text(input.account) } : {};
|
|
95
106
|
const kind = input?.kind;
|
|
96
|
-
if (!HUMAN_REQUEST_KINDS.includes(kind)) return
|
|
97
|
-
const fields = { remember: rememberScopes(input.remember) };
|
|
107
|
+
if (!HUMAN_REQUEST_KINDS.includes(kind)) return bound;
|
|
108
|
+
const fields = { ...bound, remember: rememberScopes(input.remember) };
|
|
98
109
|
// The agent the request acts for (its name on the card and the remembered grant).
|
|
99
110
|
if (text(input.agentId)) fields.agentId = text(input.agentId);
|
|
100
111
|
if (kind === 'outbound' && isRecord(input.outbound)) {
|
|
@@ -187,6 +198,20 @@ export function humanRequestFields(input = {}) {
|
|
|
187
198
|
})),
|
|
188
199
|
};
|
|
189
200
|
}
|
|
201
|
+
if (kind === 'connector') {
|
|
202
|
+
const connector = isRecord(input.connector) ? input.connector : {};
|
|
203
|
+
const level = (value) => (CONNECTOR_LEVELS.includes(value) ? value : '');
|
|
204
|
+
fields.connector = {
|
|
205
|
+
server: text(connector.server),
|
|
206
|
+
tool: text(connector.tool),
|
|
207
|
+
from: level(connector.from),
|
|
208
|
+
requested: level(connector.requested),
|
|
209
|
+
choices: (Array.isArray(connector.choices) ? connector.choices : []).filter((choice) =>
|
|
210
|
+
CONNECTOR_WIDEN_LEVELS.includes(choice)
|
|
211
|
+
),
|
|
212
|
+
};
|
|
213
|
+
fields.remember = ['once'];
|
|
214
|
+
}
|
|
190
215
|
return fields;
|
|
191
216
|
}
|
|
192
217
|
|
|
@@ -226,6 +251,11 @@ export function normalizeHumanResponse(request, approved, extra = {}) {
|
|
|
226
251
|
const ids = (request?.permission?.scopes || []).map((scope) => scope.id);
|
|
227
252
|
if (ids.includes(extra?.scope)) result.scope = extra.scope;
|
|
228
253
|
}
|
|
254
|
+
// The level the person picked; none of the offered ones picks nothing.
|
|
255
|
+
if (kind === 'connector' && polarity) {
|
|
256
|
+
const choices = Array.isArray(request?.connector?.choices) ? request.connector.choices : [];
|
|
257
|
+
if (choices.includes(extra?.scope)) result.scope = extra.scope;
|
|
258
|
+
}
|
|
229
259
|
return result;
|
|
230
260
|
}
|
|
231
261
|
|
|
@@ -16,6 +16,9 @@ import { CONTEXT_SHARE_RATIO, COMPACT_TARGET_MIN_TOKENS, COMPACT_SAFETY_PERCENT
|
|
|
16
16
|
import { HANDOFF_TIMEOUT_MAX_MS } from '../compact/constants.mjs';
|
|
17
17
|
import { envFlag, envPositiveInt } from '../../../../shared/env.mjs';
|
|
18
18
|
import { positiveInt } from '../../../../shared/numbers.mjs';
|
|
19
|
+
import { cacheWarmUseFor, lastCacheWarmUseAt } from '../../../../shared/idle-auto-clear-gate.mjs';
|
|
20
|
+
import { ACCOUNT_PROVIDERS } from '../../../../shared/provider-accounts.mjs';
|
|
21
|
+
import { plannedAccountId } from '../../providers/account-pool.mjs';
|
|
19
22
|
import { isAgentOwner } from '../../agent-owner.mjs';
|
|
20
23
|
import { isAgentModeSession } from '../agent-mode.mjs';
|
|
21
24
|
import { providerInputExcludesCache, providerNativePdf } from '../../providers/registry.mjs';
|
|
@@ -703,13 +706,40 @@ export function shouldCompactForRequestMedia(messages, provider = '') {
|
|
|
703
706
|
// Anthropic's 5m message-tail TTL (agent-runtime/cache-strategy.mjs gives it
|
|
704
707
|
// to agent sessions). A send this long after the previous one finds the tail
|
|
705
708
|
// cache expired and would rewrite the whole accumulated transcript; compacting
|
|
706
|
-
// first makes that cold write the compacted transcript instead.
|
|
709
|
+
// first makes that cold write the compacted transcript instead. The tail was
|
|
710
|
+
// last used by the session's own send or by a successful cache warm
|
|
711
|
+
// (cache-warm.mjs), which reads and refreshes it without moving
|
|
712
|
+
// lastProviderSendAt: a warmed tail has not expired — for a request on the
|
|
713
|
+
// warm's provider, model and account only, since the entry lives there.
|
|
707
714
|
const AGENT_MESSAGE_CACHE_TTL_MS = 5 * 60_000;
|
|
708
715
|
|
|
709
|
-
|
|
716
|
+
// The account the request would be served by: the roster's first pick for a
|
|
717
|
+
// provider with accounts (account-pool.mjs), '' for one without a roster.
|
|
718
|
+
function requestAccountId(provider, model, sessionRef, opts, messages) {
|
|
719
|
+
if (!ACCOUNT_PROVIDERS.includes(provider)) return '';
|
|
720
|
+
return plannedAccountId(provider, {
|
|
721
|
+
sessionId: opts?.sessionId || sessionRef?.id || null,
|
|
722
|
+
messages,
|
|
723
|
+
providerState: opts?.providerState,
|
|
724
|
+
model,
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/** Whether the agent session's 5m message tail expired before this request
|
|
729
|
+
* on `provider` / `model` (default: the session's route). */
|
|
730
|
+
export function shouldCompactForExpiredAgentCache(sessionRef, opts, { provider, model, messages = [] } = {}) {
|
|
710
731
|
if (!isAgentOwner(sessionRef) || opts?.cacheStrategy?.messages !== '5m') return false;
|
|
711
732
|
const lastSendAt = Number(sessionRef.lastProviderSendAt);
|
|
712
|
-
|
|
733
|
+
if (!(lastSendAt > 0)) return false;
|
|
734
|
+
const now = Date.now();
|
|
735
|
+
if (now - lastSendAt <= AGENT_MESSAGE_CACHE_TTL_MS) return false;
|
|
736
|
+
// No warm since the last send: the tail expired.
|
|
737
|
+
if (!(lastCacheWarmUseAt(sessionRef.id) > lastSendAt)) return true;
|
|
738
|
+
const route = { provider: provider || sessionRef.provider || '', model: model || sessionRef.model || '' };
|
|
739
|
+
const accountId = requestAccountId(route.provider, route.model, sessionRef, opts, messages);
|
|
740
|
+
if (accountId === null) return true;
|
|
741
|
+
const warmAt = cacheWarmUseFor(sessionRef.id, { ...route, accountId });
|
|
742
|
+
return now - Math.max(lastSendAt, warmAt) > AGENT_MESSAGE_CACHE_TTL_MS;
|
|
713
743
|
}
|
|
714
744
|
|
|
715
745
|
export function shouldCompactForSession(
|