mixdog 1.2.4 → 1.2.6
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 +1 -1
- package/scripts/lib/gate-scheduler.mjs +2 -2
- package/scripts/lib/run-node-tests.mjs +5 -14
- package/scripts/mobile-release.mjs +5 -4
- package/scripts/provider-pingpong-live.mjs +9 -9
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +2 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +11 -0
- package/src/defaults/skills/browser-use/SKILL.md +2 -1
- package/src/defaults/skills/computer-use/SKILL.md +3 -1
- package/src/defaults/skills/visualize/SKILL.md +3 -2
- package/src/lib/rules-builder.cjs +1 -1
- package/src/output-styles/common.md +22 -5
- package/src/output-styles/detailed.md +7 -5
- package/src/output-styles/minimal.md +7 -3
- package/src/output-styles/simple.md +2 -3
- package/src/rules/agent/AGENT.md +3 -1
- package/src/rules/lead/LEAD.md +10 -7
- package/src/rules/shared/10-tool-workflow.md +2 -1
- package/src/rules/shared/60-verification.md +4 -5
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -1
- package/src/runtime/agent/orchestrator/config.mjs +6 -0
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +1 -1
- package/src/runtime/agent/orchestrator/internal-agents.mjs +10 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +53 -60
- package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +2 -3
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +40 -19
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/catalog-deadline.mjs +163 -0
- package/src/runtime/agent/orchestrator/providers/catalog-failures.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +38 -14
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +100 -26
- package/src/runtime/agent/orchestrator/providers/lib/send-callbacks.mjs +24 -0
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +49 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +0 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +11 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +45 -16
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-connect.mjs +196 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +74 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-login.mjs +194 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-tokens.mjs +353 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +293 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +33 -100
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/registry.mjs +41 -27
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +2 -3
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +3 -8
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +74 -13
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +102 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +8 -2
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/lifecycle-scan.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +39 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +9 -19
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +10 -7
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +62 -22
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +81 -34
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/request-fork.mjs +47 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/side-question.mjs +5 -43
- package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +73 -6
- package/src/runtime/agent/orchestrator/session/store/load-session.mjs +40 -0
- package/src/runtime/agent/orchestrator/session/store/save-fault.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-header.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +255 -32
- package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +306 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +70 -21
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +46 -30
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +144 -45
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +32 -13
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +364 -38
- package/src/runtime/agent/orchestrator/session/store.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/task-wait-control.mjs +43 -12
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +23 -6
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -6
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +13 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/benign-exit.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +40 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +37 -34
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +0 -4
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +29 -27
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/find-files-tool.mjs +28 -11
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +12 -3
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +203 -101
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +90 -41
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-delivery.mjs +199 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +165 -39
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +25 -13
- package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +7 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +19 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-line-collector.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +25 -7
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-render.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +12 -5
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +61 -22
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +32 -8
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +193 -19
- package/src/runtime/agent/orchestrator/tools/builtin/shell-direct-exe.mjs +57 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +119 -32
- package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +26 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +13 -28
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +90 -11
- package/src/runtime/agent/orchestrator/tools/builtin/wait-budgets.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +54 -10
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +22 -28
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +11 -7
- package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +126 -9
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +15 -6
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +40 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promotion-results.mjs +13 -3
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +35 -4
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +39 -23
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/attachments/office-extract.mjs +11 -9
- package/src/runtime/memory/lib/embedding-tokenizer.mjs +32 -18
- package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -1
- package/src/runtime/memory/lib/tool-call-handler.mjs +7 -5
- package/src/runtime/office/authoring/pptx-script-normalize.mjs +11 -8
- package/src/runtime/office/core/tabular.mjs +1 -1
- package/src/runtime/office/design/library/design-template-inspect.mjs +7 -4
- package/src/runtime/office/portable/docx-formatting.mjs +1 -1
- package/src/runtime/office/portable/docx-runs.mjs +1 -1
- package/src/runtime/office/portable/docx-tracked-edits.mjs +2 -2
- package/src/runtime/office/portable/portable-docx-edits.mjs +11 -10
- package/src/runtime/office/portable/portable-docx-operations.mjs +21 -17
- package/src/runtime/office/portable/portable-docx-parts.mjs +15 -9
- package/src/runtime/office/portable/portable-docx-styles.mjs +4 -1
- package/src/runtime/office/portable/portable-docx-xml.mjs +9 -9
- package/src/runtime/office/portable/portable-opc.mjs +27 -13
- package/src/runtime/office/portable/portable-pivot.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-chart.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-charts.mjs +24 -18
- package/src/runtime/office/portable/portable-pptx-core.mjs +5 -5
- package/src/runtime/office/portable/portable-pptx-deck.mjs +8 -4
- package/src/runtime/office/portable/portable-pptx-package.mjs +7 -4
- package/src/runtime/office/portable/portable-pptx-shapes.mjs +18 -9
- package/src/runtime/office/portable/portable-sheet-parts.mjs +9 -3
- package/src/runtime/office/portable/portable-sheet-xml.mjs +5 -5
- package/src/runtime/office/portable/portable-xlsx-charts.mjs +4 -1
- package/src/runtime/office/portable/portable-xlsx-drawings.mjs +10 -6
- package/src/runtime/office/portable/portable-xlsx-operations.mjs +8 -5
- package/src/runtime/office/portable/portable-xlsx-pivot-ops.mjs +1 -1
- package/src/runtime/office/portable/portable-xlsx-reference-shift.mjs +11 -7
- package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +6 -3
- package/src/runtime/office/portable/portable-xml.mjs +1 -1
- package/src/runtime/shared/atomic-file.mjs +22 -13
- package/src/runtime/shared/background-tasks.mjs +60 -20
- package/src/runtime/shared/child-spawn-gate.mjs +26 -16
- package/src/runtime/shared/config.mjs +0 -10
- package/src/runtime/shared/file-lock.mjs +7 -1
- package/src/runtime/shared/file-permissions-worker.mjs +38 -0
- package/src/runtime/shared/file-permissions.d.mts +19 -4
- package/src/runtime/shared/file-permissions.mjs +310 -4
- package/src/runtime/shared/git-runner-worker.mjs +6 -78
- package/src/runtime/shared/llm/http-agent.mjs +7 -3
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +10 -0
- package/src/runtime/shared/llm/usage-accounting.mjs +2 -0
- package/src/runtime/shared/llm/usage-ledger-import.mjs +32 -3
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +12 -5
- package/src/runtime/shared/llm/usage-ledger-worker.mjs +1 -1
- package/src/runtime/shared/llm/usage-ledger.mjs +20 -5
- package/src/runtime/shared/memory-snapshot.mjs +5 -1
- package/src/runtime/shared/notify-trace.mjs +8 -1
- package/src/runtime/shared/pristine-execution-contract.json +5 -1
- package/src/runtime/shared/process-runner-worker.mjs +7 -0
- package/src/runtime/shared/process-runner.mjs +38 -0
- package/src/runtime/shared/provider-accounts.mjs +2 -1
- package/src/runtime/shared/provider-api-key.mjs +0 -1
- package/src/runtime/shared/read-row-numbers.mjs +1 -1
- package/src/runtime/shared/resource-admission.mjs +60 -18
- package/src/runtime/shared/run-child.mjs +84 -0
- package/src/runtime/shared/session-activity-signal.mjs +23 -0
- package/src/runtime/shared/shell-output-summary.mjs +23 -0
- package/src/runtime/shared/singleton-owner.mjs +126 -42
- package/src/runtime/shared/tool-output-limit.mjs +4 -2
- package/src/runtime/shared/tool-output-marker.mjs +58 -0
- package/src/runtime/shared/user-data-guard.mjs +28 -9
- package/src/runtime/shared/worktrees/activity-gate.mjs +33 -8
- package/src/runtime/shared/worktrees/git-head.mjs +20 -2
- package/src/runtime/shared/worktrees/lock.mjs +3 -2
- package/src/runtime/terminal-bridge/tool-defs.mjs +1 -1
- package/src/runtime/tidy/runners/biome.mjs +3 -1
- package/src/runtime/tidy/shadow.mjs +2 -1
- package/src/runtime/web-search/index.mjs +5 -7
- package/src/runtime/web-search/lib/formatter.mjs +42 -6
- package/src/runtime/web-search/tool-defs.mjs +6 -1
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +4 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +7 -4
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +3 -3
- package/src/session-runtime/lifecycle/shared.mjs +19 -2
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +5 -2
- package/src/session-runtime/lifecycle-api.mjs +3 -1
- package/src/session-runtime/provider-auth/login.mjs +10 -6
- package/src/session-runtime/provider-auth/setup.mjs +19 -2
- package/src/session-runtime/provider-catalog-cache.mjs +101 -25
- package/src/session-runtime/provider-models/catalog-load.mjs +14 -3
- package/src/session-runtime/provider-models/row-hydration.mjs +4 -0
- package/src/session-runtime/provider-models.mjs +76 -10
- package/src/session-runtime/provider-readiness.mjs +4 -0
- package/src/session-runtime/services/agent-tool/close-flow.mjs +2 -1
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +10 -2
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +13 -4
- package/src/session-runtime/services/agent-tool/notify.mjs +15 -4
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +134 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/deferred-spawn.mjs +2 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -1
- package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +8 -3
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +4 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +44 -10
- package/src/session-runtime/services/agent-tool.mjs +20 -0
- package/src/session-runtime/services/provider-admin.mjs +92 -20
- package/src/session-runtime/services/usage-dashboard-model.mjs +2 -2
- package/src/session-runtime/services/usage-dashboard.mjs +27 -69
- package/src/session-runtime/turn/session-ops.mjs +2 -2
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/usage-stats-api.mjs +6 -1
- package/src/standalone/channel-transport/http-routes.mjs +10 -9
- package/src/standalone/daemon-desktop-runtime.mjs +20 -7
- package/src/standalone/daemon-owner.mjs +117 -25
- package/src/standalone/daemon.mjs +43 -13
- package/src/standalone/desktop-service-registry.mjs +32 -5
- package/src/standalone/session-call-cache.mjs +6 -0
- package/src/standalone/session-protocol.mjs +1 -1
- package/src/standalone/session-service/retention/busy.mjs +7 -2
- package/src/standalone/session-transport/routes.mjs +7 -6
- package/src/tui/app/model-options.mjs +39 -2
- package/src/tui/app/model-picker.mjs +16 -2
- package/src/tui/app/provider-setup-picker.mjs +1 -2
- package/src/tui/dist/index.mjs +436 -123
- package/src/tui/session/notice-text.mjs +0 -1
- package/src/tui/session/session-api/intake/submission.mjs +7 -13
- package/src/tui/session/session-api/integrations.mjs +1 -5
- package/src/tui/session/session-flow/drain.mjs +8 -0
- package/src/tui/session/session-flow/steering.mjs +46 -0
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/turn-stream.mjs +33 -0
- package/src/tui/session/turn.mjs +30 -3
- package/src/ui/statusline.mjs +1 -6
- package/src/ui/streaming-markdown-heal.mjs +94 -25
- package/src/vendor/statusline/bin/statusline-route.mjs +0 -1
- package/src/vendor/statusline/src/gateway/route-meta.mjs +0 -1
- package/src/workflows/default/WORKFLOW.md +9 -13
|
@@ -35,7 +35,6 @@ const FAILED_NOTICE_ACTIONS = new Map([
|
|
|
35
35
|
['oauth login', 'start OAuth login'],
|
|
36
36
|
['output style switch', 'switch output style'],
|
|
37
37
|
['openai usage auth save', 'save OpenAI usage auth'],
|
|
38
|
-
['opencode go usage auth save', 'save OpenCode Go usage auth'],
|
|
39
38
|
['plugin add', 'add plugin'],
|
|
40
39
|
['plugin mcp enable', 'enable plugin MCP'],
|
|
41
40
|
['plugin uninstall', 'uninstall plugin'],
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { promptDisplayText } from '../../queue-helpers.mjs';
|
|
5
5
|
|
|
6
6
|
export function createSubmissionIntake(bag) {
|
|
7
|
-
const {
|
|
7
|
+
const { nextId, flags, getState, enqueue, autoClearBeforeSubmit } = bag;
|
|
8
8
|
|
|
9
9
|
const submission = (text, options = {}) => {
|
|
10
10
|
const displayText = promptDisplayText(text, options);
|
|
@@ -25,19 +25,13 @@ export function createSubmissionIntake(bag) {
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
const enqueueSubmission = (intake) => {
|
|
28
|
+
// The queue itself wakes a passive `task wait` or shell hold for typed
|
|
29
|
+
// input (not for slash commands, which run after the turn); see enqueue.
|
|
28
30
|
const accepted = enqueue(intake.text, intake.queueOptions);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if ((intake.queueOptions.mode || 'prompt') === 'prompt') {
|
|
34
|
-
bag.cancelQuotaResumeOnUserInput?.();
|
|
35
|
-
bag.cancelQueuedGoalContinuations?.();
|
|
36
|
-
bag.archiveCompletedGoalOnUserInput?.();
|
|
37
|
-
}
|
|
38
|
-
try {
|
|
39
|
-
runtime.interruptTaskWait?.('user-message');
|
|
40
|
-
} catch {}
|
|
31
|
+
if (accepted !== false && (intake.queueOptions.mode || 'prompt') === 'prompt') {
|
|
32
|
+
bag.cancelQuotaResumeOnUserInput?.();
|
|
33
|
+
bag.cancelQueuedGoalContinuations?.();
|
|
34
|
+
bag.archiveCompletedGoalOnUserInput?.();
|
|
41
35
|
}
|
|
42
36
|
return accepted;
|
|
43
37
|
};
|
|
@@ -139,6 +139,7 @@ export function createSessionIntegrationsApi(bag, { oauthFlows }) {
|
|
|
139
139
|
(result) => `custom provider saved: ${result.id}`
|
|
140
140
|
),
|
|
141
141
|
updateCustomProviderModel: (id, modelId, patch) => runtime.updateCustomProviderModel(id, modelId, patch),
|
|
142
|
+
setModelPreferences: (provider, changes) => runtime.setModelPreferences(provider, changes),
|
|
142
143
|
removeCustomProvider: async (id) => {
|
|
143
144
|
const result = await runtime.removeCustomProvider(id);
|
|
144
145
|
refreshRouteStats();
|
|
@@ -148,11 +149,6 @@ export function createSessionIntegrationsApi(bag, { oauthFlows }) {
|
|
|
148
149
|
testCustomProvider: (input) => runtime.testCustomProvider(input),
|
|
149
150
|
checkCustomProviderKeyEnv: (name) => runtime.checkCustomProviderKeyEnv(name),
|
|
150
151
|
discoverCustomProviderModels: (input) => runtime.discoverCustomProviderModels(input),
|
|
151
|
-
saveOpenCodeGoUsageAuth: async (opts) => {
|
|
152
|
-
await runtime.saveOpenCodeGoUsageAuth(opts);
|
|
153
|
-
pushNotice('OpenCode Go usage auth saved', 'info');
|
|
154
|
-
return true;
|
|
155
|
-
},
|
|
156
152
|
saveOpenAIUsageSessionKey: async (secret) => {
|
|
157
153
|
await runtime.saveOpenAIUsageSessionKey(secret);
|
|
158
154
|
pushNotice('OpenAI usage auth saved', 'info');
|
|
@@ -332,6 +332,14 @@ export function createDrainLoop(
|
|
|
332
332
|
}
|
|
333
333
|
submissions.remember(submissionId);
|
|
334
334
|
pending.push(entry);
|
|
335
|
+
// Typed input or a deliverable notification ends a passive task wait or
|
|
336
|
+
// shell hold so the next boundary hands it to the model now.
|
|
337
|
+
const wake = steering.taskWaitWakeForEntry(entry);
|
|
338
|
+
if (wake) {
|
|
339
|
+
try {
|
|
340
|
+
bag.runtime?.interruptTaskWait?.(wake, wake === 'notification' ? entry.execution?.id || null : null);
|
|
341
|
+
} catch {}
|
|
342
|
+
}
|
|
335
343
|
const needsDurableSteering =
|
|
336
344
|
(getState().busy || getState().commandBusy || flags.autoClearRunning || flags.quotaResumePending) &&
|
|
337
345
|
steering.shouldMirrorSteeringEntry(entry);
|
|
@@ -131,6 +131,47 @@ export function createSteeringOps(bag, { queue, submissions }) {
|
|
|
131
131
|
);
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
// Queued input the user typed (editable prompts), not runtime notices.
|
|
135
|
+
function hasPendingUserInput() {
|
|
136
|
+
if (!admissionOpen()) return false;
|
|
137
|
+
return pending.some((entry) => isQueuedEntryEditable(entry) && !isSlashQueuedEntry(entry));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// A notification the next boundary will deliver: a task notification (one
|
|
141
|
+
// the agent already received through task wait/read is not deliverable) or
|
|
142
|
+
// the Goal closeout. `later` entries (scheduled and channel injects) wait
|
|
143
|
+
// for the turn to end, so they are not deliverable mid-turn.
|
|
144
|
+
function isDeliverableNotification(entry) {
|
|
145
|
+
const mode = entry?.mode;
|
|
146
|
+
return (
|
|
147
|
+
admissionOpen() &&
|
|
148
|
+
(mode === 'task-notification' || mode === 'goal-closeout') &&
|
|
149
|
+
queuePriorityValue(entry.priority) <= queuePriorityValue('next') &&
|
|
150
|
+
canDeliverSteeringEntry(entry) &&
|
|
151
|
+
steeringMessageFromEntry(entry) !== null
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function hasPendingNotification() {
|
|
156
|
+
return pending.some(isDeliverableNotification);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// What one queued entry should wake a passive wait or shell hold for: typed
|
|
160
|
+
// input, a deliverable notification, or nothing (slash commands and
|
|
161
|
+
// informational meta prompts run or ride along without ending a wait).
|
|
162
|
+
function taskWaitWakeForEntry(entry) {
|
|
163
|
+
if (!admissionOpen()) return false;
|
|
164
|
+
if (isQueuedEntryEditable(entry) && !isSlashQueuedEntry(entry)) return 'user-message';
|
|
165
|
+
return isDeliverableNotification(entry) ? 'notification' : false;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// What a passive wait or shell hold should wake for right now: user input
|
|
169
|
+
// first, else a deliverable notification.
|
|
170
|
+
function pendingTaskWaitWake() {
|
|
171
|
+
if (hasPendingUserInput()) return 'user-message';
|
|
172
|
+
return hasPendingNotification() ? 'notification' : false;
|
|
173
|
+
}
|
|
174
|
+
|
|
134
175
|
// `later` notifications (scheduled tasks) are skipped unless the runtime
|
|
135
176
|
// explicitly asks for a later flush.
|
|
136
177
|
function drainPendingSteering(_sessionIdOrOptions = null, maybeOptions = null) {
|
|
@@ -219,6 +260,11 @@ export function createSteeringOps(bag, { queue, submissions }) {
|
|
|
219
260
|
commitSteeringQueueEntries,
|
|
220
261
|
settleSteeredSubmissions,
|
|
221
262
|
hasPendingSteering,
|
|
263
|
+
hasPendingUserInput,
|
|
264
|
+
isDeliverableNotification,
|
|
265
|
+
hasPendingNotification,
|
|
266
|
+
taskWaitWakeForEntry,
|
|
267
|
+
pendingTaskWaitWake,
|
|
222
268
|
drainPendingSteering,
|
|
223
269
|
restoreLeadSteeringFromDisk,
|
|
224
270
|
};
|
|
@@ -39,6 +39,8 @@ export function createSessionFlow(bag) {
|
|
|
39
39
|
enqueue: loop.enqueue,
|
|
40
40
|
settleClosedQueue: loop.settleClosedQueue,
|
|
41
41
|
hasPendingSteering: steering.hasPendingSteering,
|
|
42
|
+
hasPendingUserInput: steering.hasPendingUserInput,
|
|
43
|
+
pendingTaskWaitWake: steering.pendingTaskWaitWake,
|
|
42
44
|
drainPendingSteering: steering.drainPendingSteering,
|
|
43
45
|
restoreLeadSteeringFromDisk: steering.restoreLeadSteeringFromDisk,
|
|
44
46
|
autoClearBeforeSubmit: autoClear.autoClearBeforeSubmit,
|
|
@@ -33,6 +33,12 @@ export function createTurnStream(deps) {
|
|
|
33
33
|
// segment out of the provider's final content individually: the combined
|
|
34
34
|
// prefix no longer matches when the provider omits an earlier segment.
|
|
35
35
|
committedSegments: [],
|
|
36
|
+
// The open segment was settled when the provider streamed a tool call
|
|
37
|
+
// (turn.mjs); cleared when that response's tool calls open.
|
|
38
|
+
settledBeforeToolCall: false,
|
|
39
|
+
// The phase the provider named for the message this segment streams
|
|
40
|
+
// (`commentary` / `final_answer`), or null; the desktop row carries it.
|
|
41
|
+
phase: null,
|
|
36
42
|
thinkingText: '',
|
|
37
43
|
thinkingStartedAt: 0,
|
|
38
44
|
thinkingSegmentStartedAt: 0,
|
|
@@ -113,6 +119,7 @@ function ensureAssistant(stream, initialText = '') {
|
|
|
113
119
|
text: String(initialText || ''),
|
|
114
120
|
at,
|
|
115
121
|
messageId,
|
|
122
|
+
...phaseField(stream),
|
|
116
123
|
...stream.routeMeta,
|
|
117
124
|
});
|
|
118
125
|
}
|
|
@@ -149,11 +156,17 @@ function partialNow(stream) {
|
|
|
149
156
|
streaming: true,
|
|
150
157
|
at: identity.at,
|
|
151
158
|
messageId: identity.messageId,
|
|
159
|
+
...phaseField(stream),
|
|
152
160
|
...stream.routeMeta,
|
|
153
161
|
},
|
|
154
162
|
};
|
|
155
163
|
}
|
|
156
164
|
|
|
165
|
+
// The row's `phase` field; absent when the provider named none.
|
|
166
|
+
function phaseField(stream) {
|
|
167
|
+
return stream.phase ? { phase: stream.phase } : {};
|
|
168
|
+
}
|
|
169
|
+
|
|
157
170
|
function samePartial(left, right) {
|
|
158
171
|
if (left === right) return true;
|
|
159
172
|
if (!left || !right) return false;
|
|
@@ -208,6 +221,7 @@ function resetLineScan(stream) {
|
|
|
208
221
|
function closeAssistantSegment(stream) {
|
|
209
222
|
stream.currentAssistantId = null;
|
|
210
223
|
stream.currentAssistantText = '';
|
|
224
|
+
stream.phase = null;
|
|
211
225
|
stream.claimPersistedAssistant = false;
|
|
212
226
|
stream.assistantIdentity = null;
|
|
213
227
|
resetLineScan(stream);
|
|
@@ -296,6 +310,7 @@ function flushTextBatch(stream) {
|
|
|
296
310
|
text: visibleText,
|
|
297
311
|
streaming: true,
|
|
298
312
|
at: current?.at || Date.now(),
|
|
313
|
+
phase: stream.phase || undefined,
|
|
299
314
|
...stream.routeMeta,
|
|
300
315
|
};
|
|
301
316
|
}
|
|
@@ -449,6 +464,24 @@ export function appendAssistantText(stream, full, { committed = false } = {}) {
|
|
|
449
464
|
flushStreamBatch(stream);
|
|
450
465
|
}
|
|
451
466
|
|
|
467
|
+
// The provider named the phase of the message it is streaming. A message of
|
|
468
|
+
// another phase than the open segment's text is its own row: that segment
|
|
469
|
+
// settles first. A segment whose phase was not known yet (the provider named
|
|
470
|
+
// it only on the finished message) takes it.
|
|
471
|
+
export function noteAssistantPhase(stream, phase) {
|
|
472
|
+
if (phase !== 'commentary' && phase !== 'final_answer') return;
|
|
473
|
+
if (stream.phase === phase) return;
|
|
474
|
+
if (stream.phase && stream.currentAssistantText.trim()) {
|
|
475
|
+
flushStreamBatch(stream);
|
|
476
|
+
commitAssistantSegment(stream);
|
|
477
|
+
}
|
|
478
|
+
stream.phase = phase;
|
|
479
|
+
const tail = stream.getState().streamingTail;
|
|
480
|
+
if (stream.currentAssistantId != null && tail?.id === stream.currentAssistantId) {
|
|
481
|
+
stream.updateStreamingTail(tail.id, { phase });
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
452
485
|
// Reasoning is not a commit boundary: a turn interrupted while it is still
|
|
453
486
|
// thinking produced no model-visible message, so Esc must hand the prompt
|
|
454
487
|
// back to the input box. Text, tool calls and turn end still commit it.
|
package/src/tui/session/turn.mjs
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
appendTextDelta,
|
|
35
35
|
appendAssistantText,
|
|
36
36
|
appendReasoningDelta,
|
|
37
|
+
noteAssistantPhase,
|
|
37
38
|
resetStreamedText,
|
|
38
39
|
applyStageChange,
|
|
39
40
|
settleFinalText,
|
|
@@ -241,9 +242,21 @@ function injectSteerMessage({ stream, cards, pushUserOrSyntheticItem }, text, st
|
|
|
241
242
|
pushUserOrSyntheticItem(value, steeringIds[0], 'injected', steeringItemExtras(steeringMeta));
|
|
242
243
|
}
|
|
243
244
|
|
|
245
|
+
function settleSegmentBeforeToolCall(ctx) {
|
|
246
|
+
const { stream } = ctx;
|
|
247
|
+
if (!stream.currentAssistantText.trim()) return;
|
|
248
|
+
ctx.markPromptCommitted();
|
|
249
|
+
flushStreamBatch(stream);
|
|
250
|
+
commitAssistantSegment(stream, { sealToolBlock: true });
|
|
251
|
+
// The response's own content (onAssistantText, before its tool calls open)
|
|
252
|
+
// is this streamed text again: it must not reopen as a second row.
|
|
253
|
+
stream.settledBeforeToolCall = true;
|
|
254
|
+
}
|
|
255
|
+
|
|
244
256
|
async function openToolCalls(ctx, calls) {
|
|
245
257
|
const { stream, cards, runtime } = ctx;
|
|
246
258
|
ctx.markPromptCommitted();
|
|
259
|
+
stream.settledBeforeToolCall = false;
|
|
247
260
|
// Flush buffered mid-turn assistant text before the tool card appears;
|
|
248
261
|
// otherwise, with neither a thinking panel nor a spinner active, the
|
|
249
262
|
// message above the tool card vanished.
|
|
@@ -372,9 +385,14 @@ function turnHandlers(ctx) {
|
|
|
372
385
|
};
|
|
373
386
|
}
|
|
374
387
|
|
|
375
|
-
function toolHandlers(ctx) {
|
|
388
|
+
export function toolHandlers(ctx) {
|
|
376
389
|
const { isCurrentTurn, cards, getState, set, options } = ctx;
|
|
377
390
|
return {
|
|
391
|
+
// The provider streamed a tool call: the text before it is complete (a
|
|
392
|
+
// preamble), so it settles now instead of after the whole response.
|
|
393
|
+
onAssistantToolCallObserved: () => {
|
|
394
|
+
if (isCurrentTurn()) settleSegmentBeforeToolCall(ctx);
|
|
395
|
+
},
|
|
378
396
|
onToolCall: async (_iter, calls) => {
|
|
379
397
|
if (isCurrentTurn()) await openToolCalls(ctx, calls);
|
|
380
398
|
},
|
|
@@ -431,13 +449,22 @@ export function streamHandlers(ctx) {
|
|
|
431
449
|
// The streaming path owns this segment when it already produced text.
|
|
432
450
|
// Do not check turn-global assistantText: earlier closed preambles stay
|
|
433
451
|
// there across tool calls.
|
|
434
|
-
if (stream.currentAssistantText.trim()) return;
|
|
452
|
+
if (stream.currentAssistantText.trim() || stream.settledBeforeToolCall) return;
|
|
435
453
|
ctx.markPromptCommitted();
|
|
436
454
|
appendAssistantText(stream, full, { committed: detail?.committed === true });
|
|
437
455
|
},
|
|
438
456
|
onReasoningDelta: (chunk) => {
|
|
439
457
|
if (isCurrentTurn()) appendReasoningDelta(stream, String(chunk ?? ''));
|
|
440
458
|
},
|
|
459
|
+
// A provider output item started. A tool call ends the text before it
|
|
460
|
+
// (a preamble settles at the call's start, not after its arguments or
|
|
461
|
+
// the whole response); a message naming its phase marks its row as
|
|
462
|
+
// commentary or final answer.
|
|
463
|
+
onStreamItemStart: (detail) => {
|
|
464
|
+
if (!isCurrentTurn()) return;
|
|
465
|
+
if (detail?.kind === 'tool') settleSegmentBeforeToolCall(ctx);
|
|
466
|
+
else if (detail?.kind === 'text') noteAssistantPhase(stream, detail.phase);
|
|
467
|
+
},
|
|
441
468
|
};
|
|
442
469
|
}
|
|
443
470
|
|
|
@@ -693,7 +720,7 @@ export function createRunTurn(bag) {
|
|
|
693
720
|
markPromptCommitted: () => commitPromptRestore(flags, turn),
|
|
694
721
|
};
|
|
695
722
|
const stopTaskWaitSteeringCheck = registerTaskWaitSteeringCheck(
|
|
696
|
-
(sessionId) => isCurrentTurn() && runtime.id === sessionId && bag.
|
|
723
|
+
(sessionId) => isCurrentTurn() && runtime.id === sessionId && bag.pendingTaskWaitWake()
|
|
697
724
|
);
|
|
698
725
|
try {
|
|
699
726
|
const { result, session } = await runtime.ask(userText, {
|
package/src/ui/statusline.mjs
CHANGED
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
* CLI route passed here.
|
|
11
11
|
*/
|
|
12
12
|
import { readCachedOAuthUsageSnapshot } from '../runtime/agent/orchestrator/providers/oauth-usage.mjs';
|
|
13
|
-
import { readCachedOpenCodeGoUsageSnapshot } from '../runtime/agent/orchestrator/providers/opencode-go-usage.mjs';
|
|
14
13
|
import { buildGatewayLimits } from '../runtime/agent/orchestrator/providers/statusline-route-meta.mjs';
|
|
15
14
|
import { formatGatewayLimitSegments, loadGatewayStatus } from '../vendor/statusline/bin/statusline-route.mjs';
|
|
16
15
|
import { createSessionStats } from './session-stats.mjs';
|
|
@@ -614,14 +613,11 @@ function refreshFallbackQuotaStatus(cacheKey, normalizedProvider, model) {
|
|
|
614
613
|
// the route reports nothing worth a segment.
|
|
615
614
|
function fallbackQuotaValue(routeInfo, normalizedProvider) {
|
|
616
615
|
let usageSnapshot = null;
|
|
617
|
-
if (normalizedProvider
|
|
618
|
-
usageSnapshot = readCachedOpenCodeGoUsageSnapshot();
|
|
619
|
-
} else if (normalizedProvider.includes('oauth')) {
|
|
616
|
+
if (normalizedProvider.includes('oauth')) {
|
|
620
617
|
try {
|
|
621
618
|
usageSnapshot = readCachedOAuthUsageSnapshot(routeInfo, { allowStale: true });
|
|
622
619
|
} catch {}
|
|
623
620
|
}
|
|
624
|
-
if (normalizedProvider === 'opencode-go' && !usageSnapshot) return null;
|
|
625
621
|
// Boot guard: do not render previous-launch usage before the current
|
|
626
622
|
// runtime has captured at least one snapshot. Once captured in this
|
|
627
623
|
// process, keep it visible while idle even if refreshes are delayed.
|
|
@@ -647,7 +643,6 @@ function fallbackQuotaValue(routeInfo, normalizedProvider) {
|
|
|
647
643
|
|
|
648
644
|
function providerKindForQuota(provider) {
|
|
649
645
|
const p = String(provider || '').toLowerCase();
|
|
650
|
-
if (p === 'opencode-go') return 'quota-api';
|
|
651
646
|
if (p.includes('oauth')) return 'oauth';
|
|
652
647
|
if (p === 'mixdog-local') return 'local';
|
|
653
648
|
return 'api';
|
|
@@ -8,19 +8,47 @@ const HEALABLE_MARKDOWN_SYNTAX = /[`*_~[]/;
|
|
|
8
8
|
function openFence(text) {
|
|
9
9
|
let marker = '';
|
|
10
10
|
let length = 0;
|
|
11
|
+
let start = 0;
|
|
12
|
+
let lineStart = 0;
|
|
11
13
|
for (const rawLine of String(text ?? '').split('\n')) {
|
|
12
14
|
const fence = FENCE_LINE.exec(rawLine.replace(/\r$/, ''));
|
|
13
|
-
if (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
marker
|
|
20
|
-
|
|
15
|
+
if (fence) {
|
|
16
|
+
const marks = fence[1];
|
|
17
|
+
if (!marker) {
|
|
18
|
+
marker = marks[0];
|
|
19
|
+
length = marks.length;
|
|
20
|
+
start = lineStart;
|
|
21
|
+
} else if (marks[0] === marker && marks.length >= length && !fence[2].trim()) {
|
|
22
|
+
marker = '';
|
|
23
|
+
length = 0;
|
|
24
|
+
}
|
|
21
25
|
}
|
|
26
|
+
lineStart += rawLine.length + 1;
|
|
22
27
|
}
|
|
23
|
-
return marker ? { marker, length } : null;
|
|
28
|
+
return marker ? { marker, length, start } : null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// The opening fence line arrives a token at a time: ``` → ```py → ```python.
|
|
32
|
+
// Rendered at once, the card opened unlabelled and then relabelled (and
|
|
33
|
+
// re-highlighted) per token. The card appears with its first code character:
|
|
34
|
+
// an opening line alone would paint an empty box before any code.
|
|
35
|
+
function trimPartialOpeningFence(text, fence) {
|
|
36
|
+
const lineEnd = text.indexOf('\n', fence.start);
|
|
37
|
+
return lineEnd >= 0 && /\S/.test(text.slice(lineEnd + 1)) ? text : text.slice(0, fence.start);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// A line holding only a block marker so far has no content to show, and the
|
|
41
|
+
// marker alone parses as something else: `-` or `=` under a paragraph is a
|
|
42
|
+
// setext underline (the paragraph flashed into a heading until the item text
|
|
43
|
+
// arrived), `2` is a lazy paragraph continuation until its `.` arrives, `#`
|
|
44
|
+
// grows into `##`, and a lone backtick run is literal text until it becomes a
|
|
45
|
+
// fence. Hold the line back until its first content character.
|
|
46
|
+
const PENDING_BLOCK_MARKER_LINE = /(?:^|\n)[ \t]*(?:[-+*=_#>~`]+|\d{1,9}[.)]?)[ \t]*$/;
|
|
47
|
+
|
|
48
|
+
function trimPendingBlockMarker(text) {
|
|
49
|
+
const pending = PENDING_BLOCK_MARKER_LINE.exec(text);
|
|
50
|
+
if (!pending) return text;
|
|
51
|
+
return text.slice(0, pending.index + (pending[0].startsWith('\n') ? 1 : 0));
|
|
24
52
|
}
|
|
25
53
|
|
|
26
54
|
// A closing fence arrives a token at a time. Until its run is long enough to
|
|
@@ -57,7 +85,9 @@ function closeInlineCode(text, isPendingLocalPath) {
|
|
|
57
85
|
} else if (run === open) open = 0;
|
|
58
86
|
index = end;
|
|
59
87
|
}
|
|
60
|
-
|
|
88
|
+
// An opener with nothing after it yet closes into an empty span, which
|
|
89
|
+
// parses as a literal backtick run that then vanishes into code.
|
|
90
|
+
if (open && (!text.slice(openIndex + open) || isPendingLocalPath?.(text.slice(openIndex + open)))) {
|
|
61
91
|
return text.slice(0, openIndex);
|
|
62
92
|
}
|
|
63
93
|
return open > 0 ? `${text}${'`'.repeat(open)}` : text;
|
|
@@ -93,6 +123,7 @@ function scanEmphasisRuns(masked) {
|
|
|
93
123
|
let end = index + 1;
|
|
94
124
|
while (masked[end] === marker) end += 1;
|
|
95
125
|
const length = end - index;
|
|
126
|
+
const at = index;
|
|
96
127
|
const before = index > 0 ? masked[index - 1] : '';
|
|
97
128
|
const after = end < masked.length ? masked[end] : '';
|
|
98
129
|
const beforeSpace = isMarkdownSpace(before);
|
|
@@ -102,16 +133,26 @@ function scanEmphasisRuns(masked) {
|
|
|
102
133
|
const left = !afterSpace && (!afterPunctuation || beforeSpace || beforePunctuation);
|
|
103
134
|
const right = !beforeSpace && (!beforePunctuation || afterSpace || afterPunctuation);
|
|
104
135
|
if (marker === '~') {
|
|
105
|
-
|
|
136
|
+
// A single tilde is inert, but at the end it may be half of `~~`.
|
|
137
|
+
runs.push({
|
|
138
|
+
marker,
|
|
139
|
+
length: Math.min(length, 2),
|
|
140
|
+
canOpen: left && length >= 2,
|
|
141
|
+
canClose: right && length >= 2,
|
|
142
|
+
at,
|
|
143
|
+
end,
|
|
144
|
+
});
|
|
106
145
|
} else if (marker === '_') {
|
|
107
146
|
runs.push({
|
|
108
147
|
marker,
|
|
109
148
|
length,
|
|
110
149
|
canOpen: left && (!right || beforePunctuation),
|
|
111
150
|
canClose: right && (!left || afterPunctuation),
|
|
151
|
+
at,
|
|
152
|
+
end,
|
|
112
153
|
});
|
|
113
154
|
} else {
|
|
114
|
-
runs.push({ marker, length, canOpen: left, canClose: right });
|
|
155
|
+
runs.push({ marker, length, canOpen: left, canClose: right, at, end });
|
|
115
156
|
}
|
|
116
157
|
index = end;
|
|
117
158
|
}
|
|
@@ -120,7 +161,9 @@ function scanEmphasisRuns(masked) {
|
|
|
120
161
|
|
|
121
162
|
function closeEmphasis(text) {
|
|
122
163
|
const open = [];
|
|
123
|
-
|
|
164
|
+
const runs = scanEmphasisRuns(maskCode(text));
|
|
165
|
+
const last = runs[runs.length - 1];
|
|
166
|
+
for (const run of runs) {
|
|
124
167
|
let length = run.length;
|
|
125
168
|
while (run.canClose && length > 0) {
|
|
126
169
|
let match = -1;
|
|
@@ -137,13 +180,21 @@ function closeEmphasis(text) {
|
|
|
137
180
|
length -= used;
|
|
138
181
|
open.length = opener.length > 0 ? match + 1 : match;
|
|
139
182
|
}
|
|
183
|
+
// A run ending the text that closed nothing has no content after it yet:
|
|
184
|
+
// it painted as literal `**` until the next token turned it into style.
|
|
185
|
+
if (run === last && run.end === text.length && length === run.length) {
|
|
186
|
+
return closeEmphasis(text.slice(0, run.at));
|
|
187
|
+
}
|
|
140
188
|
if (length > 0 && run.canOpen) open.push({ marker: run.marker, length });
|
|
141
189
|
}
|
|
142
|
-
|
|
190
|
+
// Closers go before trailing whitespace: `**word ` closed after the space
|
|
191
|
+
// could not close (a closing run must follow non-space) and stayed literal.
|
|
192
|
+
const body = text.trimEnd();
|
|
193
|
+
let closers = '';
|
|
143
194
|
for (let index = open.length - 1; index >= 0; index -= 1) {
|
|
144
|
-
|
|
195
|
+
closers += open[index].marker.repeat(Math.min(open[index].length, 3));
|
|
145
196
|
}
|
|
146
|
-
return
|
|
197
|
+
return closers ? `${body}${closers}${text.slice(body.length)}` : text;
|
|
147
198
|
}
|
|
148
199
|
|
|
149
200
|
function linkDestinationEnd(text, start) {
|
|
@@ -228,26 +279,44 @@ function tableCells(line) {
|
|
|
228
279
|
// time. Until the delimiter is complete (and has the header's cell count) the
|
|
229
280
|
// rows are a paragraph of raw pipes, which then re-laid out as a table of a
|
|
230
281
|
// different height — the reply grew and shrank under a followed transcript.
|
|
231
|
-
// Hold both rows back until the table can form in one step.
|
|
282
|
+
// Hold both rows back until the table can form in one step. The head may end
|
|
283
|
+
// a block under paragraph lines (a table directly below its caption line),
|
|
284
|
+
// and a header row needs no leading pipe: such a row is held while it is the
|
|
285
|
+
// block's last line, and with a partial delimiter row below it.
|
|
232
286
|
function trimPendingTableHead(text) {
|
|
233
287
|
let offset = 0;
|
|
234
288
|
for (const blank of text.matchAll(/\n[ \t]*\r?\n/g)) offset = blank.index + blank[0].length;
|
|
235
289
|
const block = text.slice(offset);
|
|
236
290
|
const lines = block.split('\n').map((line) => line.replace(/\r$/, ''));
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
291
|
+
// A row that ended with its newline is still the block's last row: the
|
|
292
|
+
// empty line after it is not a (partial) delimiter row.
|
|
293
|
+
let last = lines.length - 1;
|
|
294
|
+
if (last >= 1 && !lines[last].trim()) last -= 1;
|
|
295
|
+
let head = last;
|
|
296
|
+
if (last >= 1 && PARTIAL_DELIMITER_ROW.test(lines[last]) && hasCellPipe(lines[last - 1])) {
|
|
297
|
+
const delimiter = lines[last];
|
|
298
|
+
if (DELIMITER_ROW.test(delimiter) && tableCells(delimiter) === tableCells(lines[last - 1])) return text;
|
|
299
|
+
head = last - 1;
|
|
242
300
|
}
|
|
243
|
-
|
|
301
|
+
if (!(PIPE_ROW.test(lines[head]) || hasCellPipe(lines[head]))) return text;
|
|
302
|
+
// Rows below a delimiter belong to a table that already formed.
|
|
303
|
+
if (lines.slice(0, head).some((line) => DELIMITER_ROW.test(line))) return text;
|
|
304
|
+
let start = offset;
|
|
305
|
+
for (let index = 0; index < head; index += 1) start += lines[index].length + 1;
|
|
306
|
+
return text.slice(0, start);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// A cell separator outside inline code: the line can head a table.
|
|
310
|
+
function hasCellPipe(line) {
|
|
311
|
+
return /(?<!\\)\|/.test(line.replace(INLINE_CODE_SPAN, ''));
|
|
244
312
|
}
|
|
245
313
|
|
|
246
314
|
export function healStreamingMarkdownTail(text, isPendingLocalPath) {
|
|
247
315
|
const source = String(text ?? '');
|
|
248
316
|
const fence = source.includes('`') || source.includes('~') ? openFence(source) : null;
|
|
249
|
-
if (fence) return trimPartialClosingFence(source, fence);
|
|
250
|
-
const
|
|
317
|
+
if (fence) return trimPartialOpeningFence(trimPartialClosingFence(source, fence), fence);
|
|
318
|
+
const unmarked = trimPendingBlockMarker(source);
|
|
319
|
+
const value = unmarked.includes('|') ? trimPendingTableHead(unmarked) : unmarked;
|
|
251
320
|
const hasSyntax = HEALABLE_MARKDOWN_SYNTAX.test(value);
|
|
252
321
|
if (!value || (!hasSyntax && !isPendingLocalPath)) return value;
|
|
253
322
|
const healed = hasSyntax
|
|
@@ -113,7 +113,6 @@ function cleanString(value) {
|
|
|
113
113
|
function providerKind(provider) {
|
|
114
114
|
const p = String(provider || '').toLowerCase();
|
|
115
115
|
if (!p) return 'unknown';
|
|
116
|
-
if (p === 'opencode-go') return 'quota-api';
|
|
117
116
|
if (p.includes('oauth')) return 'oauth';
|
|
118
117
|
if (p === 'mixdog-local') return 'local';
|
|
119
118
|
return 'api';
|
|
@@ -101,7 +101,6 @@ function cleanBool(value) {
|
|
|
101
101
|
function providerKind(provider) {
|
|
102
102
|
const p = String(provider || '').toLowerCase();
|
|
103
103
|
if (!p) return 'unknown';
|
|
104
|
-
if (p === 'opencode-go') return 'quota-api';
|
|
105
104
|
if (p.includes('oauth')) return 'oauth';
|
|
106
105
|
if (p === 'mixdog-local') return 'local';
|
|
107
106
|
return 'api';
|
|
@@ -4,17 +4,13 @@ name: Default
|
|
|
4
4
|
description: "Handle tasks as requested."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
before asking for approval.
|
|
7
|
+
An explicit request is the approval within its scope: carry it out, including
|
|
8
|
+
routine supporting steps and delegation, without asking again. Resolve
|
|
9
|
+
discoverable facts by inspection; decide minor details yourself and say which
|
|
10
|
+
you chose. Read-only requests do not authorize changes.
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
approved: carry it out without stepwise approval. Reserve questions for scope
|
|
19
|
-
outside that objective, including a commit, push, release, deployment, or
|
|
20
|
-
payment the user has not requested.
|
|
12
|
+
Ask only for a decision that only the user can make and that materially
|
|
13
|
+
changes the outcome, or for authorization outside the request's scope —
|
|
14
|
+
including a commit, push, release, deployment, or payment the user has not
|
|
15
|
+
requested. When user input is required, park only the affected work, continue
|
|
16
|
+
the rest, and ask pending questions together once no such work remains.
|