synabun 2.0.10 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +207 -0
- package/README.md +25 -2
- package/THIRD-PARTY-LICENSES.md +22 -0
- package/bin/synabun.js +71 -24
- package/docs/whatsapp.md +13 -13
- package/hooks/claude-code/pre-websearch.mjs +12 -1
- package/hooks/claude-code/shared.mjs +5 -0
- package/hooks/claude-code/stop.mjs +1 -1
- package/lib/claude-hooks.js +172 -18
- package/lib/client-config-repair.js +30 -17
- package/lib/desktop-app.js +7 -1
- package/lib/external-tools.js +7 -6
- package/lib/first-launch-protection.js +57 -12
- package/lib/mcp-dist.js +176 -0
- package/lib/release-npm-ci.mjs +138 -0
- package/lib/release-publish.mjs +91 -0
- package/lib/release-scan.mjs +50 -0
- package/lib/server-crash-record.js +123 -0
- package/lib/server-exit.js +318 -0
- package/lib/server-supervisor.js +508 -0
- package/lib/start-launcher.js +37 -4
- package/lib/tools-cli.js +45 -0
- package/lib/update-snapshot.js +302 -0
- package/lib/virustotal.mjs +203 -0
- package/lib/windows-crash-event.js +269 -0
- package/mcp-server/dist/http.d.ts +20 -1
- package/mcp-server/dist/http.d.ts.map +1 -1
- package/mcp-server/dist/http.js +59 -12
- package/mcp-server/dist/http.js.map +1 -1
- package/mcp-server/dist/index.d.ts +33 -27
- package/mcp-server/dist/index.d.ts.map +1 -1
- package/mcp-server/dist/index.js +128 -143
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/preload.js +1 -1
- package/mcp-server/dist/preload.js.map +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -1
- package/mcp-server/dist/services/budget-judgments.js +5 -3
- package/mcp-server/dist/services/budget-judgments.js.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.d.ts +6 -2
- package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.js +81 -28
- package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
- package/mcp-server/dist/services/identity.d.ts +2 -2
- package/mcp-server/dist/services/identity.js +2 -2
- package/mcp-server/dist/services/memory-judge-backfill.d.ts +6 -0
- package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
- package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
- package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
- package/mcp-server/dist/services/memory-sessions.d.ts +1 -1
- package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -1
- package/mcp-server/dist/services/memory-sessions.js +28 -2
- package/mcp-server/dist/services/memory-sessions.js.map +1 -1
- package/mcp-server/dist/services/neural-interface.d.ts +18 -11
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js +67 -11
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/server-instructions.d.ts +7 -2
- package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
- package/mcp-server/dist/services/server-instructions.js +22 -63
- package/mcp-server/dist/services/server-instructions.js.map +1 -1
- package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
- package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-catalog.js +339 -0
- package/mcp-server/dist/services/tool-catalog.js.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
- package/mcp-server/dist/services/tool-list.d.ts +108 -0
- package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list.js +334 -0
- package/mcp-server/dist/services/tool-list.js.map +1 -0
- package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
- package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-runtime.js +400 -0
- package/mcp-server/dist/services/tool-runtime.js.map +1 -0
- package/mcp-server/dist/services/typesafe-config.js +1 -1
- package/mcp-server/dist/services/typesafe-config.js.map +1 -1
- package/mcp-server/dist/services/whiteboard-geometry.d.ts +26 -2
- package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
- package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
- package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +14 -14
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +29 -19
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
- package/mcp-server/dist/tools/choice.d.ts +6 -0
- package/mcp-server/dist/tools/choice.d.ts.map +1 -1
- package/mcp-server/dist/tools/choice.js +18 -13
- package/mcp-server/dist/tools/choice.js.map +1 -1
- package/mcp-server/dist/tools/git-tools.js +2 -2
- package/mcp-server/dist/tools/git-tools.js.map +1 -1
- package/mcp-server/dist/tools/image-tools.d.ts +1 -1
- package/mcp-server/dist/tools/image-tools.js +1 -1
- package/mcp-server/dist/tools/morelogin.d.ts.map +1 -1
- package/mcp-server/dist/tools/morelogin.js +9 -6
- package/mcp-server/dist/tools/morelogin.js.map +1 -1
- package/mcp-server/dist/tools/skill-tools.d.ts +505 -0
- package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill-tools.js +642 -0
- package/mcp-server/dist/tools/skill-tools.js.map +1 -0
- package/mcp-server/dist/tools/skill.d.ts +7 -0
- package/mcp-server/dist/tools/skill.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill.js +11 -0
- package/mcp-server/dist/tools/skill.js.map +1 -0
- package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
- package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
- package/mcp-server/dist/tools/tool-groups.js +147 -0
- package/mcp-server/dist/tools/tool-groups.js.map +1 -0
- package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-format.js +7 -4
- package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
- package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
- package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/src/http.ts +75 -12
- package/mcp-server/src/index.ts +147 -154
- package/mcp-server/src/preload.ts +12 -12
- package/mcp-server/src/services/budget-judgments.ts +5 -3
- package/mcp-server/src/services/codex-config-heal.ts +80 -29
- package/mcp-server/src/services/identity.ts +2 -2
- package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
- package/mcp-server/src/services/memory-sessions.ts +24 -3
- package/mcp-server/src/services/neural-interface.ts +81 -21
- package/mcp-server/src/services/server-instructions.ts +29 -64
- package/mcp-server/src/services/tool-catalog.ts +403 -0
- package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
- package/mcp-server/src/services/tool-list.ts +410 -0
- package/mcp-server/src/services/tool-runtime.ts +457 -0
- package/mcp-server/src/services/typesafe-config.ts +1 -1
- package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
- package/mcp-server/src/tools/agents.ts +29 -20
- package/mcp-server/src/tools/choice.ts +17 -12
- package/mcp-server/src/tools/git-tools.ts +2 -2
- package/mcp-server/src/tools/image-tools.ts +1 -1
- package/mcp-server/src/tools/morelogin.ts +6 -4
- package/mcp-server/src/tools/skill-tools.ts +592 -0
- package/mcp-server/src/tools/skill.ts +13 -0
- package/mcp-server/src/tools/tool-groups.ts +164 -0
- package/mcp-server/src/tools/whiteboard-format.ts +9 -3
- package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
- package/neural-interface/i18n/en.json +3953 -228
- package/neural-interface/i18n/pt-BR.json +3901 -179
- package/neural-interface/lib/agent-sandbox-elevation.js +6 -0
- package/neural-interface/lib/antigravity/acp-client-host.js +554 -0
- package/neural-interface/lib/antigravity/acp-connection.js +299 -0
- package/neural-interface/lib/antigravity/bypass.js +100 -0
- package/neural-interface/lib/antigravity/catalog.js +273 -0
- package/neural-interface/lib/antigravity/home.js +260 -0
- package/neural-interface/lib/antigravity/migrate-gemini.js +139 -0
- package/neural-interface/lib/antigravity/panel-bridge.js +1058 -0
- package/neural-interface/lib/antigravity/policy-hook.mjs +78 -0
- package/neural-interface/lib/antigravity/policy.js +74 -0
- package/neural-interface/lib/antigravity/tool-call.js +178 -0
- package/neural-interface/lib/antigravity/transcripts.js +252 -0
- package/neural-interface/lib/antigravity/usage.js +43 -0
- package/neural-interface/lib/assistant-api.js +128 -28
- package/neural-interface/lib/assistant-brains/antigravity.js +423 -0
- package/neural-interface/lib/assistant-brains/claude.js +4 -3
- package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +12 -2
- package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +32 -9
- package/neural-interface/lib/assistant-brains/codex.js +9 -5
- package/neural-interface/lib/assistant-brains/opencode.js +120 -54
- package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +28 -13
- package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +59 -19
- package/neural-interface/lib/assistant-budget-planner.js +7 -3
- package/neural-interface/lib/assistant-budget-split.js +42 -15
- package/neural-interface/lib/assistant-catalog.js +81 -15
- package/neural-interface/lib/assistant-config.js +6 -3
- package/neural-interface/lib/assistant-dispatch.js +1073 -200
- package/neural-interface/lib/assistant-envelope.js +156 -2
- package/neural-interface/lib/assistant-evidence.js +80 -0
- package/neural-interface/lib/assistant-hidden-models.js +7 -5
- package/neural-interface/lib/assistant-persona.js +93 -19
- package/neural-interface/lib/assistant-plan-permissions.js +25 -9
- package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
- package/neural-interface/lib/assistant-route-gate.js +6 -4
- package/neural-interface/lib/assistant-router.js +245 -38
- package/neural-interface/lib/assistant-runtime.js +214 -30
- package/neural-interface/lib/assistant-task-prompt.js +87 -21
- package/neural-interface/lib/assistant-tools.js +51 -0
- package/neural-interface/lib/assistant-usage.js +29 -0
- package/neural-interface/lib/backup-service.js +626 -4
- package/neural-interface/lib/backup-zip-reader.js +10 -5
- package/neural-interface/lib/backup-zip-writer.js +257 -0
- package/neural-interface/lib/browser-execution.js +10 -2
- package/neural-interface/lib/browser-guard-cdp.js +84 -0
- package/neural-interface/lib/browser-network-guard.js +476 -0
- package/neural-interface/lib/browser-policy-roots.js +64 -0
- package/neural-interface/lib/browser-tool-policy.js +198 -38
- package/neural-interface/lib/claude-agent-bridge.js +11 -2
- package/neural-interface/lib/claude-history-cache.js +210 -0
- package/neural-interface/lib/claude-hooks-status.js +103 -0
- package/neural-interface/lib/claude-model-catalog.js +5 -1
- package/neural-interface/lib/claude-temporary.js +5 -11
- package/neural-interface/lib/cli-install-api.js +1 -1
- package/neural-interface/lib/cli-install.js +163 -154
- package/neural-interface/lib/cli-resolver.js +13 -3
- package/neural-interface/lib/cli-update-planner.js +52 -41
- package/neural-interface/lib/cloudflared/tunnel.js +42 -2
- package/neural-interface/lib/codex-mcp-approvals.js +11 -0
- package/neural-interface/lib/codex-rollout-reader.js +52 -0
- package/neural-interface/lib/codex-worker-app-server.js +191 -0
- package/neural-interface/lib/confined-fs.js +30 -3
- package/neural-interface/lib/crash-notice-api.js +98 -0
- package/neural-interface/lib/editor-completion-opencode.js +68 -68
- package/neural-interface/lib/editor-git-api.js +3 -20
- package/neural-interface/lib/exec-loop-command.js +13 -10
- package/neural-interface/lib/file-explorer-api.js +74 -40
- package/neural-interface/lib/file-explorer-watch.js +9 -3
- package/neural-interface/lib/git-bash/install.js +52 -6
- package/neural-interface/lib/git-bash/manager.js +59 -17
- package/neural-interface/lib/git-bash/pins.js +12 -0
- package/neural-interface/lib/git-read.js +2 -2
- package/neural-interface/lib/git-status-runner.js +390 -0
- package/neural-interface/lib/git-status-watchdog.js +40 -0
- package/neural-interface/lib/greeting/budgets.js +1 -0
- package/neural-interface/lib/greeting/engine.js +2 -2
- package/neural-interface/lib/greeting/sources.js +10 -12
- package/neural-interface/lib/greeting/writer.js +1 -1
- package/neural-interface/lib/http-guards.js +8 -2
- package/neural-interface/lib/install-details.js +4 -1
- package/neural-interface/lib/mcp-agent-servers.js +67 -0
- package/neural-interface/lib/mcp-client-config.js +35 -33
- package/neural-interface/lib/mcp-external-servers.js +332 -0
- package/neural-interface/lib/mcp-installer.js +2 -1
- package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
- package/neural-interface/lib/memory-session-capture.js +17 -3
- package/neural-interface/lib/morelogin.js +177 -25
- package/neural-interface/lib/native-loop-providers.js +965 -66
- package/neural-interface/lib/native-loop-runtime.js +290 -42
- package/neural-interface/lib/opencode-config.js +557 -0
- package/neural-interface/lib/opencode-db-schema.js +17 -34
- package/neural-interface/lib/opencode-history.js +48 -218
- package/neural-interface/lib/opencode-mcp-ready.js +108 -0
- package/neural-interface/lib/opencode-native-boundary.js +53 -0
- package/neural-interface/lib/opencode-protocol.js +249 -112
- package/neural-interface/lib/opencode-runtime-config.js +32 -22
- package/neural-interface/lib/opencode-serve-records.js +39 -21
- package/neural-interface/lib/opencode-v2-client.js +48 -153
- package/neural-interface/lib/opencode-v2-ws-requests.js +36 -210
- package/neural-interface/lib/opencode-worker-data.js +27 -0
- package/neural-interface/lib/opencode2-client.js +73 -37
- package/neural-interface/lib/opencode2-proxy.js +23 -63
- package/neural-interface/lib/opencode2-translate.js +51 -2
- package/neural-interface/lib/owner-authority.js +249 -0
- package/neural-interface/lib/page-session.js +275 -0
- package/neural-interface/lib/path-confine.js +12 -9
- package/neural-interface/lib/peer-identity.js +793 -0
- package/neural-interface/lib/pty-host/core.js +28 -1
- package/neural-interface/lib/pty-host/lifetime.js +12 -0
- package/neural-interface/lib/pty-host/manager.js +12 -1
- package/neural-interface/lib/remote-policy.js +1 -1
- package/neural-interface/lib/request-gate.js +20 -2
- package/neural-interface/lib/rulesets/api.js +7 -6
- package/neural-interface/lib/rulesets/fs-safe.js +1 -1
- package/neural-interface/lib/rulesets/installer.js +180 -36
- package/neural-interface/lib/rulesets/json-edit.js +1 -1
- package/neural-interface/lib/rulesets/render.js +1 -1
- package/neural-interface/lib/session-cache-builder.js +81 -31
- package/neural-interface/lib/session-title-generator.js +58 -36
- package/neural-interface/lib/skills/api-v2.js +495 -0
- package/neural-interface/lib/skills/bundle.js +418 -0
- package/neural-interface/lib/skills/catalog.js +298 -0
- package/neural-interface/lib/skills/creation-api.js +191 -0
- package/neural-interface/lib/skills/creation-brief.js +247 -0
- package/neural-interface/lib/skills/creation-sources.js +285 -0
- package/neural-interface/lib/skills/creation.js +843 -0
- package/neural-interface/lib/skills/deploy.js +569 -0
- package/neural-interface/lib/skills/digest.js +119 -0
- package/neural-interface/lib/skills/discover.js +111 -0
- package/neural-interface/lib/skills/draft-confinement.js +216 -0
- package/neural-interface/lib/skills/eval-confinement.js +399 -0
- package/neural-interface/lib/skills/eval-sandbox.js +280 -0
- package/neural-interface/lib/skills/eval-trace.js +135 -0
- package/neural-interface/lib/skills/evals-api.js +212 -0
- package/neural-interface/lib/skills/evals.js +1573 -0
- package/neural-interface/lib/skills/export.js +203 -0
- package/neural-interface/lib/skills/frontmatter.js +64 -0
- package/neural-interface/lib/skills/health.js +75 -0
- package/neural-interface/lib/skills/json-edit.js +165 -0
- package/neural-interface/lib/skills/known-bridge-digests.json +441 -0
- package/neural-interface/lib/skills/known-bridges.js +96 -0
- package/neural-interface/lib/skills/library.js +823 -0
- package/neural-interface/lib/skills/local-store.js +21 -0
- package/neural-interface/lib/skills/migration.js +433 -0
- package/neural-interface/lib/skills/operations.js +45 -0
- package/neural-interface/lib/skills/ownership.js +427 -0
- package/neural-interface/lib/skills/packages.js +88 -0
- package/neural-interface/lib/skills/reviews.js +212 -0
- package/neural-interface/lib/skills/revision.js +80 -0
- package/neural-interface/lib/skills/roots.js +269 -0
- package/neural-interface/lib/skills/runtime-checks.js +358 -0
- package/neural-interface/lib/skills/scan-assets.js +252 -0
- package/neural-interface/lib/skills/scan-context.js +26 -0
- package/neural-interface/lib/skills/scan-shell.js +324 -0
- package/neural-interface/lib/skills/scan.js +364 -0
- package/neural-interface/lib/skills/scanners.js +54 -0
- package/neural-interface/lib/skills/service.js +530 -0
- package/neural-interface/lib/skills/telemetry.js +119 -0
- package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
- package/neural-interface/lib/synabun-version.js +1 -1
- package/neural-interface/lib/system-activity.js +1 -1
- package/neural-interface/lib/tool-lists.js +124 -0
- package/neural-interface/lib/whatsapp/brain.js +7 -3
- package/neural-interface/lib/whatsapp/bridge.js +6 -3
- package/neural-interface/lib/whatsapp/cards.js +22 -9
- package/neural-interface/lib/whatsapp/config.js +1 -1
- package/neural-interface/lib/worker-confinement.js +1268 -0
- package/neural-interface/lib/worker-guard-setting.js +56 -0
- package/neural-interface/lib/worker-mcp-channel.js +175 -0
- package/neural-interface/lib/worker-question.js +74 -0
- package/neural-interface/lib/worker-relay-ports.js +227 -0
- package/neural-interface/lib/worker-resume.js +238 -0
- package/neural-interface/lib/worker-sandbox.js +329 -0
- package/neural-interface/package-lock.json +34 -12
- package/neural-interface/package.json +3 -2
- package/neural-interface/public/index.html +3 -1
- package/neural-interface/public/index2d.html +19 -11
- package/neural-interface/public/onboarding.html +3 -3
- package/neural-interface/public/shared/account-menu.js +8 -5
- package/neural-interface/public/shared/agent-runtime-options.js +125 -31
- package/neural-interface/public/shared/agy/agy-bypass.js +47 -0
- package/neural-interface/public/shared/agy/agy-client.js +266 -0
- package/neural-interface/public/shared/agy/agy-commands.js +120 -0
- package/neural-interface/public/shared/agy/agy-copy.js +326 -0
- package/neural-interface/public/shared/agy/agy-diff.js +161 -0
- package/neural-interface/public/shared/agy/agy-events.js +469 -0
- package/neural-interface/public/shared/agy/agy-greeting.js +26 -0
- package/neural-interface/public/shared/agy/agy-options.js +232 -0
- package/neural-interface/public/shared/agy/agy-panel.js +2543 -0
- package/neural-interface/public/shared/agy/agy-render.js +392 -0
- package/neural-interface/public/shared/agy/agy-setup.js +149 -0
- package/neural-interface/public/shared/agy/agy-styles.js +604 -0
- package/neural-interface/public/shared/agy/agy-tabs-logic.js +181 -0
- package/neural-interface/public/shared/api.js +1527 -1336
- package/neural-interface/public/shared/app-frame.js +192 -0
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +36 -6
- package/neural-interface/public/shared/assistant/asst-api.js +1 -1
- package/neural-interface/public/shared/assistant/asst-ask-styles.js +270 -0
- package/neural-interface/public/shared/assistant/asst-ask-tail.js +118 -0
- package/neural-interface/public/shared/assistant/asst-ask.js +397 -0
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +105 -44
- package/neural-interface/public/shared/assistant/asst-budget.js +5 -4
- package/neural-interface/public/shared/assistant/asst-control.js +205 -26
- package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
- package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
- package/neural-interface/public/shared/assistant/asst-hosts.js +16 -7
- package/neural-interface/public/shared/assistant/asst-limit-dock.js +45 -0
- package/neural-interface/public/shared/assistant/asst-limit-wait.js +327 -0
- package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
- package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
- package/neural-interface/public/shared/assistant/asst-menu.js +7 -6
- package/neural-interface/public/shared/assistant/asst-panel.js +151 -19
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +66 -49
- package/neural-interface/public/shared/assistant/asst-render.js +445 -82
- package/neural-interface/public/shared/assistant/asst-route.js +304 -53
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +9 -8
- package/neural-interface/public/shared/assistant/asst-scenes.js +56 -1
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +117 -10
- package/neural-interface/public/shared/assistant/asst-slash.js +17 -9
- package/neural-interface/public/shared/assistant/asst-state.js +87 -24
- package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +93 -21
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +190 -23
- package/neural-interface/public/shared/assistant/asst-usage.js +2 -1
- package/neural-interface/public/shared/automation-context.js +5 -2
- package/neural-interface/public/shared/cc-dropdown.js +89 -19
- package/neural-interface/public/shared/cdx/cdx-context-menu.js +10 -9
- package/neural-interface/public/shared/cdx/cdx-copy.js +16 -0
- package/neural-interface/public/shared/cdx/cdx-output-model.js +22 -1
- package/neural-interface/public/shared/cdx/cdx-output.js +34 -10
- package/neural-interface/public/shared/cdx/cdx-panel.js +59 -151
- package/neural-interface/public/shared/cdx/cdx-preview.js +12 -0
- package/neural-interface/public/shared/cdx/cdx-protocol.js +39 -11
- package/neural-interface/public/shared/cdx/cdx-render.js +57 -38
- package/neural-interface/public/shared/cdx/cdx-requests.js +14 -4
- package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
- package/neural-interface/public/shared/cdx/cdx-styles.js +15 -3
- package/neural-interface/public/shared/cdx/cdx-tabs.js +127 -44
- package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
- package/neural-interface/public/shared/cli-install-controller.js +218 -0
- package/neural-interface/public/shared/cli-install-view.js +11 -12
- package/neural-interface/public/shared/cli-status.js +11 -10
- package/neural-interface/public/shared/constants.js +5 -4
- package/neural-interface/public/shared/context-menu-areas.js +34 -0
- package/neural-interface/public/shared/context-menu-logic.js +243 -0
- package/neural-interface/public/shared/context-menu-model.js +367 -0
- package/neural-interface/public/shared/context-menu.js +372 -0
- package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
- package/neural-interface/public/shared/cp/cp-restore.js +162 -0
- package/neural-interface/public/shared/cp/cp-tool-cards.js +10 -3
- package/neural-interface/public/shared/crash-notice-view.js +168 -0
- package/neural-interface/public/shared/desktop-bridge.js +17 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +12 -0
- package/neural-interface/public/shared/desktop-titlebar.js +13 -4
- package/neural-interface/public/shared/desktop-update-view.js +21 -0
- package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
- package/neural-interface/public/shared/explorer/fx-api.js +4 -4
- package/neural-interface/public/shared/explorer/fx-links.js +3 -3
- package/neural-interface/public/shared/explorer/fx-logic.js +1 -1
- package/neural-interface/public/shared/explorer/fx-main.js +48 -16
- package/neural-interface/public/shared/explorer/fx-tree.js +1 -0
- package/neural-interface/public/shared/greeting/greeting-card.js +2 -2
- package/neural-interface/public/shared/greeting/greeting-view.js +1 -0
- package/neural-interface/public/shared/html-shell.js +30 -15
- package/neural-interface/public/shared/i18n.js +2 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +7 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +4 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +3 -101
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +2 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +1 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +2 -6
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +11 -11
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +0 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +8 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +7 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-outcome-notifications.js +16 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +74 -259
- package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
- package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +95 -202
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +13 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +13 -22
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +4 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +8 -61
- package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +2 -91
- package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +16 -15
- package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +8 -21
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +1 -99
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +5 -35
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +17 -21
- package/neural-interface/public/shared/ocp-v2/{ocp-v2-profile-inheritance.js → ocp-v2-tools-inheritance.js} +16 -16
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +60 -50
- package/neural-interface/public/shared/page-session.js +96 -0
- package/neural-interface/public/shared/provider-icons.js +4 -2
- package/neural-interface/public/shared/registry.js +5 -3
- package/neural-interface/public/shared/retired-2d.js +3 -0
- package/neural-interface/public/shared/schedules-view.js +195 -61
- package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
- package/neural-interface/public/shared/settings/settings-data.js +3 -1
- package/neural-interface/public/shared/settings/settings-ia.js +6 -6
- package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
- package/neural-interface/public/shared/settings/settings-rules.js +2 -2
- package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +265 -0
- package/neural-interface/public/shared/settings/settings-skill-folders.js +130 -0
- package/neural-interface/public/shared/settings/settings-worker-guard.js +72 -0
- package/neural-interface/public/shared/showcase-privacy.js +6 -1
- package/neural-interface/public/shared/sidepanel-session-status.js +3 -3
- package/neural-interface/public/shared/skills/ss-args.js +96 -0
- package/neural-interface/public/shared/skills/ss-creation.js +222 -0
- package/neural-interface/public/shared/skills/ss-dialog.js +133 -0
- package/neural-interface/public/shared/skills/ss-doc.js +173 -0
- package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
- package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
- package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
- package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
- package/neural-interface/public/shared/skills/ss-evals.js +417 -0
- package/neural-interface/public/shared/skills/ss-form.js +159 -0
- package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
- package/neural-interface/public/shared/skills/ss-ids.js +32 -0
- package/neural-interface/public/shared/skills/ss-lint.js +149 -0
- package/neural-interface/public/shared/skills/ss-presets.js +117 -0
- package/neural-interface/public/shared/skills/ss-profiles.js +513 -0
- package/neural-interface/public/shared/skills/ss-resources.js +165 -0
- package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
- package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
- package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
- package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
- package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai.js +237 -0
- package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
- package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
- package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
- package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
- package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
- package/neural-interface/public/shared/skills/studio/sx-dom.js +230 -0
- package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
- package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
- package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
- package/neural-interface/public/shared/skills/studio/sx-fixes-view.js +359 -0
- package/neural-interface/public/shared/skills/studio/sx-fixes.js +327 -0
- package/neural-interface/public/shared/skills/studio/sx-geometry.js +82 -0
- package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
- package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
- package/neural-interface/public/shared/skills/studio/sx-install-flow.js +282 -0
- package/neural-interface/public/shared/skills/studio/sx-install.js +313 -0
- package/neural-interface/public/shared/skills/studio/sx-library-view.js +748 -0
- package/neural-interface/public/shared/skills/studio/sx-library.js +479 -0
- package/neural-interface/public/shared/skills/studio/sx-main.js +690 -0
- package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
- package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
- package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
- package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
- package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
- package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
- package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
- package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
- package/neural-interface/public/shared/skills/studio/sx-subject.js +249 -0
- package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
- package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
- package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
- package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +426 -0
- package/neural-interface/public/shared/state.js +1 -1
- package/neural-interface/public/shared/streaming-markdown.js +58 -0
- package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
- package/neural-interface/public/shared/styles.css +1822 -1756
- package/neural-interface/public/shared/synabun-mascot.js +1115 -9
- package/neural-interface/public/shared/text-cache.js +29 -0
- package/neural-interface/public/shared/tool-list-picker.js +55 -0
- package/neural-interface/public/shared/tool-list-storage.js +24 -0
- package/neural-interface/public/shared/tool-list-view.js +112 -0
- package/neural-interface/public/shared/topright-overflow-logic.js +54 -0
- package/neural-interface/public/shared/tour/tour-actor.js +268 -0
- package/neural-interface/public/shared/tour/tour-beats.js +336 -0
- package/neural-interface/public/shared/tour/tour-engine.js +884 -0
- package/neural-interface/public/shared/tour/tour-ink.js +390 -0
- package/neural-interface/public/shared/tour/tour-stage.js +440 -0
- package/neural-interface/public/shared/tour/tour-state.js +40 -0
- package/neural-interface/public/shared/tour/tour-tips.js +99 -0
- package/neural-interface/public/shared/tour/tour.css +144 -0
- package/neural-interface/public/shared/ui-antigravity-panel.js +19 -0
- package/neural-interface/public/shared/ui-assistant.js +2 -0
- package/neural-interface/public/shared/ui-automation-studio.js +111 -140
- package/neural-interface/public/shared/ui-claude-panel.js +376 -82
- package/neural-interface/public/shared/ui-cli-banner.js +23 -167
- package/neural-interface/public/shared/ui-command-runner.js +6 -3
- package/neural-interface/public/shared/ui-context-menu.js +295 -0
- package/neural-interface/public/shared/ui-cost-widget.js +57 -59
- package/neural-interface/public/shared/ui-crash-notice.js +187 -0
- package/neural-interface/public/shared/ui-detail.js +15 -3
- package/neural-interface/public/shared/ui-file-explorer.js +48 -6
- package/neural-interface/public/shared/ui-file-links.js +2 -2
- package/neural-interface/public/shared/ui-games.js +2 -2
- package/neural-interface/public/shared/ui-image-gallery.js +50 -47
- package/neural-interface/public/shared/ui-judgments.js +1 -1
- package/neural-interface/public/shared/ui-keybinds.js +33 -2
- package/neural-interface/public/shared/ui-link.js +3 -3
- package/neural-interface/public/shared/ui-menubar.js +10 -20
- package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +11 -1
- package/neural-interface/public/shared/ui-navbar.js +49 -24
- package/neural-interface/public/shared/ui-notifications.js +1 -0
- package/neural-interface/public/shared/ui-panels.js +96 -65
- package/neural-interface/public/shared/ui-resume.js +9 -7
- package/neural-interface/public/shared/ui-schedules-studio.js +546 -431
- package/neural-interface/public/shared/ui-scroll-follow.js +16 -5
- package/neural-interface/public/shared/ui-sessions.js +27 -15
- package/neural-interface/public/shared/ui-settings.js +683 -526
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +9 -2
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +4 -4
- package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
- package/neural-interface/public/shared/ui-sidepanel-tray.js +48 -7
- package/neural-interface/public/shared/ui-sidepanel-windows.js +18 -13
- package/neural-interface/public/shared/ui-skills.js +33 -2830
- package/neural-interface/public/shared/ui-styleguide.js +5 -2
- package/neural-interface/public/shared/ui-sync.js +15 -5
- package/neural-interface/public/shared/ui-terminal.js +270 -190
- package/neural-interface/public/shared/ui-tool-updates.js +6 -4
- package/neural-interface/public/shared/ui-tooltip.js +81 -51
- package/neural-interface/public/shared/ui-topright-overflow.js +233 -0
- package/neural-interface/public/shared/ui-trash.js +6 -4
- package/neural-interface/public/shared/ui-tutorial-layout.js +3 -117
- package/neural-interface/public/shared/ui-tutorial-preview.js +103 -0
- package/neural-interface/public/shared/ui-tutorial-steps.js +3 -65
- package/neural-interface/public/shared/ui-tutorial.css +47 -100
- package/neural-interface/public/shared/ui-tutorial.js +285 -509
- package/neural-interface/public/shared/ui-update.js +38 -2
- package/neural-interface/public/shared/ui-whiteboard.js +312 -59
- package/neural-interface/public/shared/ui-worker-end.js +5 -1
- package/neural-interface/public/shared/ui-workspaces.js +3 -2
- package/neural-interface/public/shared/view-variant.js +66 -0
- package/neural-interface/public/shared/whatsapp/wa-view.js +3 -3
- package/neural-interface/public/shared/whiteboard-list.js +172 -0
- package/neural-interface/public/shared/worker-end.js +10 -3
- package/neural-interface/public/shared/worker-questions.js +34 -0
- package/neural-interface/public/shared/worker-restart.js +12 -0
- package/neural-interface/public/sidepanel-session.html +2 -2
- package/neural-interface/public/variant/2d/background.js +2 -1
- package/neural-interface/public/variant/2d/context-menu.js +8 -2
- package/neural-interface/public/variant/2d/graph.js +42 -20
- package/neural-interface/public/variant/2d/hulls.js +14 -9
- package/neural-interface/public/variant/2d/lasso.js +11 -7
- package/neural-interface/public/variant/2d/main.js +32 -1
- package/neural-interface/public/variant/2d/minimap.js +11 -13
- package/neural-interface/public/variant/3d/main.js +69 -6
- package/neural-interface/public/variant/3d/map-controls.js +24 -9
- package/neural-interface/public/vendor/caveat/OFL.txt +93 -0
- package/neural-interface/public/vendor/caveat/caveat-latin-400-normal.woff2 +0 -0
- package/neural-interface/public/vendor/caveat/caveat-latin-700-normal.woff2 +0 -0
- package/neural-interface/public/vendor/caveat/caveat.css +17 -0
- package/neural-interface/public/vendor/caveat/manifest.json +12 -0
- package/neural-interface/public/vendor/yaml/LICENSE +13 -0
- package/neural-interface/public/vendor/yaml/manifest.json +4 -0
- package/neural-interface/public/vendor/yaml/yaml-2.9.1.min.js +137 -0
- package/neural-interface/scripts/build-vendor.mjs +32 -0
- package/neural-interface/server.js +4553 -2855
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/neural-interface/templates/rulesets/core.md +1 -1
- package/neural-interface/templates/rulesets/legacy-hashes.json +23 -5
- package/neural-interface/templates/rulesets/manifest.json +8 -8
- package/npm-shrinkwrap.json +34 -12
- package/package.json +17 -3
- package/postinstall.js +9 -4
- package/preuninstall.js +1 -1
- package/setup.js +97 -322
- package/skills/skill-forge/SKILL.md +177 -0
- package/skills/skill-forge/evals/evals.json +54 -0
- package/skills/skill-forge/references/package.md +105 -0
- package/skills/skill-forge/references/review-and-recovery.md +63 -0
- package/skills/skill-forge/references/runtime-profiles.md +20 -0
- package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
- package/skills/synabun/SKILL.md +10 -7
- package/skills/synabun/modules/audit.md +1 -5
- package/skills/synabun/modules/changelog.md +1 -5
- package/skills/synabun/modules/idea.md +1 -1
- package/skills/synabun/modules/memorize.md +6 -9
- package/skills/synabun/modules/schedule.md +6 -6
- package/mcp-server/dist/services/profiles.d.ts +0 -120
- package/mcp-server/dist/services/profiles.d.ts.map +0 -1
- package/mcp-server/dist/services/profiles.js +0 -387
- package/mcp-server/dist/services/profiles.js.map +0 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +0 -97
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +0 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.js +0 -228
- package/mcp-server/dist/tools/leonardo-browser-tools.js.map +0 -1
- package/mcp-server/dist/tools/leonardo.d.ts +0 -13
- package/mcp-server/dist/tools/leonardo.d.ts.map +0 -1
- package/mcp-server/dist/tools/leonardo.js +0 -21
- package/mcp-server/dist/tools/leonardo.js.map +0 -1
- package/mcp-server/dist/tools/profile.d.ts +0 -17
- package/mcp-server/dist/tools/profile.d.ts.map +0 -1
- package/mcp-server/dist/tools/profile.js +0 -114
- package/mcp-server/dist/tools/profile.js.map +0 -1
- package/mcp-server/src/services/profiles.ts +0 -428
- package/mcp-server/src/tools/leonardo-browser-tools.ts +0 -291
- package/mcp-server/src/tools/leonardo.ts +0 -30
- package/mcp-server/src/tools/profile.ts +0 -122
- package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +0 -47
- package/neural-interface/lib/assistant-brains/opencode-route-gate.js +0 -62
- package/neural-interface/lib/mcp-profile-servers.js +0 -120
- package/neural-interface/public/shared/ui-tutorial-draw.js +0 -311
- package/skills/leonardo/SKILL.md +0 -168
- package/skills/leonardo/icon.svg +0 -1
- package/skills/leonardo/modules/browser-guide.md +0 -378
- package/skills/leonardo/modules/image-prompter.md +0 -283
- package/skills/leonardo/modules/model-advisor.md +0 -100
- package/skills/leonardo/modules/prompt-library.md +0 -110
- package/skills/leonardo/modules/style-guide.md +0 -186
- package/skills/leonardo/modules/video-prompter.md +0 -317
- /package/neural-interface/templates/rulesets/{gemini.md → antigravity.md} +0 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { t } from './i18n.js';
|
|
2
|
+
import { answerWorkerQuestion, syncWorkerQuestionQueue } from './worker-questions.js';
|
|
1
3
|
import { providerAuthSnapshot } from './ui-provider-auth.js';
|
|
2
4
|
import { mountProviderTerminalAuth, providerApiKeyRequest, startProviderTerminalLogin } from './ui-provider-terminal-auth.js';
|
|
3
5
|
import { accountName, accountSwitchPlan, accountText, tabAccountId, serverAccountId } from './account-view.js';
|
|
@@ -23,7 +25,7 @@ import { createStickyScrollController } from './ui-scroll-follow.js';
|
|
|
23
25
|
import { requestGeneratedSessionTitle } from './session-title.js';
|
|
24
26
|
import { wireFileLinks } from './ui-file-links.js';
|
|
25
27
|
import { WORKER_END_CLASS, backToAssistant, buildWorkerEndCard, endWorkerRunOnClose, forgetWorkerEnd, trackWorkerEnd, updateWorkerEndBusy } from './ui-worker-end.js';
|
|
26
|
-
import { isDispatchedRun, isEndOfRunAbort } from './worker-end.js';
|
|
28
|
+
import { isDispatchedRun, isEndOfRunAbort, workerEndView } from './worker-end.js';
|
|
27
29
|
import { runAwaitsAnswer } from './sidepanel-session-status.js';
|
|
28
30
|
// ── cp/ feature modules (SDK-engine CLI parity: diffs, agents, bash, perms, statusline) ──
|
|
29
31
|
import { setCpCtx } from './cp/cp-ctx.js';
|
|
@@ -52,7 +54,7 @@ import { sanitizeStoredHtml } from './assistant/asst-sanitize.js';
|
|
|
52
54
|
import { escapeHtml, classToken } from './cp/cp-markdown.js';
|
|
53
55
|
import { rehydrateStoredTranscript } from './cp/cp-rehydrate.js';
|
|
54
56
|
import { compactHolds, compactQueue, isCompactCommand, newConversation, nextQueued, ownsQueued, queuedRefusal, restoredQueue, QUEUED_REFUSAL_LINES } from './cp/cp-compose.js';
|
|
55
|
-
import { scrubSavedTab, historyProjectOf, shownUuids, shownTail, snapshotVerdict, withStartConfig, historyOutcome, transcriptOwner, historyNotFoundText } from './cp/cp-restore.js';
|
|
57
|
+
import { scrubSavedTab, historyProjectOf, shownUuids, shownTail, snapshotVerdict, withStartConfig, historyOutcome, transcriptOwner, historyNotFoundText, splitHistoryTail, replayTodosFromMessages, markHistoryRows, earlierHistoryRows, HISTORY_ROW as HISTORY_ROW_KEY, liveRows, queueHistoryLoad, historyGate, renderHistoryRowsInto, holdPendingResult, takePendingResult } from './cp/cp-restore.js';
|
|
56
58
|
import { hasCapability, slashCommandRoute, bypassesPromptBuffer, idleEndsTurn, describeResult, describeTurnFooter, localCommandOutput, splitAssistantBlocks, normalizeSlashCommands, matchSlashCommands, listSlashCommands, slashMenuMaxHeight, splitCommandsByCapability, readInit, statusRows } from './cp/cp-events.js';
|
|
57
59
|
import {
|
|
58
60
|
renderSdkEvent, noteUnhandledEvent, applyEngineHello, renderCompactBoundary, markDeniedFromResult, endTurnRows,
|
|
@@ -282,7 +284,7 @@ const _snapshotsReady = fetchBlobNamespace('claude-snapshots')
|
|
|
282
284
|
const EFFORT_LEVELS = ['off', 'low', 'medium', 'high', 'xhigh', 'max'];
|
|
283
285
|
const EFFORT_LABELS = { off: 'Think', low: 'lo', medium: 'med', high: 'hi', xhigh: 'xhi', max: 'max' };
|
|
284
286
|
const EFFORT_TITLES = {
|
|
285
|
-
off: '
|
|
287
|
+
off: 'Thinking off',
|
|
286
288
|
low: 'Thinking: low',
|
|
287
289
|
medium: 'Thinking: medium',
|
|
288
290
|
high: 'Thinking: high',
|
|
@@ -483,6 +485,10 @@ function injectStyles() {
|
|
|
483
485
|
opacity: 1;
|
|
484
486
|
overflow: visible;
|
|
485
487
|
}
|
|
488
|
+
/* Windows: the shell is 92% opaque, so the blur behind it barely shows, yet Chromium recomputes it on every repaint
|
|
489
|
+
inside the panel (a transcript rendering, a stream). There it goes; the colour stays. */
|
|
490
|
+
html.platform-win32 .claude-panel,
|
|
491
|
+
html.desktop-titlebar--win32 .claude-panel { backdrop-filter: none; -webkit-backdrop-filter: none; }
|
|
486
492
|
/* Raise panel above floating terminal windows while a dropdown is open
|
|
487
493
|
so project/branch/recall menus aren't clipped behind them. */
|
|
488
494
|
.claude-panel:has(.cp-dropdown.open) { z-index: 99999; }
|
|
@@ -1768,8 +1774,8 @@ function injectStyles() {
|
|
|
1768
1774
|
pointer-events: auto;
|
|
1769
1775
|
width: 0; opacity: 0; overflow: hidden;
|
|
1770
1776
|
background: rgba(18, 18, 20, 0.92);
|
|
1771
|
-
backdrop-filter:
|
|
1772
|
-
-webkit-backdrop-filter:
|
|
1777
|
+
backdrop-filter: none;
|
|
1778
|
+
-webkit-backdrop-filter: none;
|
|
1773
1779
|
border: 0.5px solid rgba(255,255,255,0.06);
|
|
1774
1780
|
border-radius: 14px;
|
|
1775
1781
|
box-shadow:
|
|
@@ -1782,7 +1788,19 @@ function injectStyles() {
|
|
|
1782
1788
|
transition: width 0.22s cubic-bezier(0.2,0,0.2,1), opacity 0.18s;
|
|
1783
1789
|
max-height: 100%;
|
|
1784
1790
|
}
|
|
1785
|
-
.cp-todo-dock.is-open .cp-todo-drawer {
|
|
1791
|
+
.cp-todo-dock.is-open .cp-todo-drawer {
|
|
1792
|
+
width: 260px; opacity: 1;
|
|
1793
|
+
backdrop-filter: blur(60px) saturate(1.5);
|
|
1794
|
+
-webkit-backdrop-filter: blur(60px) saturate(1.5);
|
|
1795
|
+
}
|
|
1796
|
+
html.platform-win32 .cp-todo-tag,
|
|
1797
|
+
html.desktop-titlebar--win32 .cp-todo-tag,
|
|
1798
|
+
html.platform-win32 .cp-todo-dock.is-open .cp-todo-drawer,
|
|
1799
|
+
html.desktop-titlebar--win32 .cp-todo-dock.is-open .cp-todo-drawer {
|
|
1800
|
+
background: rgba(18, 18, 20, 0.96);
|
|
1801
|
+
backdrop-filter: none;
|
|
1802
|
+
-webkit-backdrop-filter: none;
|
|
1803
|
+
}
|
|
1786
1804
|
.cp-todo-dock.is-open .cp-todo-tag { display: none; }
|
|
1787
1805
|
|
|
1788
1806
|
.cp-todo-drawer .cp-todo-head {
|
|
@@ -2336,6 +2354,19 @@ function injectStyles() {
|
|
|
2336
2354
|
rgba(212,162,127,0.0) 100%
|
|
2337
2355
|
);
|
|
2338
2356
|
}
|
|
2357
|
+
html.platform-win32 .cp-session-pill.cp-pill-running,
|
|
2358
|
+
html.desktop-titlebar--win32 .cp-session-pill.cp-pill-running {
|
|
2359
|
+
border-color: rgba(212, 162, 127, 0.42);
|
|
2360
|
+
}
|
|
2361
|
+
html.platform-win32 .cp-session-pill.cp-pill-running:hover,
|
|
2362
|
+
html.desktop-titlebar--win32 .cp-session-pill.cp-pill-running:hover {
|
|
2363
|
+
border-color: rgba(212, 162, 127, 0.62);
|
|
2364
|
+
}
|
|
2365
|
+
html.platform-win32 .cp-session-pill.cp-pill-running::before,
|
|
2366
|
+
html.desktop-titlebar--win32 .cp-session-pill.cp-pill-running::before {
|
|
2367
|
+
animation: none;
|
|
2368
|
+
opacity: 0;
|
|
2369
|
+
}
|
|
2339
2370
|
.cp-session-pill .term-minimized-pill-icon { color: rgba(212, 162, 127, 0.45); transition: color 0.2s; }
|
|
2340
2371
|
.cp-session-pill.cp-pill-running .term-minimized-pill-icon { color: rgba(212, 162, 127, 1); }
|
|
2341
2372
|
.cp-session-pill:hover .term-minimized-pill-icon { color: rgba(212, 162, 127, 0.85); }
|
|
@@ -2600,7 +2631,7 @@ function injectStyles() {
|
|
|
2600
2631
|
border: 0.5px solid rgba(255,255,255,0.05);
|
|
2601
2632
|
border-radius: 6px;
|
|
2602
2633
|
font-size: 11px; color: rgba(255,255,255,0.7);
|
|
2603
|
-
cursor:
|
|
2634
|
+
cursor: move;
|
|
2604
2635
|
transition: background 0.15s, border-color 0.15s;
|
|
2605
2636
|
}
|
|
2606
2637
|
.cp-queue-item:hover {
|
|
@@ -2614,7 +2645,7 @@ function injectStyles() {
|
|
|
2614
2645
|
background: rgba(120,180,255,0.08);
|
|
2615
2646
|
}
|
|
2616
2647
|
.cp-queue-drag {
|
|
2617
|
-
color: rgba(255,255,255,0.2); cursor:
|
|
2648
|
+
color: rgba(255,255,255,0.2); cursor: move;
|
|
2618
2649
|
font-size: 10px; user-select: none; flex-shrink: 0;
|
|
2619
2650
|
}
|
|
2620
2651
|
.cp-queue-text {
|
|
@@ -2802,6 +2833,13 @@ function _effortLevelsForModel() {
|
|
|
2802
2833
|
return ['off', ...advertised.filter(id => id !== 'off')];
|
|
2803
2834
|
}
|
|
2804
2835
|
|
|
2836
|
+
// Whether the tab's model (the selector's, for the active tab) has effort levels.
|
|
2837
|
+
function _modelSupportsEffort(tab) {
|
|
2838
|
+
if (tab === activeTab()) return _effortLevelsForModel().length > 1;
|
|
2839
|
+
const model = tab?.model ? _models.find(m => m.id === tab.model) : null;
|
|
2840
|
+
return !Array.isArray(model?.effortLevels) || model.effortLevels.some(id => id !== 'off');
|
|
2841
|
+
}
|
|
2842
|
+
|
|
2805
2843
|
// Some models have no thinking at all (Haiku). Disable the toggle and force 'off'
|
|
2806
2844
|
// rather than passing a --effort the CLI will ignore.
|
|
2807
2845
|
function _syncThinkAvailability() {
|
|
@@ -2922,7 +2960,7 @@ function newTabState(sessionId = null, label = 'New chat', id = null) {
|
|
|
2922
2960
|
};
|
|
2923
2961
|
}
|
|
2924
2962
|
|
|
2925
|
-
function createTab(sessionId = null, label = 'New chat', { autoSwitch = true, id = null } = {}) {
|
|
2963
|
+
function createTab(sessionId = null, label = 'New chat', { autoSwitch = true, id = null, deferHistory = false } = {}) {
|
|
2926
2964
|
if (_tabs.length >= MAX_TABS) return null;
|
|
2927
2965
|
const tab = newTabState(sessionId, label, id);
|
|
2928
2966
|
// Create messages div — kept DETACHED until the tab activates. Inactive
|
|
@@ -2937,14 +2975,17 @@ function createTab(sessionId = null, label = 'New chat', { autoSwitch = true, id
|
|
|
2937
2975
|
msgDiv.innerHTML = `<div class="cp-empty"><div class="cp-empty-logo">${CLAUDE_ICON}</div><span class="cp-empty-name">Claude</span><span class="cp-empty-hint">Send a message to start</span></div>`;
|
|
2938
2976
|
tab.messagesEl = msgDiv;
|
|
2939
2977
|
tab.scrollController = createStickyScrollController(msgDiv, { active: false });
|
|
2940
|
-
// Connect WebSocket
|
|
2978
|
+
// Connect WebSocket (every tab, active or not: a restored tab reattaches to the background agents,
|
|
2979
|
+
// shells and wakeups its session kept on the server).
|
|
2941
2980
|
connectTab(tab);
|
|
2942
2981
|
// Create pill (rendered in shared tray, not inside panel)
|
|
2943
2982
|
tab.pillEl = _createTrayPill(tab);
|
|
2944
2983
|
_paintTemporary(tab);
|
|
2945
2984
|
_tabs.push(tab);
|
|
2946
2985
|
if (autoSwitch) switchTab(_tabs.length - 1);
|
|
2947
|
-
|
|
2986
|
+
// A restored background tab loads its transcript when it is first shown (switchTab), not all at once at panel open.
|
|
2987
|
+
if (sessionId && deferHistory) tab._historyDeferred = sessionId;
|
|
2988
|
+
if (sessionId && !deferHistory) loadSessionHistory(sessionId, tab.messagesEl);
|
|
2948
2989
|
renderPills();
|
|
2949
2990
|
if (autoSwitch) saveTabs();
|
|
2950
2991
|
return tab;
|
|
@@ -3095,7 +3136,9 @@ function switchTab(idx) {
|
|
|
3095
3136
|
const items = _models.map(m => ({ value: m.id, label: m.label }));
|
|
3096
3137
|
const modelVal = _resolveModelValue(items, tab.model || _getDefaultModel());
|
|
3097
3138
|
ddPopulateModels($model, items, modelVal);
|
|
3098
|
-
|
|
3139
|
+
// The unverified fallback list (the CLI not asked yet: /api/claude/config answers at once) never
|
|
3140
|
+
// rewrites a tab's model; refreshModels() puts the real list in and settles it.
|
|
3141
|
+
if (modelVal && modelVal !== tab.model && _modelsSource !== 'fallback') { tab.model = modelVal; saveTabs(); }
|
|
3099
3142
|
}
|
|
3100
3143
|
if ($think && tab.effort) _setEffort($think, tab.effort);
|
|
3101
3144
|
_syncThinkAvailability();
|
|
@@ -3117,6 +3160,10 @@ function switchTab(idx) {
|
|
|
3117
3160
|
populateModeDropdown(_panel?.querySelector('#cp-mode'), tab);
|
|
3118
3161
|
_renderAccountMenu();
|
|
3119
3162
|
_paintTemporary(tab);
|
|
3163
|
+
if (tab._historyDeferred && tab._historyDeferred === tab.sessionId && !tab.automationRunId) {
|
|
3164
|
+
tab._historyDeferred = false;
|
|
3165
|
+
loadSessionHistory(tab.sessionId, tab.messagesEl);
|
|
3166
|
+
}
|
|
3120
3167
|
saveTabs();
|
|
3121
3168
|
}
|
|
3122
3169
|
|
|
@@ -3414,8 +3461,23 @@ function _scrubStaleTabState(key) {
|
|
|
3414
3461
|
}
|
|
3415
3462
|
}
|
|
3416
3463
|
|
|
3464
|
+
// A restored tab that was working (a turn, a question, background agents or shells) can get live rows
|
|
3465
|
+
// as soon as its socket reattaches: its transcript loads at once, ahead of them. An idle one waits until
|
|
3466
|
+
// it is shown (switchTab), so opening the panel does not fetch and render every tab's transcript.
|
|
3467
|
+
function _loadHistoryIfWorking(tab, saved) {
|
|
3468
|
+
if (!tab._historyDeferred || tab._historyDeferred !== tab.sessionId) return;
|
|
3469
|
+
if (!(saved?.running || saved?.needsYou || Number(saved?.backgroundWork) > 0)) return;
|
|
3470
|
+
tab._historyDeferred = false;
|
|
3471
|
+
loadSessionHistory(tab.sessionId, tab.messagesEl);
|
|
3472
|
+
}
|
|
3473
|
+
|
|
3417
3474
|
function restoreTabs() {
|
|
3418
3475
|
_cleanStaleWindows();
|
|
3476
|
+
const pickRestoredTabIdx = (activeIdx) => {
|
|
3477
|
+
const pendingId = globalThis.__synabunPendingTab?.provider === 'claude' ? globalThis.__synabunPendingTab.tabId : '';
|
|
3478
|
+
const pendingIdx = pendingId ? _tabs.findIndex(t => t.id === pendingId || t.sessionId === pendingId) : -1;
|
|
3479
|
+
return pendingIdx >= 0 ? pendingIdx : Math.min(activeIdx || 0, _tabs.length - 1);
|
|
3480
|
+
};
|
|
3419
3481
|
// Try window-scoped tabs first
|
|
3420
3482
|
try {
|
|
3421
3483
|
const raw = storage.getItem(STOR.tabs);
|
|
@@ -3424,7 +3486,7 @@ function restoreTabs() {
|
|
|
3424
3486
|
if (data.tabs?.length) {
|
|
3425
3487
|
for (const saved of data.tabs) {
|
|
3426
3488
|
if (saved.automationActive && saved.automationOwnerId !== nativeLoopWindowId) continue;
|
|
3427
|
-
const t = createTab(saved.automationRunId ? null : saved.sessionId, saved.label, { autoSwitch: false, id: saved.id });
|
|
3489
|
+
const t = createTab(saved.automationRunId ? null : saved.sessionId, saved.label, { autoSwitch: false, id: saved.id, deferHistory: true });
|
|
3428
3490
|
if (t && saved.automationRunId) t.sessionId = saved.sessionId || null;
|
|
3429
3491
|
if (t && saved.sessionCost) t.sessionCost = saved.sessionCost;
|
|
3430
3492
|
if (t && saved.running && !saved.automationRunId) t._wasRunning = true; // trigger reattach on WS open
|
|
@@ -3448,9 +3510,10 @@ function restoreTabs() {
|
|
|
3448
3510
|
if (t && saved.automationRunId) t.automationActive = !!saved.automationActive;
|
|
3449
3511
|
if (t && saved.automationRunId) t.automationOwnerId = saved.automationOwnerId || null;
|
|
3450
3512
|
if (t && saved.releasedRunId && !saved.automationRunId) t.releasedRunId = saved.releasedRunId;
|
|
3513
|
+
if (t) _loadHistoryIfWorking(t, saved);
|
|
3451
3514
|
}
|
|
3452
3515
|
if (_tabs.length) {
|
|
3453
|
-
switchTab(
|
|
3516
|
+
switchTab(pickRestoredTabIdx(data.activeIdx));
|
|
3454
3517
|
return;
|
|
3455
3518
|
}
|
|
3456
3519
|
}
|
|
@@ -3464,7 +3527,7 @@ function restoreTabs() {
|
|
|
3464
3527
|
if (data.tabs?.length) {
|
|
3465
3528
|
for (const saved of data.tabs) {
|
|
3466
3529
|
if (saved.automationActive && saved.automationOwnerId !== nativeLoopWindowId) continue;
|
|
3467
|
-
const t = createTab(saved.automationRunId ? null : saved.sessionId, saved.label, { autoSwitch: false, id: saved.id });
|
|
3530
|
+
const t = createTab(saved.automationRunId ? null : saved.sessionId, saved.label, { autoSwitch: false, id: saved.id, deferHistory: true });
|
|
3468
3531
|
if (t && saved.automationRunId) t.sessionId = saved.sessionId || null;
|
|
3469
3532
|
if (t && saved.sessionCost) t.sessionCost = saved.sessionCost;
|
|
3470
3533
|
if (t && saved.running && !saved.automationRunId) t._wasRunning = true;
|
|
@@ -3475,9 +3538,10 @@ function restoreTabs() {
|
|
|
3475
3538
|
if (t && saved.automationRunId) t.automationRunId = saved.automationRunId;
|
|
3476
3539
|
if (t && saved.automationRunId) t.automationActive = !!saved.automationActive;
|
|
3477
3540
|
if (t && saved.automationRunId) t.automationOwnerId = saved.automationOwnerId || null;
|
|
3541
|
+
if (t) _loadHistoryIfWorking(t, saved);
|
|
3478
3542
|
}
|
|
3479
3543
|
if (_tabs.length) {
|
|
3480
|
-
switchTab(
|
|
3544
|
+
switchTab(pickRestoredTabIdx(data.activeIdx));
|
|
3481
3545
|
// Don't remove legacy key — other windows may still need it during rollout
|
|
3482
3546
|
return;
|
|
3483
3547
|
}
|
|
@@ -4512,6 +4576,8 @@ function writeSessionSnapshot(tab) {
|
|
|
4512
4576
|
const sid = tab?.sessionId || null;
|
|
4513
4577
|
const $msgs = tab?.messagesEl || null;
|
|
4514
4578
|
if (!sid || !$msgs) return;
|
|
4579
|
+
// Not loaded yet (a restored tab not shown so far), or half rebuilt: what is on screen is not the transcript.
|
|
4580
|
+
if (tab._historyDeferred || tab._historyRendering || tab._historyHold) return;
|
|
4515
4581
|
const html = providerAuthSnapshot($msgs);
|
|
4516
4582
|
if (!html.trim()) return;
|
|
4517
4583
|
// Skip snapshot if the transcript only contains the empty-state placeholder
|
|
@@ -4686,9 +4752,14 @@ function _renderHistoryRow(tab, $msgs, m) {
|
|
|
4686
4752
|
if (typeof t === 'object' && t.name) {
|
|
4687
4753
|
// A question or a plan that was already answered: a record of it, not
|
|
4688
4754
|
// the interactive card (and not a JSON dump).
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
else
|
|
4755
|
+
let card;
|
|
4756
|
+
if (t.name === 'AskUserQuestion') card = buildHistoryAskCard(t);
|
|
4757
|
+
else if (t.name === 'ExitPlanMode') card = buildHistoryPlanCard(t);
|
|
4758
|
+
else card = buildTool(t, tab);
|
|
4759
|
+
if (card) {
|
|
4760
|
+
if (t.id && $msgs._replayCards instanceof Map) $msgs._replayCards.set(String(t.id), card);
|
|
4761
|
+
wrap.appendChild(card);
|
|
4762
|
+
}
|
|
4692
4763
|
} else {
|
|
4693
4764
|
// Legacy: tool name string only
|
|
4694
4765
|
const tName = String(t);
|
|
@@ -4704,20 +4775,33 @@ function _renderHistoryRow(tab, $msgs, m) {
|
|
|
4704
4775
|
}
|
|
4705
4776
|
}
|
|
4706
4777
|
el.appendChild(wrap); $msgs.appendChild(el);
|
|
4778
|
+
// Live results that arrived for these cards while the replay had not built them.
|
|
4779
|
+
if (live && tab._pendingResults instanceof Map && tab._pendingResults.size) {
|
|
4780
|
+
for (const t of m.tools || []) {
|
|
4781
|
+
const ev = t?.id ? takePendingResult(tab, t.id) : null;
|
|
4782
|
+
if (ev) { try { updateToolResult(tab, ev); } catch {} }
|
|
4783
|
+
}
|
|
4784
|
+
}
|
|
4707
4785
|
return;
|
|
4708
4786
|
}
|
|
4709
4787
|
if (m.role === 'tool_result' && m.toolUseId) {
|
|
4710
4788
|
if (fillHistoryCard($msgs, m)) return;
|
|
4789
|
+
const indexedCard = $msgs._replayCards instanceof Map ? $msgs._replayCards.get(String(m.toolUseId)) : null;
|
|
4711
4790
|
if (live) {
|
|
4712
|
-
|
|
4791
|
+
// Marked as a replayed result: it is not kept as pending, and its todos are already in the precomputed list.
|
|
4792
|
+
tab._replayRow = true;
|
|
4793
|
+
try { updateToolResult(tab, { type: 'tool_result', tool_use_id: m.toolUseId, content: m.text || '', is_error: !!m.isError, tool_use_result: m.structured }); }
|
|
4794
|
+
finally { tab._replayRow = false; }
|
|
4713
4795
|
// A subagent of a past session: its own transcript loads when the card is opened.
|
|
4714
4796
|
const agentId = m.structured?.agentId;
|
|
4715
|
-
const agentCard = agentId && sessionActionsAvailable(tab)
|
|
4797
|
+
const agentCard = agentId && sessionActionsAvailable(tab)
|
|
4798
|
+
? ((indexedCard?.classList?.contains('cp-agent-card') ? indexedCard : null) || $msgs.querySelector(`.cp-agent-card[data-tool-id="${CSS.escape(m.toolUseId)}"]`))
|
|
4799
|
+
: null;
|
|
4716
4800
|
if (agentCard) _wireSubagentTranscript(tab, agentCard, String(agentId));
|
|
4717
4801
|
return;
|
|
4718
4802
|
}
|
|
4719
4803
|
// No tab behind this container: plain text into the card.
|
|
4720
|
-
const card = $msgs.querySelector(`.tool-card[data-tool-id="${CSS.escape(m.toolUseId)}"]`);
|
|
4804
|
+
const card = (indexedCard?.matches?.('.tool-card') ? indexedCard : null) || $msgs.querySelector(`.tool-card[data-tool-id="${CSS.escape(m.toolUseId)}"]`);
|
|
4721
4805
|
const rLbl = card?.querySelector('.tool-result-label');
|
|
4722
4806
|
const rSec = card?.querySelector('.tool-result-content');
|
|
4723
4807
|
if (rSec && m.text) {
|
|
@@ -4822,12 +4906,19 @@ function _addHistoryPager(tab, $msgs, sid, project, data) {
|
|
|
4822
4906
|
// Render at the end (the live renderers append), then move the block up.
|
|
4823
4907
|
const tail = $msgs.lastElementChild;
|
|
4824
4908
|
tab._replaying = (tab._replaying || 0) + 1;
|
|
4909
|
+
const replayCards = new Map();
|
|
4910
|
+
$msgs._replayCards = replayCards;
|
|
4825
4911
|
try { for (const m of page.messages) _renderHistoryRow(tab, $msgs, m); }
|
|
4826
|
-
finally {
|
|
4912
|
+
finally {
|
|
4913
|
+
if ($msgs._replayCards === replayCards) delete $msgs._replayCards;
|
|
4914
|
+
tab._replaying = Math.max(0, (tab._replaying || 1) - 1);
|
|
4915
|
+
}
|
|
4827
4916
|
const added = [];
|
|
4828
4917
|
for (let n = tail?.nextElementSibling; n; n = n.nextElementSibling) added.push(n);
|
|
4918
|
+
markHistoryRows(added, 'earlier'); // history: a later rebuild replaces it
|
|
4829
4919
|
const anchor = note.nextElementSibling;
|
|
4830
4920
|
for (const n of added) $msgs.insertBefore(n, anchor);
|
|
4921
|
+
try { collapseAdjacentMcpTools($msgs); } catch {}
|
|
4831
4922
|
try { settleReplayedCards($msgs, tab); } catch {}
|
|
4832
4923
|
// What the user asked to see must survive the next prune.
|
|
4833
4924
|
$msgs._pruneCap = $msgs.childElementCount + MAX_MSG_CHILDREN;
|
|
@@ -4860,20 +4951,42 @@ function _dropSessionSnapshot(sid) {
|
|
|
4860
4951
|
try { delete _sessionSnapshots[sid]; deleteBlob('claude-snapshots', sid); } catch {}
|
|
4861
4952
|
}
|
|
4862
4953
|
|
|
4863
|
-
|
|
4954
|
+
// Loads of one container run one at a time, the newest asked for wins (queueHistoryLoad, cp/cp-restore.js).
|
|
4955
|
+
// The tab that owns the container is taken once, here: per-tab state (todos, usage, the snapshot) never goes
|
|
4956
|
+
// to another tab, and a tab closed meanwhile stops the load. While any load of a tab runs, its live
|
|
4957
|
+
// transcript messages wait in its buffer (historyGate in handleTabMsg) and play after the history.
|
|
4958
|
+
function loadSessionHistory(sid, $msgs) {
|
|
4864
4959
|
if (!$msgs) $msgs = activeTab()?.messagesEl;
|
|
4865
|
-
if (!$msgs) return;
|
|
4960
|
+
if (!$msgs) return Promise.resolve();
|
|
4961
|
+
const ownerTab = _tabs.find(t => t.messagesEl === $msgs) || null;
|
|
4962
|
+
if (ownerTab && ownerTab._historyDeferred === sid) ownerTab._historyDeferred = false;
|
|
4963
|
+
if (ownerTab) ownerTab._historyHold = (ownerTab._historyHold || 0) + 1;
|
|
4964
|
+
const job = queueHistoryLoad($msgs, (isStale, ticket) => {
|
|
4965
|
+
const stale = () => isStale() || !!(ownerTab && (ownerTab.closed || ownerTab.messagesEl !== $msgs));
|
|
4966
|
+
if (stale()) return;
|
|
4967
|
+
return _loadSessionHistoryNow(sid, $msgs, ownerTab, stale, ticket);
|
|
4968
|
+
});
|
|
4969
|
+
return job.finally(() => {
|
|
4970
|
+
if (!ownerTab) return;
|
|
4971
|
+
ownerTab._historyHold = Math.max(0, (ownerTab._historyHold || 1) - 1);
|
|
4972
|
+
if (!ownerTab._historyHold && ownerTab._msgBuffer?.length && !ownerTab.closed) _flushMsgBuffer(ownerTab);
|
|
4973
|
+
});
|
|
4974
|
+
}
|
|
4975
|
+
|
|
4976
|
+
async function _loadSessionHistoryNow(sid, $msgs, ownerTab, stale, ticket) {
|
|
4866
4977
|
// Try local snapshot first — exact replay of the live render, lossless.
|
|
4867
4978
|
// Snapshot hydration is async (blob store); wait for it so a fresh page
|
|
4868
4979
|
// load doesn't miss its own snapshots and rebuild from JSONL needlessly.
|
|
4869
4980
|
try { await _snapshotsReady; } catch {}
|
|
4981
|
+
if (stale()) return;
|
|
4870
4982
|
const snap = getSessionSnapshot(sid);
|
|
4871
4983
|
let restored = null; // the rows the snapshot put back, when a rebuild follows it
|
|
4872
4984
|
if (snap && snap.html) {
|
|
4873
|
-
const tab =
|
|
4985
|
+
const tab = ownerTab;
|
|
4874
4986
|
$msgs._historySid = sid; // the session this transcript shows (a restored pager loads its earlier pages)
|
|
4875
4987
|
if (renderStoredSession(snap, $msgs, tab)) {
|
|
4876
4988
|
restored = [...$msgs.children];
|
|
4989
|
+
markHistoryRows(restored, ticket); // the next rebuild replaces them
|
|
4877
4990
|
scrollEnd();
|
|
4878
4991
|
// Background refresh: pull latest JSONL in case the session continued in
|
|
4879
4992
|
// another window, or was rewound there. The probe reads what the owning
|
|
@@ -4889,6 +5002,7 @@ async function loadSessionHistory(sid, $msgs) {
|
|
|
4889
5002
|
if (tab?.accountId) params.set('account', tab.accountId);
|
|
4890
5003
|
const probe = await fetch(`/api/claude-code/sessions/${encodeURIComponent(sid)}/messages?${params}`);
|
|
4891
5004
|
const probeData = await probe.json();
|
|
5005
|
+
if (stale()) return;
|
|
4892
5006
|
// `visible` counts prompts and replies only (a server that predates it sends `total`).
|
|
4893
5007
|
if ((probeData?.visible ?? probeData?.total ?? 0) > (snap.itemCount || 0) + 2) {
|
|
4894
5008
|
// Upstream has materially more content — fall through to full rebuild
|
|
@@ -4904,8 +5018,8 @@ async function loadSessionHistory(sid, $msgs) {
|
|
|
4904
5018
|
} catch { return; }
|
|
4905
5019
|
}
|
|
4906
5020
|
}
|
|
4907
|
-
const accountTab =
|
|
4908
|
-
let project = _historyProject(
|
|
5021
|
+
const accountTab = ownerTab;
|
|
5022
|
+
let project = _historyProject(ownerTab || activeTab()) || undefined;
|
|
4909
5023
|
const readHistory = async (from) => {
|
|
4910
5024
|
const params = new URLSearchParams({ limit: '500' });
|
|
4911
5025
|
if (from) params.set('project', from);
|
|
@@ -4916,6 +5030,7 @@ async function loadSessionHistory(sid, $msgs) {
|
|
|
4916
5030
|
};
|
|
4917
5031
|
try {
|
|
4918
5032
|
let data = await readHistory(project);
|
|
5033
|
+
if (stale()) return;
|
|
4919
5034
|
// The tab's Claude account was removed in Settings: say so. Its transcripts
|
|
4920
5035
|
// are not looked for under the default account (another identity's folder).
|
|
4921
5036
|
if (data.code === 'account_unavailable') {
|
|
@@ -4932,6 +5047,7 @@ async function loadSessionHistory(sid, $msgs) {
|
|
|
4932
5047
|
if (historyOutcome(data) === 'not_in_project') {
|
|
4933
5048
|
const owner = await _transcriptOwner(sid, project, accountTab?.accountId || '');
|
|
4934
5049
|
const moved = owner ? await readHistory(owner) : null;
|
|
5050
|
+
if (stale()) return;
|
|
4935
5051
|
if (moved && historyOutcome(moved) !== 'not_in_project' && historyOutcome(moved) !== 'not_found' && historyOutcome(moved) !== 'refused') {
|
|
4936
5052
|
data = moved;
|
|
4937
5053
|
project = owner;
|
|
@@ -4963,29 +5079,66 @@ async function loadSessionHistory(sid, $msgs) {
|
|
|
4963
5079
|
return;
|
|
4964
5080
|
}
|
|
4965
5081
|
// Chunked rebuild: rendering 500 messages in one task froze the UI during
|
|
4966
|
-
// cold restore / orphan resync.
|
|
4967
|
-
//
|
|
4968
|
-
//
|
|
4969
|
-
|
|
4970
|
-
const
|
|
4971
|
-
// The rebuild replaces the snapshot that was put back above (only those
|
|
4972
|
-
// rows: what a live turn appended meanwhile stays).
|
|
5082
|
+
// cold restore / orphan resync. A newer load of this container (reattach resync,
|
|
5083
|
+
// in-tab session switch) or the tab closing stops this one at its next yield.
|
|
5084
|
+
// What an earlier rebuild of this container left (finished, stopped half way, or
|
|
5085
|
+
// the snapshot put back above) is taken out: never a second copy after it.
|
|
5086
|
+
for (const node of earlierHistoryRows($msgs.children, ticket)) node.remove();
|
|
4973
5087
|
if (restored) for (const node of restored) node.remove();
|
|
5088
|
+
// Rows that came live before the load (the history goes before them: it is older).
|
|
5089
|
+
const live = liveRows($msgs.children);
|
|
5090
|
+
const liveAnchor = live[0] || null;
|
|
5091
|
+
const liveSet = new Set(live);
|
|
5092
|
+
const { head, tail } = !restored ? splitHistoryTail(data.messages, 40) : { head: [], tail: data.messages };
|
|
5093
|
+
// Renders rows at the end, marks them as this load's, and moves them before `before`.
|
|
5094
|
+
const renderRows = (rows, before) => renderHistoryRowsInto($msgs, rows, (m) => _renderHistoryRow(ownerTab, $msgs, m), { before, ticket, skip: liveSet });
|
|
4974
5095
|
// Replay goes through the live renderers (tool cards, typed results), marked
|
|
4975
5096
|
// so it leaves no activity behind: no hook-strip entries, no statusline verb.
|
|
4976
5097
|
if (ownerTab) ownerTab._replaying = (ownerTab._replaying || 0) + 1;
|
|
5098
|
+
if (ownerTab) ownerTab._historyRendering = (ownerTab._historyRendering || 0) + 1;
|
|
5099
|
+
if (ownerTab && head.length) {
|
|
5100
|
+
const precomputedTodos = replayTodosFromMessages(data.messages, ownerTab.todos);
|
|
5101
|
+
if (precomputedTodos) ownerTab.todos = precomputedTodos;
|
|
5102
|
+
ownerTab._skipReplayTodos = true;
|
|
5103
|
+
}
|
|
5104
|
+
const replayCards = new Map();
|
|
5105
|
+
$msgs._replayCards = replayCards;
|
|
4977
5106
|
try {
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
5107
|
+
if (head.length) {
|
|
5108
|
+
const tailNodes = renderRows(tail, liveAnchor);
|
|
5109
|
+
const firstTailNode = tailNodes[0] || liveAnchor;
|
|
5110
|
+
scrollEnd();
|
|
5111
|
+
const CHUNK = 50;
|
|
5112
|
+
for (let offset = 0; offset < head.length; offset += CHUNK) {
|
|
4981
5113
|
await new Promise(r => setTimeout(r, 0));
|
|
4982
|
-
if (
|
|
5114
|
+
if (stale()) return;
|
|
5115
|
+
renderRows(head.slice(offset, offset + CHUNK), firstTailNode);
|
|
5116
|
+
// Following the bottom: stay there. Scrolled up: the browser's scroll anchoring keeps the rows in view.
|
|
5117
|
+
if (ownerTab === activeTab()) scrollEnd();
|
|
5118
|
+
}
|
|
5119
|
+
} else {
|
|
5120
|
+
const CHUNK = 40;
|
|
5121
|
+
for (let offset = 0; offset < data.messages.length; offset += CHUNK) {
|
|
5122
|
+
if (offset) {
|
|
5123
|
+
await new Promise(r => setTimeout(r, 0));
|
|
5124
|
+
if (stale()) return;
|
|
5125
|
+
}
|
|
5126
|
+
renderRows(data.messages.slice(offset, offset + CHUNK), liveAnchor);
|
|
4983
5127
|
}
|
|
4984
|
-
_renderHistoryRow(ownerTab, $msgs, m);
|
|
4985
5128
|
}
|
|
4986
5129
|
} finally {
|
|
4987
|
-
if (
|
|
5130
|
+
if ($msgs._replayCards === replayCards) delete $msgs._replayCards;
|
|
5131
|
+
if (ownerTab) {
|
|
5132
|
+
delete ownerTab._skipReplayTodos;
|
|
5133
|
+
ownerTab._historyRendering = Math.max(0, (ownerTab._historyRendering || 1) - 1);
|
|
5134
|
+
ownerTab._replaying = Math.max(0, (ownerTab._replaying || 1) - 1);
|
|
5135
|
+
// Live results kept for cards this page never built (cut by the page) are dropped.
|
|
5136
|
+
if (!ownerTab._historyRendering) ownerTab._pendingResults = null;
|
|
5137
|
+
}
|
|
4988
5138
|
}
|
|
5139
|
+
try { collapseAdjacentMcpTools($msgs); } catch {}
|
|
5140
|
+
// Always for the tab on screen: a list the page emptied must clear the dock too.
|
|
5141
|
+
if (ownerTab && ownerTab === activeTab()) { try { renderTodoWidget(ownerTab); } catch {} }
|
|
4989
5142
|
// Calls whose result is not in this page (interrupted, or cut by the page) stop looking busy.
|
|
4990
5143
|
try { settleReplayedCards($msgs, ownerTab); } catch {}
|
|
4991
5144
|
pruneMessages($msgs);
|
|
@@ -5001,6 +5154,8 @@ async function loadSessionHistory(sid, $msgs) {
|
|
|
5001
5154
|
$msgs.appendChild(note);
|
|
5002
5155
|
}
|
|
5003
5156
|
if (ownerTab) ownerTab._historyResults = historyHasResultSupport(data);
|
|
5157
|
+
// The pager and the notes are this load's too (a later rebuild replaces them).
|
|
5158
|
+
markHistoryRows([...$msgs.children].filter(n => !liveSet.has(n) && n[HISTORY_ROW_KEY] == null), ticket);
|
|
5004
5159
|
// Populate context gauge from session history usage
|
|
5005
5160
|
const tab = ownerTab;
|
|
5006
5161
|
if (tab && data.usage) {
|
|
@@ -5013,10 +5168,10 @@ async function loadSessionHistory(sid, $msgs) {
|
|
|
5013
5168
|
renderGauge(tab);
|
|
5014
5169
|
}
|
|
5015
5170
|
scrollEnd();
|
|
5016
|
-
// Cache the rebuilt transcript so
|
|
5017
|
-
|
|
5018
|
-
if (tab && tab.sessionId === sid) writeSessionSnapshot(tab);
|
|
5171
|
+
// Cache the rebuilt transcript (debounced so DOM serialization never blocks session open).
|
|
5172
|
+
if (tab && tab.sessionId === sid) scheduleSessionSnapshotSave(tab);
|
|
5019
5173
|
} catch {
|
|
5174
|
+
if (stale()) return;
|
|
5020
5175
|
$msgs.innerHTML = '<div class="msg-status">Failed to load history</div>';
|
|
5021
5176
|
}
|
|
5022
5177
|
}
|
|
@@ -5270,6 +5425,14 @@ function handleTabMsg(tab, msg) {
|
|
|
5270
5425
|
// An MCP server's elicitation_complete resolves the URL card that is waiting
|
|
5271
5426
|
// (bypassesPromptBuffer in cp/cp-events.js lists what passes).
|
|
5272
5427
|
const _bufferBypass = bypassesPromptBuffer(msg);
|
|
5428
|
+
// A restored tab whose history is not loaded yet gets a live row (a wakeup, a background turn): its
|
|
5429
|
+
// history loads first and the message waits for it; any running history load holds them the same way.
|
|
5430
|
+
const gate = historyGate(tab, msg, _bufferBypass);
|
|
5431
|
+
if (gate === 'load') { tab._historyDeferred = false; loadSessionHistory(tab.sessionId, tab.messagesEl); }
|
|
5432
|
+
if (gate !== 'pass') {
|
|
5433
|
+
if (tab._msgBuffer.length < 500) tab._msgBuffer.push(msg);
|
|
5434
|
+
return;
|
|
5435
|
+
}
|
|
5273
5436
|
// Also buffer while a chunked drain is in progress (or older messages still
|
|
5274
5437
|
// queue) — without this, live events overtake buffered ones between slices.
|
|
5275
5438
|
if ((tab._activePerm || tab.pendingAskRequestId || tab._draining || tab._msgBuffer.length) && !_bufferBypass) {
|
|
@@ -5295,10 +5458,11 @@ function _flushMsgBuffer(tab) {
|
|
|
5295
5458
|
while (tab._msgBuffer.length && n++ < budget) {
|
|
5296
5459
|
// A drained message can re-arm a permission/ask prompt — stop and let
|
|
5297
5460
|
// that flow's resolution resume the drain (its handlers call us again).
|
|
5298
|
-
if (tab._activePerm || tab.pendingAskRequestId) break;
|
|
5461
|
+
if (tab._activePerm || tab.pendingAskRequestId || tab._historyHold) break;
|
|
5299
5462
|
_processTabMsg(tab, tab._msgBuffer.shift());
|
|
5300
5463
|
}
|
|
5301
|
-
|
|
5464
|
+
// A history load holds the rest: it drains them when it is done.
|
|
5465
|
+
if (tab._msgBuffer.length && !tab._activePerm && !tab.pendingAskRequestId && !tab._historyHold) {
|
|
5302
5466
|
setTimeout(step, 0);
|
|
5303
5467
|
} else {
|
|
5304
5468
|
tab._draining = false;
|
|
@@ -5413,6 +5577,11 @@ function _processTabMsg(tab, msg) {
|
|
|
5413
5577
|
_sessionSaysMode(tab, msg.mode, 'reattach', msg);
|
|
5414
5578
|
// Orphan buffer overflowed while detached — rebuild transcript from JSONL
|
|
5415
5579
|
if (msg.resynced && tab.sessionId) {
|
|
5580
|
+
tab._historyDeferred = false;
|
|
5581
|
+
try { loadSessionHistory(tab.sessionId, tab.messagesEl); } catch {}
|
|
5582
|
+
} else if (tab._historyDeferred && tab._historyDeferred === tab.sessionId) {
|
|
5583
|
+
// A restored tab not shown yet whose session is still live on the server: its history first.
|
|
5584
|
+
tab._historyDeferred = false;
|
|
5416
5585
|
try { loadSessionHistory(tab.sessionId, tab.messagesEl); } catch {}
|
|
5417
5586
|
}
|
|
5418
5587
|
if (msg.running) {
|
|
@@ -5442,7 +5611,8 @@ function _processTabMsg(tab, msg) {
|
|
|
5442
5611
|
if (expectRunning && !(tab.sendStartedAt > tab._reattachSentAt)) {
|
|
5443
5612
|
console.log('[claude-panel] No orphan to reattach — the turn ended while disconnected');
|
|
5444
5613
|
finishTab(tab, true);
|
|
5445
|
-
|
|
5614
|
+
// A dispatched worker's session says what became of its run (resumed, or how it ended), not only this.
|
|
5615
|
+
_lostTurnLine(tab).then((line) => { if (!tab.closed) appendStatus(tab, line); });
|
|
5446
5616
|
}
|
|
5447
5617
|
// Prompts queued behind a Compact when the socket closed: nothing says it finished.
|
|
5448
5618
|
if (tab._queueWaits === 'session') _compactQueue.after(tab, 'lost');
|
|
@@ -6687,6 +6857,8 @@ function renderAssistant(tab, msg) {
|
|
|
6687
6857
|
|
|
6688
6858
|
/** Build an interactive AskUserQuestion card from a tool_use block */
|
|
6689
6859
|
function buildAskFromToolUse(tab, block) {
|
|
6860
|
+
// A task worker’s broker owns the interactive card, even if this tool event arrives first.
|
|
6861
|
+
if (tab.automationRunId) { const placeholder = document.createElement('div'); placeholder.hidden = true; return placeholder; }
|
|
6690
6862
|
const input = block.input || {};
|
|
6691
6863
|
const toolUseId = block.id || '';
|
|
6692
6864
|
tab.pendingAskToolUseId = toolUseId;
|
|
@@ -6878,7 +7050,7 @@ function buildAskFromToolUse(tab, block) {
|
|
|
6878
7050
|
// Submit button — sends all answers as a batch
|
|
6879
7051
|
submitBtn.addEventListener('click', () => {
|
|
6880
7052
|
// An answer is shown as given only once it can be sent: until then the card stays as it is.
|
|
6881
|
-
if (tab.ws?.readyState !== WebSocket.OPEN) { appendStatus(tab, ASK_ANSWER_UNSENT); return; }
|
|
7053
|
+
if (!tab.automationRunId && tab.ws?.readyState !== WebSocket.OPEN) { appendStatus(tab, ASK_ANSWER_UNSENT); return; }
|
|
6882
7054
|
container.querySelectorAll('.ask-option').forEach(b => { b.disabled = true; });
|
|
6883
7055
|
container.querySelectorAll('.ask-text-input, .ask-notes').forEach(i => { i.disabled = true; });
|
|
6884
7056
|
submitBtn.disabled = true;
|
|
@@ -6896,6 +7068,21 @@ function buildAskFromToolUse(tab, block) {
|
|
|
6896
7068
|
|
|
6897
7069
|
// Returns whether the answer left: false while the tab's socket is closed.
|
|
6898
7070
|
function sendAskAnswer(tab, questions, answers, annotations = null) {
|
|
7071
|
+
if (tab.automationRunId) {
|
|
7072
|
+
const requestId = tab.pendingAskRequestId;
|
|
7073
|
+
if (!tab._workerQuestions?.has(requestId)) return false;
|
|
7074
|
+
answerWorkerQuestion(tab.automationRunId, requestId, { decision: 'answer', answers }).catch((error) => {
|
|
7075
|
+
appendStatus(tab, error.message);
|
|
7076
|
+
// Keep the native card retryable after a delivery failure.
|
|
7077
|
+
if (tab._workerQuestions?.has(requestId)) {
|
|
7078
|
+
const card = tab.messagesEl?.querySelector(`[data-worker-question-id="${CSS.escape(requestId)}"]`);
|
|
7079
|
+
card?.querySelectorAll('button, input, textarea').forEach((el) => { el.disabled = false; });
|
|
7080
|
+
const submit = card?.querySelector('.ask-submit');
|
|
7081
|
+
if (submit) submit.textContent = t('common.retry');
|
|
7082
|
+
}
|
|
7083
|
+
});
|
|
7084
|
+
return true;
|
|
7085
|
+
}
|
|
6899
7086
|
if (!tab.ws || tab.ws.readyState !== WebSocket.OPEN) return false;
|
|
6900
7087
|
|
|
6901
7088
|
const requestId = tab.pendingAskRequestId;
|
|
@@ -7347,9 +7534,15 @@ function updateToolResult(tab, ev) {
|
|
|
7347
7534
|
if (!$msgs) return;
|
|
7348
7535
|
// Background task output (BashOutput results) routes back to the origin card
|
|
7349
7536
|
try { handleBgToolResult(ev, tab); } catch {}
|
|
7350
|
-
|
|
7351
|
-
const
|
|
7352
|
-
|
|
7537
|
+
// During a replay the cards it built are indexed by id (no selector scan of the transcript per result).
|
|
7538
|
+
const indexed = $msgs._replayCards instanceof Map ? $msgs._replayCards.get(String(ev.tool_use_id)) : null;
|
|
7539
|
+
let card = indexed?.matches?.('.tool-card, .plan-card') ? indexed : null;
|
|
7540
|
+
if (!card) {
|
|
7541
|
+
const escapedId = CSS.escape(ev.tool_use_id);
|
|
7542
|
+
card = $msgs.querySelector(`.tool-card[data-tool-id="${escapedId}"]`) || $msgs.querySelector(`.plan-card[data-tool-id="${escapedId}"]`);
|
|
7543
|
+
}
|
|
7544
|
+
// A live result for a card the tail-first replay has not built yet: applied when it is built.
|
|
7545
|
+
if (!card) { holdPendingResult(tab, ev); return; }
|
|
7353
7546
|
// Synthetic PostToolUse hook event + SubagentStop
|
|
7354
7547
|
const toolNm = card.dataset.toolName || '';
|
|
7355
7548
|
recordHookEvent(tab, ev.is_error ? 'PostToolUseFailure' : 'PostToolUse', toolNm);
|
|
@@ -7374,8 +7567,10 @@ function updateToolResult(tab, ev) {
|
|
|
7374
7567
|
finalizeDiffCard(card, ev, typed?.view);
|
|
7375
7568
|
if (!ev.is_error) return; // success: stats in the header say it all — skip noisy RESULT text
|
|
7376
7569
|
}
|
|
7377
|
-
// Collapse adjacent repeated MCP tool calls (
|
|
7378
|
-
|
|
7570
|
+
// Collapse adjacent repeated MCP tool calls inside this turn (replays batch once at the end)
|
|
7571
|
+
if (!tab._replaying && toolNm.startsWith('mcp__')) {
|
|
7572
|
+
try { collapseAdjacentMcpTools(card.parentElement || $msgs); } catch {}
|
|
7573
|
+
}
|
|
7379
7574
|
// Plan cards don't have result sections — just mark success/error via border
|
|
7380
7575
|
if (card.classList.contains('plan-card')) {
|
|
7381
7576
|
card.style.borderColor = ev.is_error ? 'rgba(255,82,82,0.3)' : 'rgba(100,200,120,0.3)';
|
|
@@ -7557,6 +7752,9 @@ function _applySessionOptions(tab, msg) {
|
|
|
7557
7752
|
if (hasCapability(tab, 'tool_policy')) msg.toolPolicy = tab.toolPolicy || 'full';
|
|
7558
7753
|
// The tab's session settings (/session): the bridge validates them again.
|
|
7559
7754
|
if (hasCapability(tab, 'session_settings')) msg.session = normalizeSession(tab.session);
|
|
7755
|
+
// Think off on a model with effort levels is a pick of its own: sent as 'off'
|
|
7756
|
+
// so the bridge disables thinking, or the user's settings' effortLevel applies.
|
|
7757
|
+
if (!msg.effort && hasCapability(tab, 'effort_off') && _modelSupportsEffort(tab)) msg.effort = 'off';
|
|
7560
7758
|
// The Claude account this tab runs under (the default account sends nothing).
|
|
7561
7759
|
if (hasCapability(tab, 'accounts')) msg.accountId = tab.accountId || 'default';
|
|
7562
7760
|
// A name typed before the first message becomes the new session's title.
|
|
@@ -8056,6 +8254,7 @@ function renderAskUserQuestion(tab, requestId, input) {
|
|
|
8056
8254
|
const allQuestions = input.questions || questions;
|
|
8057
8255
|
const el = document.createElement('div');
|
|
8058
8256
|
el.className = 'msg msg-assistant';
|
|
8257
|
+
el.dataset.workerQuestionId = requestId;
|
|
8059
8258
|
|
|
8060
8259
|
const avatar = document.createElement('div');
|
|
8061
8260
|
avatar.className = 'msg-avatar';
|
|
@@ -8237,7 +8436,7 @@ function renderAskUserQuestion(tab, requestId, input) {
|
|
|
8237
8436
|
// Submit button — sends all answers as a batch
|
|
8238
8437
|
submitBtn.addEventListener('click', () => {
|
|
8239
8438
|
// An answer is shown as given only once it can be sent: until then the card stays as it is.
|
|
8240
|
-
if (tab.ws?.readyState !== WebSocket.OPEN) { appendStatus(tab, ASK_ANSWER_UNSENT); return; }
|
|
8439
|
+
if (!tab.automationRunId && tab.ws?.readyState !== WebSocket.OPEN) { appendStatus(tab, ASK_ANSWER_UNSENT); return; }
|
|
8241
8440
|
wrap.querySelectorAll('.ask-option').forEach(b => { b.disabled = true; });
|
|
8242
8441
|
wrap.querySelectorAll('.ask-text-input, .ask-notes').forEach(i => { i.disabled = true; });
|
|
8243
8442
|
submitBtn.disabled = true;
|
|
@@ -8307,8 +8506,12 @@ function appendUser(tab, text, images, files) {
|
|
|
8307
8506
|
function _stampUserMessageUuid(tab, uuid) {
|
|
8308
8507
|
const $msgs = tab.messagesEl;
|
|
8309
8508
|
if (!$msgs || !uuid) return;
|
|
8310
|
-
const
|
|
8311
|
-
|
|
8509
|
+
const last = $msgs.lastElementChild;
|
|
8510
|
+
let row = (last?.classList?.contains('msg-user') && !last.dataset.uuid) ? last : null;
|
|
8511
|
+
if (!row) {
|
|
8512
|
+
const rows = [...$msgs.querySelectorAll('.msg-user')].reverse();
|
|
8513
|
+
row = rows.find(r => !r.dataset.uuid);
|
|
8514
|
+
}
|
|
8312
8515
|
if (!row) return;
|
|
8313
8516
|
row.dataset.uuid = uuid;
|
|
8314
8517
|
if (!tab.sdkMode) return;
|
|
@@ -10348,29 +10551,36 @@ const _fileLinkOptions = {
|
|
|
10348
10551
|
};
|
|
10349
10552
|
|
|
10350
10553
|
// ── Public API ──
|
|
10554
|
+
let _readyPromise = null;
|
|
10351
10555
|
async function _ensureClaudePanelReady() {
|
|
10556
|
+
if (_readyPromise) return _readyPromise;
|
|
10352
10557
|
if (!_panel) {
|
|
10353
|
-
|
|
10354
|
-
|
|
10355
|
-
|
|
10356
|
-
|
|
10357
|
-
|
|
10358
|
-
|
|
10359
|
-
|
|
10360
|
-
|
|
10361
|
-
|
|
10362
|
-
|
|
10363
|
-
|
|
10364
|
-
|
|
10365
|
-
|
|
10366
|
-
|
|
10367
|
-
|
|
10368
|
-
|
|
10369
|
-
|
|
10370
|
-
|
|
10371
|
-
|
|
10372
|
-
|
|
10373
|
-
|
|
10558
|
+
_readyPromise = (async () => {
|
|
10559
|
+
injectStyles();
|
|
10560
|
+
_panel = buildPanel();
|
|
10561
|
+
document.body.appendChild(_panel);
|
|
10562
|
+
registerSidepanel({
|
|
10563
|
+
owner: PANEL_OWNER, provider: 'claude', element: _panel,
|
|
10564
|
+
header: _panel.querySelector('.cp-header'), actions: _panel.querySelector('.cp-header-actions'),
|
|
10565
|
+
buttonClass: 'cp-header-btn', dockHandle: _panel.querySelector('.cp-resize-handle'),
|
|
10566
|
+
applyVisibility: applyClaudeVisibility,
|
|
10567
|
+
});
|
|
10568
|
+
wireEvents();
|
|
10569
|
+
_panel.querySelector('#cp-messages-container')?.addEventListener('click', _onMessagesClick);
|
|
10570
|
+
wireFileLinks(_panel.querySelector('#cp-messages-container'), _fileLinkOptions);
|
|
10571
|
+
await loadConfig(); // must complete before restoreTabs — checks server boot ID
|
|
10572
|
+
loadSkills();
|
|
10573
|
+
restoreTabs();
|
|
10574
|
+
setTimeout(() => {
|
|
10575
|
+
loadMonthlyCost();
|
|
10576
|
+
syncSessionCosts();
|
|
10577
|
+
}, 400);
|
|
10578
|
+
_wireBrowserSync();
|
|
10579
|
+
_startHeartbeat();
|
|
10580
|
+
window.dispatchEvent(new CustomEvent('sidepanel-tray:provider-loaded', { detail: { provider: 'claude' } }));
|
|
10581
|
+
_ensureCliSubscription();
|
|
10582
|
+
})();
|
|
10583
|
+
return _readyPromise;
|
|
10374
10584
|
}
|
|
10375
10585
|
}
|
|
10376
10586
|
|
|
@@ -10452,8 +10662,11 @@ export async function attachClaudeAutomation(run, { focus = !!run?.focus, isCanc
|
|
|
10452
10662
|
}
|
|
10453
10663
|
if (!tab) return { ok: false, reason: 'tab_limit' };
|
|
10454
10664
|
const running = run.status === 'starting' || run.status === 'running';
|
|
10665
|
+
// A dispatched worker a server restart cut off: suspended until the next start resumes it as the same run
|
|
10666
|
+
// (lib/assistant-dispatch.js). It still owns this tab; nothing of its cut-off turn runs any more.
|
|
10667
|
+
const suspended = run.status === 'suspended';
|
|
10455
10668
|
tab.automationRunId = run.runId;
|
|
10456
|
-
tab.automationActive = running;
|
|
10669
|
+
tab.automationActive = running || suspended;
|
|
10457
10670
|
tab.automationOwnerId = nativeLoopWindowId;
|
|
10458
10671
|
tab.releasedRunId = null;
|
|
10459
10672
|
tab.sdkMode = true;
|
|
@@ -10467,6 +10680,12 @@ export async function attachClaudeAutomation(run, { focus = !!run?.focus, isCanc
|
|
|
10467
10680
|
setRunning(tab, running);
|
|
10468
10681
|
updatePillLabel(tab);
|
|
10469
10682
|
tab._automationIteration = run.currentIteration;
|
|
10683
|
+
// Resumed after a server restart: what the run did while this window was away (the continuation prompt, its first
|
|
10684
|
+
// steps: events sent before the page reconnected) is in its transcript, not in this tab, which reads it again.
|
|
10685
|
+
// That holds for a run that resumed and ended while this window was away too.
|
|
10686
|
+
const resumes = Number(run.resumes) || 0;
|
|
10687
|
+
const resumedSinceSeen = resumes > (tab._automationResumes || 0);
|
|
10688
|
+
if (tab._automationHydrated && resumedSinceSeen) tab._automationHydrated = false;
|
|
10470
10689
|
if (!tab._automationHydrated) {
|
|
10471
10690
|
tab._automationHydrated = true;
|
|
10472
10691
|
if (tab.messagesEl) tab.messagesEl.innerHTML = '';
|
|
@@ -10476,11 +10695,28 @@ export async function attachClaudeAutomation(run, { focus = !!run?.focus, isCanc
|
|
|
10476
10695
|
return { ok: false, reason: 'dismissed' };
|
|
10477
10696
|
}
|
|
10478
10697
|
}
|
|
10698
|
+
if (running && resumedSinceSeen && tab._automationResumes !== undefined) appendStatus(tab, 'Resumed after the server restart — the run continues here.');
|
|
10699
|
+
tab._automationResumes = Math.max(tab._automationResumes || 0, resumes);
|
|
10700
|
+
if (suspended) _showRunSuspended(tab, run);
|
|
10701
|
+
else tab._automationSuspendedAt = null;
|
|
10479
10702
|
// (A dispatched worker's failure, with its reason, is on its end card.)
|
|
10480
10703
|
if (run.status === 'failed' && run.error && !isDispatchedRun(run) && tab._automationLifecycleError !== run.error) {
|
|
10481
10704
|
tab._automationLifecycleError = run.error;
|
|
10482
10705
|
appendError(tab, run.error);
|
|
10483
10706
|
}
|
|
10707
|
+
syncWorkerQuestionQueue(tab, run, {
|
|
10708
|
+
open: (id, pending) => handleControlRequest(tab, { request_id: id, request: { tool_name: 'AskUserQuestion', input: pending.input || { questions: pending.questions } } }),
|
|
10709
|
+
close: (id) => {
|
|
10710
|
+
const card = tab.messagesEl?.querySelector(`[data-worker-question-id="${CSS.escape(id)}"]`);
|
|
10711
|
+
card?.querySelectorAll('button, input, textarea').forEach((el) => { el.disabled = true; });
|
|
10712
|
+
const submit = card?.querySelector('.ask-submit');
|
|
10713
|
+
if (submit) submit.textContent = t('workerQuestion.resolved');
|
|
10714
|
+
tab.pendingAskRequestId = null; tab.pendingAskToolUseId = null;
|
|
10715
|
+
tab.pendingAskBufferedAnswer = null; tab.askRenderedViaControl = false;
|
|
10716
|
+
// The same provider turn resumes; release messages buffered while its question was open.
|
|
10717
|
+
_flushMsgBuffer(tab);
|
|
10718
|
+
},
|
|
10719
|
+
});
|
|
10484
10720
|
trackWorkerEnd(run, { apply: (view) => showWorkerEnd(tab, view), busy: hasLiveBackgroundWork(tab) });
|
|
10485
10721
|
// The mode control is hidden while the run is active and back when it ended.
|
|
10486
10722
|
if (tab === activeTab()) populateModeDropdown(_panel?.querySelector('#cp-mode'), tab);
|
|
@@ -10527,6 +10763,64 @@ function hasLiveBackgroundWork(tab) {
|
|
|
10527
10763
|
return false;
|
|
10528
10764
|
}
|
|
10529
10765
|
|
|
10766
|
+
const LOST_TURN_LINE = 'Connection lost — this turn did not survive the disconnect.';
|
|
10767
|
+
// What a tab says when the turn it showed did not survive a lost connection. When its session is a dispatched worker's
|
|
10768
|
+
// (a tab opened on that session), the line says what became of the run: resumed after a server restart (in its own
|
|
10769
|
+
// tab), or how it ended, with its reason. A tab the user continued by hand after its run ended keeps the generic line:
|
|
10770
|
+
// the turn that was cut off was the user's own.
|
|
10771
|
+
async function _lostTurnLine(tab) {
|
|
10772
|
+
if (!tab?.sessionId || tab.releasedRunId) return LOST_TURN_LINE;
|
|
10773
|
+
try {
|
|
10774
|
+
const res = await fetch('/api/sidepanel-runs');
|
|
10775
|
+
const runs = res.ok ? ((await res.json())?.runs || []) : [];
|
|
10776
|
+
const run = runs.find((item) => item?.providerSessionId === tab.sessionId && isDispatchedRun(item));
|
|
10777
|
+
if (!run) return LOST_TURN_LINE;
|
|
10778
|
+
if (run.status === 'suspended') return 'SynaBun restarted — this worker run is being resumed in its own tab.';
|
|
10779
|
+
if (run.status === 'starting' || run.status === 'running') {
|
|
10780
|
+
return Number(run.resumes) > 0 ? 'SynaBun restarted — this worker run was resumed and continues in its own tab.' : LOST_TURN_LINE;
|
|
10781
|
+
}
|
|
10782
|
+
let dispatch = null;
|
|
10783
|
+
try {
|
|
10784
|
+
const reply = await fetch(`/api/assistant/runs/${encodeURIComponent(run.runId)}`);
|
|
10785
|
+
if (reply.ok) dispatch = (await reply.json())?.run || null;
|
|
10786
|
+
} catch {}
|
|
10787
|
+
const view = workerEndView(run, dispatch);
|
|
10788
|
+
return view ? `This session's worker run ended: ${view.title}${view.detail ? ` — ${view.detail}` : ''}` : LOST_TURN_LINE;
|
|
10789
|
+
} catch {
|
|
10790
|
+
return LOST_TURN_LINE;
|
|
10791
|
+
}
|
|
10792
|
+
}
|
|
10793
|
+
|
|
10794
|
+
// A run tab whose run the server suspended as it restarted (status 'suspended'): its turn was cut off, so the tab
|
|
10795
|
+
// stops looking busy (spinner, a tool row and its timer, background shells: all went with the CLI) and says the run
|
|
10796
|
+
// resumes. Once per suspension.
|
|
10797
|
+
function _showRunSuspended(tab, run) {
|
|
10798
|
+
const key = run?.suspendedAt || 'suspended';
|
|
10799
|
+
if (tab._automationSuspendedAt === key) return;
|
|
10800
|
+
tab._automationSuspendedAt = key;
|
|
10801
|
+
finishTab(tab, true);
|
|
10802
|
+
_closeCutOffTools(tab);
|
|
10803
|
+
appendStatus(tab, 'SynaBun restarted — resuming this run…');
|
|
10804
|
+
}
|
|
10805
|
+
|
|
10806
|
+
// Every tool call of the tab still waiting for its result is closed as cut off, through the path a result takes (the
|
|
10807
|
+
// card's state, its timer, an agent card), and the background work the tab showed is over.
|
|
10808
|
+
function _closeCutOffTools(tab) {
|
|
10809
|
+
const $msgs = tab?.messagesEl;
|
|
10810
|
+
if (!$msgs) return;
|
|
10811
|
+
for (const card of $msgs.querySelectorAll('.tool-card[data-tool-id]')) {
|
|
10812
|
+
if (card.classList.contains('tool-ok') || card.classList.contains('tool-error') || card.dataset.resolved === '1') continue;
|
|
10813
|
+
if (!card.dataset.toolId) continue;
|
|
10814
|
+
try { updateToolResult(tab, { type: 'tool_result', tool_use_id: card.dataset.toolId, is_error: true, content: 'Cut off by the server restart.' }); } catch {}
|
|
10815
|
+
}
|
|
10816
|
+
let shells = false;
|
|
10817
|
+
for (const task of tab.bgTasks?.values?.() || []) {
|
|
10818
|
+
if (task?.status === 'running') { task.status = 'stopped'; shells = true; }
|
|
10819
|
+
}
|
|
10820
|
+
if (shells) { try { renderBgTray(tab); } catch {} }
|
|
10821
|
+
_setBackgroundWork(tab, []);
|
|
10822
|
+
}
|
|
10823
|
+
|
|
10530
10824
|
// The end of a worker the Assistant dispatched (ui-worker-end.js): one card,
|
|
10531
10825
|
// the last row of its transcript. Its button closes this tab the way the X
|
|
10532
10826
|
// does (a warm worker that finished its task is completed, one still at work
|
|
@@ -11925,11 +12219,11 @@ function wireEvents() {
|
|
|
11925
12219
|
// Side panel browser launch removed — all automations use floating browsers only.
|
|
11926
12220
|
|
|
11927
12221
|
// Show panel without toggling it closed (used by notification click-through)
|
|
11928
|
-
on('claude-panel:show', (data) => {
|
|
11929
|
-
if (!_visible) toggleClaudePanel();
|
|
12222
|
+
on('claude-panel:show', async (data) => {
|
|
12223
|
+
if (!_visible) await toggleClaudePanel();
|
|
11930
12224
|
if (data?.tabId) {
|
|
11931
|
-
const idx = _tabs.findIndex(t => t.id === data.tabId);
|
|
11932
|
-
if (idx >= 0) switchTab(idx);
|
|
12225
|
+
const idx = _tabs.findIndex(t => t.id === data.tabId || t.sessionId === data.tabId);
|
|
12226
|
+
if (idx >= 0 && idx !== _activeTabIdx) switchTab(idx);
|
|
11933
12227
|
}
|
|
11934
12228
|
});
|
|
11935
12229
|
|