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
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// ═══════════════════════════════════════════
|
|
5
5
|
//
|
|
6
6
|
// Provides a docked bottom terminal panel with tabbed sessions.
|
|
7
|
-
// Profiles: Claude Code, Codex CLI,
|
|
7
|
+
// Profiles: Claude Code, Codex CLI, Antigravity CLI, OpenCode, Shell.
|
|
8
8
|
|
|
9
9
|
import { state, emit, on } from './state.js';
|
|
10
10
|
import { KEYS } from './constants.js';
|
|
@@ -14,6 +14,7 @@ import { registerAction } from './ui-keybinds.js';
|
|
|
14
14
|
import { isGuest, hasPermission } from './ui-sync.js';
|
|
15
15
|
import { getWhiteboardElementById } from './ui-whiteboard.js';
|
|
16
16
|
import { createFrameRenderer } from './utils.js';
|
|
17
|
+
import { frameRect, onFrameChange, clampBox, clampBoxLoose } from './app-frame.js';
|
|
17
18
|
import { notify, NOTIF_TYPE } from './ui-notifications.js';
|
|
18
19
|
import { getProviderMeta } from './provider-icons.js';
|
|
19
20
|
import { readinessKind, typeWhenReady } from './term-ready.js';
|
|
@@ -22,13 +23,12 @@ import { mountAssistant } from './assistant/asst-panel.js';
|
|
|
22
23
|
import { getAssistantSession } from './assistant/asst-api.js';
|
|
23
24
|
import { mascotCameoSvg } from './synabun-mascot.js';
|
|
24
25
|
import { brainLabel, normalizeBrain, readStoredBrain, restoredSessionName, sessionNameGivenUp } from './assistant/asst-state.js';
|
|
25
|
-
import { initAssistant, registerAssistantHost, openAssistant, assistantOwnerOf,
|
|
26
|
+
import { initAssistant, registerAssistantHost, openAssistant, assistantOwnerOf, readLiveAssistantSessions, assistantBlocked, isAssistantSessionLive } from './ui-assistant.js';
|
|
26
27
|
|
|
27
28
|
const $ = (id) => document.getElementById(id);
|
|
28
|
-
const CLI_PROFILES = new Set(['claude-code', 'codex', '
|
|
29
|
-
const NOTIF_TRACKED_CLI_PROFILES = new Set(['claude-code', 'codex', '
|
|
30
|
-
const
|
|
31
|
-
const CLI_PROFILES_NEED_RECALL = new Set(['claude-code', 'codex', 'gemini', 'opencode']);
|
|
29
|
+
const CLI_PROFILES = new Set(['claude-code', 'codex', 'antigravity', 'opencode']);
|
|
30
|
+
const NOTIF_TRACKED_CLI_PROFILES = new Set(['claude-code', 'codex', 'antigravity', 'opencode']);
|
|
31
|
+
const CLI_PROFILES_NEED_RECALL = new Set(['claude-code', 'codex', 'antigravity', 'opencode']);
|
|
32
32
|
|
|
33
33
|
// ── Platform ──
|
|
34
34
|
// macOS gets Terminal.app keys (Cmd shortcuts, Option word-jumps, Ctrl keys
|
|
@@ -144,7 +144,7 @@ function _injectPathIntoTerm(term, ws, path) {
|
|
|
144
144
|
|
|
145
145
|
const SVG_CLAUDE = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z"/></svg>';
|
|
146
146
|
const SVG_OPENAI = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M9.205 8.658v-2.26c0-.19.072-.333.238-.428l4.543-2.616c.619-.357 1.356-.523 2.117-.523 2.854 0 4.662 2.212 4.662 4.566 0 .167 0 .357-.024.547l-4.71-2.759a.797.797 0 00-.856 0l-5.97 3.473zm10.609 8.8V12.06c0-.333-.143-.57-.429-.737l-5.97-3.473 1.95-1.118a.433.433 0 01.476 0l4.543 2.617c1.309.76 2.189 2.378 2.189 3.948 0 1.808-1.07 3.473-2.76 4.163zM7.802 12.703l-1.95-1.142c-.167-.095-.239-.238-.239-.428V5.899c0-2.545 1.95-4.472 4.591-4.472 1 0 1.927.333 2.712.928L8.23 5.067c-.285.166-.428.404-.428.737v6.898zM12 15.128l-2.795-1.57v-3.33L12 8.658l2.795 1.57v3.33L12 15.128zm1.796 7.23c-1 0-1.927-.332-2.712-.927l4.686-2.712c.285-.166.428-.404.428-.737v-6.898l1.974 1.142c.167.095.238.238.238.428v5.233c0 2.545-1.974 4.472-4.614 4.472zm-5.637-5.303l-4.544-2.617c-1.308-.761-2.188-2.378-2.188-3.948A4.482 4.482 0 014.21 6.327v5.423c0 .333.143.571.428.738l5.947 3.449-1.95 1.118a.432.432 0 01-.476 0zm-.262 3.9c-2.688 0-4.662-2.021-4.662-4.519 0-.19.024-.38.047-.57l4.686 2.71c.286.167.571.167.856 0l5.97-3.448v2.26c0 .19-.07.333-.237.428l-4.543 2.616c-.619.357-1.356.523-2.117.523zm5.899 2.83a5.947 5.947 0 005.827-4.756C22.287 18.339 24 15.84 24 13.296c0-1.665-.713-3.282-1.998-4.448.119-.5.19-.999.19-1.498 0-3.401-2.759-5.947-5.946-5.947-.642 0-1.26.095-1.88.31A5.962 5.962 0 0010.205 0a5.947 5.947 0 00-5.827 4.757C1.713 5.447 0 7.945 0 10.49c0 1.666.713 3.283 1.998 4.448-.119.5-.19 1-.19 1.499 0 3.401 2.759 5.946 5.946 5.946.642 0 1.26-.095 1.88-.309a5.96 5.96 0 004.162 1.713z"/></svg>';
|
|
147
|
-
const
|
|
147
|
+
const SVG_ANTIGRAVITY = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4.5 20 12 4l7.5 16"/><path d="M8.2 20a3.8 3.8 0 0 1 7.6 0"/></svg>';
|
|
148
148
|
const SVG_OPENCODE = '<svg viewBox="0 0 240 300" fill="currentColor"><path fill-rule="evenodd" d="M0 0h240v300H0V0zm60 60v180h120V60H60z"/><rect x="60" y="120" width="120" height="120" opacity=".45"/></svg>';
|
|
149
149
|
const SVG_SHELL = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>';
|
|
150
150
|
const SVG_GIT = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg>';
|
|
@@ -156,7 +156,7 @@ const PROFILES = [
|
|
|
156
156
|
{ id: 'assistant', label: 'Assistant', svg: SVG_ASSISTANT, color: '#FFD23C' }, // non-PTY: hosts assistant/asst-panel.js
|
|
157
157
|
{ id: 'claude-code', label: 'Claude Code', svg: SVG_CLAUDE, color: '#D4A27F' },
|
|
158
158
|
{ id: 'codex', label: 'Codex CLI', svg: SVG_OPENAI, color: '#74c7a5' },
|
|
159
|
-
{ id: '
|
|
159
|
+
{ id: 'antigravity', label: 'Antigravity CLI', svg: SVG_ANTIGRAVITY, color: '#669DF6' },
|
|
160
160
|
{ id: 'opencode', label: 'OpenCode', svg: SVG_OPENCODE, color: '#E8E0DC' },
|
|
161
161
|
{ id: 'shell', label: 'Shell', svg: SVG_SHELL, color: '#aaaaaa' },
|
|
162
162
|
{ id: 'browser', label: 'Browser', svg: SVG_BROWSER, color: '#4fc3f7' },
|
|
@@ -248,6 +248,12 @@ let _closingIds = new Set(); // session IDs currently being closed (prevents r
|
|
|
248
248
|
let _opening = false; // true while openSession/openBrowserSession is in progress
|
|
249
249
|
let _openingAt = 0; // timestamp when _opening was set true (auto-reset after 15s)
|
|
250
250
|
let _restoringLayout = false; // true during reconnect+layout restore (suppresses layout saves)
|
|
251
|
+
// Saved Assistant tabs whose session list could not be read yet (server still starting).
|
|
252
|
+
// Kept in the registry on every save until a read succeeds; never pruned on a failed read.
|
|
253
|
+
let _waitingAssistant = [];
|
|
254
|
+
let _waitingAssistantTimer = null;
|
|
255
|
+
const _waitingPlace = new Map(); // waiting Assistant tab id → { float, order, pane, paneActive, switches } from the saved layout
|
|
256
|
+
const ASSISTANT_RESTORE_RETRY_MS = [500, 1000, 2000, 4000, 8000, 15_000];
|
|
251
257
|
let _windowResizeTimer = null; // debounce handle for window resize clamping
|
|
252
258
|
|
|
253
259
|
// ── Split pane state ──
|
|
@@ -256,6 +262,7 @@ let _focusedPane = 0; // 0=left, 1=right — which pane has keyboard
|
|
|
256
262
|
let _paneAssignments = new Map(); // sessionId → 0|1 (which pane a session belongs to)
|
|
257
263
|
let _activePaneIdx = [-1, -1]; // per-pane active session index (into _sessions)
|
|
258
264
|
let _splitRatio = 0.5; // left pane width fraction (0.3–0.7)
|
|
265
|
+
let _paneSwitches = [0, 0]; // per-pane count of tab switches outside a restore
|
|
259
266
|
|
|
260
267
|
const DEFAULT_HEIGHT = 320;
|
|
261
268
|
const MIN_HEIGHT = 120;
|
|
@@ -617,79 +624,6 @@ function _cliBadgeHtml(sessionId) {
|
|
|
617
624
|
: '';
|
|
618
625
|
}
|
|
619
626
|
|
|
620
|
-
// ── Floating terminal MCP profile dropdown ──
|
|
621
|
-
|
|
622
|
-
let _floatProfileCache = null;
|
|
623
|
-
let _floatProfileCacheTime = 0;
|
|
624
|
-
|
|
625
|
-
async function _fetchFloatProfiles() {
|
|
626
|
-
const now = Date.now();
|
|
627
|
-
if (_floatProfileCache && now - _floatProfileCacheTime < 60000) return _floatProfileCache;
|
|
628
|
-
try {
|
|
629
|
-
const resp = await fetch('/api/mcp/profile');
|
|
630
|
-
const data = await resp.json();
|
|
631
|
-
if (data.ok) {
|
|
632
|
-
_floatProfileCache = { current: data.profile || 'full', presets: data.presets || {} };
|
|
633
|
-
_floatProfileCacheTime = now;
|
|
634
|
-
}
|
|
635
|
-
} catch {}
|
|
636
|
-
return _floatProfileCache || { current: 'full', presets: {} };
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
function _initFloatProfileDropdown(dd) {
|
|
640
|
-
const btn = dd.querySelector('.term-float-profile-btn');
|
|
641
|
-
const menu = dd.querySelector('.term-float-profile-menu');
|
|
642
|
-
const label = dd.querySelector('.term-float-profile-label');
|
|
643
|
-
|
|
644
|
-
// Load current profile label
|
|
645
|
-
_fetchFloatProfiles().then(data => {
|
|
646
|
-
const p = data.presets[data.current];
|
|
647
|
-
label.textContent = p?.label || data.current;
|
|
648
|
-
});
|
|
649
|
-
|
|
650
|
-
btn.addEventListener('click', async (e) => {
|
|
651
|
-
e.stopPropagation();
|
|
652
|
-
const wasOpen = menu.classList.contains('open');
|
|
653
|
-
// Close all other open profile menus
|
|
654
|
-
document.querySelectorAll('.term-float-profile-menu.open').forEach(m => m.classList.remove('open'));
|
|
655
|
-
if (wasOpen) return;
|
|
656
|
-
|
|
657
|
-
const data = await _fetchFloatProfiles();
|
|
658
|
-
menu.innerHTML = '';
|
|
659
|
-
for (const [id, preset] of Object.entries(data.presets)) {
|
|
660
|
-
const opt = document.createElement('div');
|
|
661
|
-
opt.className = 'term-float-profile-option' + (id === data.current ? ' selected' : '');
|
|
662
|
-
opt.innerHTML = `<span class="tfp-name">${_escHtml(String(preset.label || id))}</span><span class="tfp-hint">${_escHtml(String(preset.tools))} tools</span>`;
|
|
663
|
-
opt.addEventListener('click', async (ev) => {
|
|
664
|
-
ev.stopPropagation();
|
|
665
|
-
menu.classList.remove('open');
|
|
666
|
-
if (id === data.current) return;
|
|
667
|
-
label.textContent = preset.label || id;
|
|
668
|
-
try {
|
|
669
|
-
await fetch('/api/mcp/profile', {
|
|
670
|
-
method: 'POST',
|
|
671
|
-
headers: { 'Content-Type': 'application/json' },
|
|
672
|
-
body: JSON.stringify({ profile: id }),
|
|
673
|
-
});
|
|
674
|
-
_floatProfileCache = null; // bust cache
|
|
675
|
-
// Update all other floating profile dropdowns
|
|
676
|
-
document.querySelectorAll('.term-float-profile-label').forEach(lbl => {
|
|
677
|
-
lbl.textContent = preset.label || id;
|
|
678
|
-
});
|
|
679
|
-
} catch {}
|
|
680
|
-
});
|
|
681
|
-
menu.appendChild(opt);
|
|
682
|
-
}
|
|
683
|
-
menu.classList.add('open');
|
|
684
|
-
|
|
685
|
-
// Close on outside click
|
|
686
|
-
const close = (ev) => {
|
|
687
|
-
if (!dd.contains(ev.target)) { menu.classList.remove('open'); document.removeEventListener('mousedown', close); }
|
|
688
|
-
};
|
|
689
|
-
setTimeout(() => document.addEventListener('mousedown', close), 0);
|
|
690
|
-
});
|
|
691
|
-
}
|
|
692
|
-
|
|
693
627
|
// ── Floating terminal Recall profile dropdown ──
|
|
694
628
|
|
|
695
629
|
const FLOAT_RECALL_META = [
|
|
@@ -1683,6 +1617,7 @@ function saveSessionRegistry() {
|
|
|
1683
1617
|
brain: s._isAssistant ? (s._brain || prev?.brain || null) : null,
|
|
1684
1618
|
});
|
|
1685
1619
|
}
|
|
1620
|
+
for (const w of _waitingAssistant) if (!seen.has(w.id)) seen.set(w.id, w);
|
|
1686
1621
|
storage.setItem(KEYS.TERMINAL_SESSIONS, JSON.stringify([...seen.values()]));
|
|
1687
1622
|
}
|
|
1688
1623
|
|
|
@@ -1719,6 +1654,14 @@ function saveTerminalLayout() {
|
|
|
1719
1654
|
if (_restoringLayout) return; // don't overwrite saved layout during reconnect
|
|
1720
1655
|
try {
|
|
1721
1656
|
const snap = getTerminalSnapshot();
|
|
1657
|
+
// A float still waiting for its session keeps its saved place.
|
|
1658
|
+
for (const w of _waitingAssistant) {
|
|
1659
|
+
const float = _waitingPlace.get(w.id)?.float;
|
|
1660
|
+
if (float && !snap.detachedTabs.some(dt => dt.sessionId === w.id)) snap.detachedTabs.push(float);
|
|
1661
|
+
// …and a docked one its split pane.
|
|
1662
|
+
const pane = _waitingPlace.get(w.id)?.pane;
|
|
1663
|
+
if (snap.splitMode && pane != null && !(w.id in snap.paneAssignments)) snap.paneAssignments[w.id] = pane;
|
|
1664
|
+
}
|
|
1722
1665
|
storage.setItem(KEYS.TERMINAL_SESSIONS + '-layout', JSON.stringify(snap));
|
|
1723
1666
|
} catch {}
|
|
1724
1667
|
}
|
|
@@ -2322,24 +2265,22 @@ function detachPanel() {
|
|
|
2322
2265
|
// so left margin matches right margin — accounts for left sidebars and right sidepanel)
|
|
2323
2266
|
let pos;
|
|
2324
2267
|
try { pos = JSON.parse(storage.getItem(KEYS.TERMINAL_FLOAT_POS)); } catch {}
|
|
2268
|
+
const f = frameRect();
|
|
2325
2269
|
if (!pos) {
|
|
2326
|
-
const
|
|
2327
|
-
const leftEdge = (parseFloat(cs.getPropertyValue('--explorer-width')) || 0)
|
|
2328
|
-
+ (parseFloat(cs.getPropertyValue('--file-explorer-width')) || 0);
|
|
2329
|
-
const rightEdge = window.innerWidth - getRightPanelReservedWidth(cs);
|
|
2270
|
+
const { left: leftEdge, right: rightEdge } = _usableArea(f);
|
|
2330
2271
|
const usableW = Math.max(0, rightEdge - leftEdge);
|
|
2331
2272
|
const w = Math.min(800, usableW * 0.6);
|
|
2332
2273
|
const h = Math.min(500, dockedH);
|
|
2333
2274
|
pos = {
|
|
2334
2275
|
left: leftEdge + (usableW - w) / 2,
|
|
2335
|
-
top: Math.max(
|
|
2276
|
+
top: Math.max(f.top, f.top + (f.height - h) / 2),
|
|
2336
2277
|
width: w, height: h,
|
|
2337
2278
|
};
|
|
2338
2279
|
}
|
|
2339
2280
|
|
|
2340
2281
|
_panel.classList.add('detached');
|
|
2341
|
-
_panel.style.left = pos.left + 'px';
|
|
2342
|
-
_panel.style.top = Math.max(
|
|
2282
|
+
_panel.style.left = Math.max(f.left, Math.min(pos.left, f.right - 80)) + 'px';
|
|
2283
|
+
_panel.style.top = Math.max(f.top, Math.min(pos.top, f.bottom - 80)) + 'px';
|
|
2343
2284
|
_panel.style.width = pos.width + 'px';
|
|
2344
2285
|
_panel.style.height = pos.height + 'px';
|
|
2345
2286
|
|
|
@@ -2436,7 +2377,7 @@ function initFloatDrag() {
|
|
|
2436
2377
|
// Header drag for floating mode
|
|
2437
2378
|
function _startPanelDrag(x, y) {
|
|
2438
2379
|
const rect = _panel.getBoundingClientRect();
|
|
2439
|
-
_floatDrag = { startX: x, startY: y, startL: rect.left, startT: rect.top };
|
|
2380
|
+
_floatDrag = { startX: x, startY: y, startL: rect.left, startT: rect.top, w: rect.width, h: rect.height, frame: frameRect() };
|
|
2440
2381
|
pendingPanelDrag = null;
|
|
2441
2382
|
_panel.classList.add('float-dragging');
|
|
2442
2383
|
document.body.classList.add('ui-interacting');
|
|
@@ -2452,7 +2393,10 @@ function initFloatDrag() {
|
|
|
2452
2393
|
finalL = Math.round(finalL / gs) * gs;
|
|
2453
2394
|
finalT = Math.round(finalT / gs) * gs;
|
|
2454
2395
|
}
|
|
2455
|
-
|
|
2396
|
+
// Inside the app frame: the header stays below the bar, 80px of the window stays in reach
|
|
2397
|
+
const f = _floatDrag.frame || (_floatDrag.frame = frameRect());
|
|
2398
|
+
const w = _floatDrag.w || 0, h = _floatDrag.h || 0;
|
|
2399
|
+
({ x: finalL, y: finalT } = clampBoxLoose(finalL, finalT, w, h, f, 80));
|
|
2456
2400
|
// Transform during drag (composited, no layout); committed on dragend
|
|
2457
2401
|
_floatDrag.lastL = finalL;
|
|
2458
2402
|
_floatDrag.lastT = finalT;
|
|
@@ -2546,7 +2490,11 @@ function initFloatResize() {
|
|
|
2546
2490
|
nl = Math.round(nl / gs) * gs; nt = Math.round(nt / gs) * gs;
|
|
2547
2491
|
nw = Math.round(nw / gs) * gs; nh = Math.round(nh / gs) * gs;
|
|
2548
2492
|
}
|
|
2549
|
-
|
|
2493
|
+
const f = frameRect();
|
|
2494
|
+
if (nt < f.top) { if (dir.includes('n')) nh -= f.top - nt; nt = f.top; }
|
|
2495
|
+
if (nl < f.left) { if (dir.includes('w')) nw -= f.left - nl; nl = f.left; }
|
|
2496
|
+
nw = Math.max(MIN_W, Math.min(nw, f.right - nl));
|
|
2497
|
+
nh = Math.max(MIN_H, Math.min(nh, f.bottom - nt));
|
|
2550
2498
|
_panel.style.left = nl + 'px';
|
|
2551
2499
|
_panel.style.top = nt + 'px';
|
|
2552
2500
|
_panel.style.width = nw + 'px';
|
|
@@ -2653,10 +2601,12 @@ function initResizeHandle() {
|
|
|
2653
2601
|
_draggingResize = true;
|
|
2654
2602
|
document.body.classList.add('ui-interacting');
|
|
2655
2603
|
graphLayers = [$('graph-container'), $('static-bg')].filter(Boolean);
|
|
2604
|
+
// Up to 80% of the window, and never past the top of the app frame (its 12px inner padding kept)
|
|
2605
|
+
const dockBottom = _panel.getBoundingClientRect().bottom;
|
|
2606
|
+
const maxH = Math.max(MIN_HEIGHT, Math.min(window.innerHeight * 0.8, dockBottom - frameRect().top - 12));
|
|
2656
2607
|
|
|
2657
2608
|
const onMove = (e) => {
|
|
2658
2609
|
const dy = startY - e.clientY;
|
|
2659
|
-
const maxH = window.innerHeight * 0.8;
|
|
2660
2610
|
const newH = Math.max(MIN_HEIGHT, Math.min(maxH, startH + dy));
|
|
2661
2611
|
scheduleHeight(newH);
|
|
2662
2612
|
};
|
|
@@ -3596,6 +3546,107 @@ function _assistantOwnedElsewhere(sessionId) {
|
|
|
3596
3546
|
}
|
|
3597
3547
|
|
|
3598
3548
|
/** Reconnect a saved assistant tab (registry / workspace) to its live server session. */
|
|
3549
|
+
/** Keep saved Assistant tabs while the session list cannot be read, and retry the read. */
|
|
3550
|
+
function _waitAssistantRestore(entries, { layout = null, order = [] } = {}) {
|
|
3551
|
+
const known = new Set(_waitingAssistant.map(w => w.id));
|
|
3552
|
+
for (const e of entries) {
|
|
3553
|
+
if (!known.has(e.id)) _waitingAssistant.push(e);
|
|
3554
|
+
// Where the tab was: its float (position, size) from the saved layout, or its docked place.
|
|
3555
|
+
const float = (layout?.detachedTabs || []).find(dt => dt?.sessionId === e.id) || null;
|
|
3556
|
+
// In split mode, its pane and whether it was that pane's active tab.
|
|
3557
|
+
const p = layout?.splitMode ? layout.paneAssignments?.[e.id] : null;
|
|
3558
|
+
const pane = p === 0 || p === 1 ? p : null;
|
|
3559
|
+
const paneActive = pane != null && (layout.sessions || [])[layout.activePaneIdx?.[pane]]?.id === e.id;
|
|
3560
|
+
_waitingPlace.set(e.id, { float, order: order.map(o => o.id), pane, paneActive, switches: null });
|
|
3561
|
+
}
|
|
3562
|
+
if (_waitingAssistantTimer) return;
|
|
3563
|
+
const attempt = async (n) => {
|
|
3564
|
+
_waitingAssistantTimer = null;
|
|
3565
|
+
if (!_waitingAssistant.length || assistantBlocked()) return;
|
|
3566
|
+
const live = await readLiveAssistantSessions();
|
|
3567
|
+
if (!live) {
|
|
3568
|
+
// Out of retries: the entries stay saved for the next page load.
|
|
3569
|
+
if (n < ASSISTANT_RESTORE_RETRY_MS.length) _waitingAssistantTimer = setTimeout(() => attempt(n + 1), ASSISTANT_RESTORE_RETRY_MS[n]);
|
|
3570
|
+
return;
|
|
3571
|
+
}
|
|
3572
|
+
const waiting = _waitingAssistant;
|
|
3573
|
+
_waitingAssistant = [];
|
|
3574
|
+
// A late restore is silent: no panel opened, the active tab kept, each tab back where it was saved.
|
|
3575
|
+
const active = _sessions[_activeIdx] || null;
|
|
3576
|
+
const restored = [];
|
|
3577
|
+
_restoringLayout = true;
|
|
3578
|
+
try {
|
|
3579
|
+
for (const saved of waiting) {
|
|
3580
|
+
if (!live.has(saved.id) || _sessions.some(s => s.id === saved.id)) continue;
|
|
3581
|
+
try { const s = await reconnectAssistantSession(saved.id, live.get(saved.id), saved); if (s) restored.push(s); }
|
|
3582
|
+
catch (err) { console.warn('[assistant] reconnect failed:', saved.id, err); }
|
|
3583
|
+
}
|
|
3584
|
+
} finally { _restoringLayout = false; }
|
|
3585
|
+
if (active) _activeIdx = _sessions.indexOf(active);
|
|
3586
|
+
for (const s of restored) _placeLateAssistant(s, _waitingPlace.get(s.id));
|
|
3587
|
+
_waitingPlace.clear();
|
|
3588
|
+
if (active) _activeIdx = _sessions.indexOf(active);
|
|
3589
|
+
else {
|
|
3590
|
+
// Nothing was active: the first docked tab is, unhidden for when the panel is opened.
|
|
3591
|
+
_activeIdx = _sessions.findIndex(s => !_detachedTabs.has(s.id));
|
|
3592
|
+
const first = _sessions[_activeIdx];
|
|
3593
|
+
if (first?.viewport) first.viewport.style.display = '';
|
|
3594
|
+
}
|
|
3595
|
+
renderTabBar();
|
|
3596
|
+
saveSessionRegistry(); // prunes the ones whose sessions are really gone
|
|
3597
|
+
saveTerminalLayout();
|
|
3598
|
+
};
|
|
3599
|
+
_waitingAssistantTimer = setTimeout(() => attempt(1), ASSISTANT_RESTORE_RETRY_MS[0]);
|
|
3600
|
+
}
|
|
3601
|
+
|
|
3602
|
+
/** The restore that started the wait is done: pane switches from now on are the user's. */
|
|
3603
|
+
function _markLatePaneSwitches() {
|
|
3604
|
+
for (const place of _waitingPlace.values()) if (!place.switches) place.switches = [..._paneSwitches];
|
|
3605
|
+
}
|
|
3606
|
+
|
|
3607
|
+
/** A tab a late restore mounted goes where it was saved: its float, or its docked place in the saved order (and split pane). */
|
|
3608
|
+
function _placeLateAssistant(session, place) {
|
|
3609
|
+
if (place?.float) {
|
|
3610
|
+
if (session.viewport) session.viewport.style.display = '';
|
|
3611
|
+
applyTerminalLayout({ detachedTabs: [place.float] });
|
|
3612
|
+
return;
|
|
3613
|
+
}
|
|
3614
|
+
if (!_splitMode) { _orderLateAssistant(session, place?.order || []); return; }
|
|
3615
|
+
// Split is on, so both panes exist: its saved pane, else its neighbour's. The user's layout stays as it is.
|
|
3616
|
+
const paneActiveIds = _activePaneIdx.map(i => _sessions[i]?.id ?? null);
|
|
3617
|
+
const pane = place?.pane ?? null;
|
|
3618
|
+
let order = place?.order || [];
|
|
3619
|
+
if (pane != null) order = order.filter(id => id === session.id || _paneAssignments.get(id) === pane);
|
|
3620
|
+
const neighbour = _orderLateAssistant(session, order);
|
|
3621
|
+
const target = pane ?? _paneAssignments.get(neighbour?.id) ?? _focusedPane;
|
|
3622
|
+
_paneAssignments.set(session.id, target);
|
|
3623
|
+
_panel?.querySelector(`.term-pane[data-pane="${target}"] .term-pane-body`)?.appendChild(session.viewport);
|
|
3624
|
+
_activePaneIdx = paneActiveIds.map(id => _sessions.findIndex(s => s.id === id));
|
|
3625
|
+
// It was the pane's active tab and nobody switched tabs there since: it is again.
|
|
3626
|
+
const untouched = place?.switches && place.switches[target] === _paneSwitches[target];
|
|
3627
|
+
if (pane != null && place.paneActive && untouched) switchToSessionInPane(_sessions.indexOf(session), target);
|
|
3628
|
+
else if (session.viewport) session.viewport.style.display = 'none';
|
|
3629
|
+
}
|
|
3630
|
+
|
|
3631
|
+
/** Move a late tab next to its nearest neighbour in `order`; returns that neighbour (or null). */
|
|
3632
|
+
function _orderLateAssistant(session, order) {
|
|
3633
|
+
const at = order.indexOf(session.id);
|
|
3634
|
+
if (at < 0) return null; // not in the saved order: it stays last
|
|
3635
|
+
const from = _sessions.indexOf(session);
|
|
3636
|
+
_sessions.splice(from, 1);
|
|
3637
|
+
// After the nearest tab saved before it, else before the nearest saved after it, else last.
|
|
3638
|
+
let to = _sessions.length;
|
|
3639
|
+
const before = order.slice(0, at).reverse().map(id => _sessions.findIndex(s => s.id === id)).find(i => i >= 0);
|
|
3640
|
+
if (before !== undefined) to = before + 1;
|
|
3641
|
+
else {
|
|
3642
|
+
const after = order.slice(at + 1).map(id => _sessions.findIndex(s => s.id === id)).find(i => i >= 0);
|
|
3643
|
+
if (after !== undefined) to = after;
|
|
3644
|
+
}
|
|
3645
|
+
const neighbour = _sessions[to] || _sessions[to - 1] || null;
|
|
3646
|
+
_sessions.splice(to, 0, session);
|
|
3647
|
+
return neighbour;
|
|
3648
|
+
}
|
|
3649
|
+
|
|
3599
3650
|
async function reconnectAssistantSession(sessionId, live, saved) {
|
|
3600
3651
|
if (_assistantOwnedElsewhere(sessionId)) return null;
|
|
3601
3652
|
let meta = live || null;
|
|
@@ -4180,12 +4231,13 @@ function initContextMenu(viewport, term, getWs) {
|
|
|
4180
4231
|
menu.style.top = '0px';
|
|
4181
4232
|
menu.classList.add('open');
|
|
4182
4233
|
const rect = menu.getBoundingClientRect();
|
|
4234
|
+
const f = frameRect();
|
|
4183
4235
|
let x = e.clientX;
|
|
4184
4236
|
let y = e.clientY;
|
|
4185
|
-
if (x + rect.width >
|
|
4186
|
-
if (y + rect.height >
|
|
4187
|
-
if (x <
|
|
4188
|
-
if (y <
|
|
4237
|
+
if (x + rect.width > f.right) x = f.right - rect.width - 4;
|
|
4238
|
+
if (y + rect.height > f.bottom) y = e.clientY - rect.height;
|
|
4239
|
+
if (x < f.left) x = f.left + 4;
|
|
4240
|
+
if (y < f.top) y = f.top + 4;
|
|
4189
4241
|
menu.style.left = x + 'px';
|
|
4190
4242
|
menu.style.top = y + 'px';
|
|
4191
4243
|
|
|
@@ -4415,7 +4467,8 @@ function sendMemoryDrop(node, ws) {
|
|
|
4415
4467
|
ws.send(JSON.stringify({ type: 'memory_drop', content, title }));
|
|
4416
4468
|
}
|
|
4417
4469
|
|
|
4418
|
-
|
|
4470
|
+
// Also what the context menu sends to the AI panel (ui-context-menu.js).
|
|
4471
|
+
export function formatMemoryForCLI(node) {
|
|
4419
4472
|
const p = node.payload;
|
|
4420
4473
|
const parts = [];
|
|
4421
4474
|
|
|
@@ -4551,10 +4604,11 @@ function _placeFloatColorPicker(picker, colorBtn) {
|
|
|
4551
4604
|
const inset = first ? first.left + first.width / 2 - box.left : 0;
|
|
4552
4605
|
const margin = 8, gap = 6;
|
|
4553
4606
|
const left = btn.left + btn.width / 2 - inset;
|
|
4607
|
+
const f = frameRect();
|
|
4554
4608
|
let top = btn.top - gap - box.height;
|
|
4555
|
-
if (top < margin) top = btn.bottom + gap;
|
|
4556
|
-
picker.style.left = Math.max(margin, Math.min(left,
|
|
4557
|
-
picker.style.top = Math.max(margin, Math.min(top,
|
|
4609
|
+
if (top < f.top + margin) top = btn.bottom + gap;
|
|
4610
|
+
picker.style.left = Math.max(f.left + margin, Math.min(left, f.right - box.width - margin)) + 'px';
|
|
4611
|
+
picker.style.top = Math.max(f.top + margin, Math.min(top, f.bottom - box.height - margin)) + 'px';
|
|
4558
4612
|
}
|
|
4559
4613
|
|
|
4560
4614
|
function getRightPanelReservedWidth(cs = getComputedStyle(document.documentElement)) {
|
|
@@ -4563,17 +4617,24 @@ function getRightPanelReservedWidth(cs = getComputedStyle(document.documentEleme
|
|
|
4563
4617
|
|| 0;
|
|
4564
4618
|
}
|
|
4565
4619
|
|
|
4620
|
+
/** The app frame's area left for the floats: right of the explorers, left of a docked right sidepanel (its reserved
|
|
4621
|
+
* width counts from the window's right edge), below the bar. */
|
|
4622
|
+
function _usableArea(f = frameRect(), cs = getComputedStyle(document.documentElement)) {
|
|
4623
|
+
const reserved = getRightPanelReservedWidth(cs);
|
|
4624
|
+
return { left: f.left, top: f.top, right: Math.max(f.left, Math.min(f.right, window.innerWidth - reserved)), bottom: f.bottom };
|
|
4625
|
+
}
|
|
4626
|
+
|
|
4566
4627
|
/** Update snapped-edge classes on all floating tabs based on adjacency */
|
|
4567
|
-
/** Compute
|
|
4628
|
+
/** Compute frame/panel snap boundaries (getComputedStyle reads — cache during drag) */
|
|
4568
4629
|
function _snapEnv() {
|
|
4569
|
-
const
|
|
4570
|
-
const
|
|
4571
|
-
const fileExplorerW = parseFloat(cs.getPropertyValue('--file-explorer-width')) || 0;
|
|
4630
|
+
const f = frameRect();
|
|
4631
|
+
const area = _usableArea(f);
|
|
4572
4632
|
return {
|
|
4573
|
-
leftPanelEdge:
|
|
4574
|
-
rightPanelEdge:
|
|
4575
|
-
|
|
4576
|
-
|
|
4633
|
+
leftPanelEdge: f.left,
|
|
4634
|
+
rightPanelEdge: area.right,
|
|
4635
|
+
frameRight: f.right,
|
|
4636
|
+
topEdge: f.top,
|
|
4637
|
+
bottomEdge: f.bottom,
|
|
4577
4638
|
};
|
|
4578
4639
|
}
|
|
4579
4640
|
|
|
@@ -4591,7 +4652,7 @@ function _updateSnappedEdges(rectsOverride, envOverride) {
|
|
|
4591
4652
|
}
|
|
4592
4653
|
}
|
|
4593
4654
|
|
|
4594
|
-
const { leftPanelEdge, rightPanelEdge, topEdge, bottomEdge } = envOverride || _snapEnv();
|
|
4655
|
+
const { leftPanelEdge, rightPanelEdge, frameRight, topEdge, bottomEdge } = envOverride || _snapEnv();
|
|
4595
4656
|
|
|
4596
4657
|
for (const [sid, dt] of _detachedTabs) {
|
|
4597
4658
|
if (!dt.el || dt.minimized) continue;
|
|
@@ -4611,8 +4672,8 @@ function _updateSnappedEdges(rectsOverride, envOverride) {
|
|
|
4611
4672
|
}
|
|
4612
4673
|
|
|
4613
4674
|
// Check adjacency to viewport / panel edges
|
|
4614
|
-
if (Math.abs(me.left - leftPanelEdge) < TOLERANCE
|
|
4615
|
-
if (Math.abs(me.right - rightPanelEdge) < TOLERANCE || Math.abs(me.right -
|
|
4675
|
+
if (Math.abs(me.left - leftPanelEdge) < TOLERANCE) edges.left = true;
|
|
4676
|
+
if (Math.abs(me.right - rightPanelEdge) < TOLERANCE || Math.abs(me.right - frameRight) < TOLERANCE) edges.right = true;
|
|
4616
4677
|
if (Math.abs(me.top - topEdge) < TOLERANCE) edges.top = true;
|
|
4617
4678
|
if (Math.abs(me.bottom - bottomEdge) < TOLERANCE) edges.bottom = true;
|
|
4618
4679
|
|
|
@@ -4668,20 +4729,16 @@ export function tileFloatingTerminals() {
|
|
|
4668
4729
|
}
|
|
4669
4730
|
if (entries.length === 0) return;
|
|
4670
4731
|
|
|
4671
|
-
// Compute available
|
|
4672
|
-
|
|
4673
|
-
const
|
|
4674
|
-
const fileExplorerW = parseFloat(cs.getPropertyValue('--file-explorer-width')) || 0;
|
|
4675
|
-
const sidebarW = explorerW + fileExplorerW;
|
|
4676
|
-
const rightPanelW = getRightPanelReservedWidth(cs);
|
|
4732
|
+
// Compute the available area: the app frame, minus a docked right sidepanel and the docked terminal (which sits
|
|
4733
|
+
// 12px inside the frame's bottom: the tiles stop at its top)
|
|
4734
|
+
const area = _usableArea();
|
|
4677
4735
|
const termPanel = document.getElementById('terminal-panel');
|
|
4678
|
-
const
|
|
4679
|
-
? termPanel.getBoundingClientRect().
|
|
4680
|
-
const
|
|
4681
|
-
const
|
|
4682
|
-
const
|
|
4683
|
-
const
|
|
4684
|
-
const areaH = window.innerHeight - TOP_PAD - termH;
|
|
4736
|
+
const termTop = (termPanel && !termPanel.classList.contains('hidden') && !termPanel.classList.contains('detached'))
|
|
4737
|
+
? termPanel.getBoundingClientRect().top : area.bottom;
|
|
4738
|
+
const areaL = area.left;
|
|
4739
|
+
const areaT = area.top;
|
|
4740
|
+
const areaW = Math.max(0, area.right - area.left);
|
|
4741
|
+
const areaH = Math.max(0, Math.min(area.bottom, termTop) - area.top);
|
|
4685
4742
|
|
|
4686
4743
|
// Calculate grid: find best cols/rows to fill the space
|
|
4687
4744
|
const n = entries.length;
|
|
@@ -4732,17 +4789,16 @@ function _defaultFloatRect(kind = {}) {
|
|
|
4732
4789
|
const offset = _detachedTabs.size * 30;
|
|
4733
4790
|
const isBrowser = kind.profile === 'browser';
|
|
4734
4791
|
const isAssistant = !!kind._isAssistant || kind.profile === 'assistant';
|
|
4735
|
-
const
|
|
4736
|
-
const leftEdge = (
|
|
4737
|
-
+ (parseFloat(cs.getPropertyValue('--file-explorer-width')) || 0);
|
|
4738
|
-
const rightEdge = window.innerWidth - getRightPanelReservedWidth(cs);
|
|
4792
|
+
const f = frameRect();
|
|
4793
|
+
const { left: leftEdge, right: rightEdge } = _usableArea(f);
|
|
4739
4794
|
const usableW = Math.max(0, rightEdge - leftEdge);
|
|
4740
4795
|
// Assistant floats default to 780×560 (chat + agents dock need more room than a TUI)
|
|
4741
4796
|
const w = Math.round(Math.min(isBrowser ? 960 : (isAssistant ? 780 : 700), usableW * (isBrowser ? 0.65 : (isAssistant ? 0.6 : 0.5))));
|
|
4742
|
-
const h = Math.round(Math.min(isBrowser ? 640 : (isAssistant ? 560 : 420),
|
|
4797
|
+
const h = Math.round(Math.min(isBrowser ? 640 : (isAssistant ? 560 : 420), f.height * (isBrowser ? 0.6 : (isAssistant ? 0.7 : 0.5))));
|
|
4798
|
+
const at = clampBox(leftEdge + (usableW - w) / 2 + offset, f.top + (f.height - h) / 2 + offset, w, h, f);
|
|
4743
4799
|
return {
|
|
4744
|
-
left: Math.round(
|
|
4745
|
-
top: Math.round(
|
|
4800
|
+
left: Math.round(at.x),
|
|
4801
|
+
top: Math.round(at.y),
|
|
4746
4802
|
width: w,
|
|
4747
4803
|
height: h,
|
|
4748
4804
|
};
|
|
@@ -4792,10 +4848,6 @@ function detachTab(idx, opts = {}) {
|
|
|
4792
4848
|
<span class="term-float-tab-icon">${prof?.svg || SVG_SHELL}</span>
|
|
4793
4849
|
<button class="term-float-color-strip" data-tooltip="Change color"></button>
|
|
4794
4850
|
<span class="term-float-tab-title">${_escHtml(_displayLabel(session))}</span>${session._isAssistant ? '<span class="term-float-brain-chip" data-tooltip="Brain" hidden></span>' : ''}${_cliBadgeHtml(session.id)}
|
|
4795
|
-
${CLI_PROFILES_NEED_PROFILER.has(session.profile) ? `<div class="term-float-profile-dd" data-tooltip="Tool profile">
|
|
4796
|
-
<button class="term-float-profile-btn"><span class="term-float-profile-label">...</span><span class="term-float-profile-arrow">▾</span></button>
|
|
4797
|
-
<div class="term-float-profile-menu"></div>
|
|
4798
|
-
</div>` : ''}
|
|
4799
4851
|
${CLI_PROFILES_NEED_RECALL.has(session.profile) ? `<div class="term-float-recall-dd" data-tooltip="Recall profile">
|
|
4800
4852
|
<button class="term-float-recall-btn"><span class="term-float-recall-label">...</span><span class="term-float-recall-arrow">▾</span></button>
|
|
4801
4853
|
<div class="term-float-recall-menu"></div>
|
|
@@ -5018,11 +5070,6 @@ function detachTab(idx, opts = {}) {
|
|
|
5018
5070
|
});
|
|
5019
5071
|
}
|
|
5020
5072
|
|
|
5021
|
-
// Wire MCP profile dropdown (CLI profiles only)
|
|
5022
|
-
const profileDd = win.querySelector('.term-float-profile-dd');
|
|
5023
|
-
if (profileDd) {
|
|
5024
|
-
_initFloatProfileDropdown(profileDd);
|
|
5025
|
-
}
|
|
5026
5073
|
|
|
5027
5074
|
// Wire recall profile dropdown
|
|
5028
5075
|
const recallDd = win.querySelector('.term-float-recall-dd');
|
|
@@ -5306,7 +5353,7 @@ function initTabFloatDrag(win, sessionId) {
|
|
|
5306
5353
|
|
|
5307
5354
|
function _checkHeader(target) {
|
|
5308
5355
|
const header = target.closest('.term-float-tab-header');
|
|
5309
|
-
if (!header || target.closest('button
|
|
5356
|
+
if (!header || target.closest('button')) return false;
|
|
5310
5357
|
const session = _sessions.find(s => s.id === sessionId);
|
|
5311
5358
|
return !session?.pinned;
|
|
5312
5359
|
}
|
|
@@ -5343,8 +5390,9 @@ function initTabFloatDrag(win, sessionId) {
|
|
|
5343
5390
|
const KEEP = 80;
|
|
5344
5391
|
const w = drag.startW || parseFloat(win.style.width) || 700;
|
|
5345
5392
|
const h = drag.startH || parseFloat(win.style.height) || 420;
|
|
5346
|
-
|
|
5347
|
-
|
|
5393
|
+
const env = drag.snapEnv;
|
|
5394
|
+
const frame = { left: env.leftPanelEdge, top: env.topEdge, right: env.frameRight, bottom: env.bottomEdge };
|
|
5395
|
+
({ x: finalL, y: finalT } = clampBoxLoose(finalL, finalT, w, h, frame, KEEP));
|
|
5348
5396
|
|
|
5349
5397
|
// Snap to other floating windows (rects cached at drag start)
|
|
5350
5398
|
const SNAP_DIST = 12;
|
|
@@ -5375,11 +5423,12 @@ function initTabFloatDrag(win, sessionId) {
|
|
|
5375
5423
|
else if (Math.abs(myB - or.bottom) < SNAP_DIST) { finalT = or.bottom - h; snapped = true; }
|
|
5376
5424
|
}
|
|
5377
5425
|
}
|
|
5378
|
-
// Also snap to
|
|
5379
|
-
if (Math.abs(finalL) < SNAP_DIST) { finalL =
|
|
5380
|
-
if (Math.abs(finalT -
|
|
5381
|
-
if (Math.abs(myR -
|
|
5382
|
-
if (Math.abs(
|
|
5426
|
+
// Also snap to the app frame's edges (and a docked right sidepanel's)
|
|
5427
|
+
if (Math.abs(finalL - frame.left) < SNAP_DIST) { finalL = frame.left; snapped = true; }
|
|
5428
|
+
if (Math.abs(finalT - frame.top) < SNAP_DIST) { finalT = frame.top; snapped = true; }
|
|
5429
|
+
if (Math.abs(myR - frame.right) < SNAP_DIST) { finalL = frame.right - w; snapped = true; }
|
|
5430
|
+
else if (Math.abs(myR - env.rightPanelEdge) < SNAP_DIST) { finalL = env.rightPanelEdge - w; snapped = true; }
|
|
5431
|
+
if (Math.abs(myB - frame.bottom) < SNAP_DIST) { finalT = frame.bottom - h; snapped = true; }
|
|
5383
5432
|
|
|
5384
5433
|
win.classList.toggle('float-snapping', snapped);
|
|
5385
5434
|
// Transform-based positioning: left/top force layout every frame; a
|
|
@@ -5498,7 +5547,9 @@ function initTabFloatResize(win, sessionId) {
|
|
|
5498
5547
|
nl = Math.round(nl / gs) * gs; nt = Math.round(nt / gs) * gs;
|
|
5499
5548
|
nw = Math.round(nw / gs) * gs; nh = Math.round(nh / gs) * gs;
|
|
5500
5549
|
}
|
|
5501
|
-
|
|
5550
|
+
// The header never goes above the app frame's top (a top edge stops there, the bottom edge stays put)
|
|
5551
|
+
const frameTop = frameRect().top;
|
|
5552
|
+
if (nt < frameTop) { if (dir.includes('n')) nh = Math.max(MIN_H, nh - (frameTop - nt)); nt = frameTop; }
|
|
5502
5553
|
win.style.left = nl + 'px';
|
|
5503
5554
|
win.style.top = nt + 'px';
|
|
5504
5555
|
win.style.width = nw + 'px';
|
|
@@ -5841,41 +5892,48 @@ export async function initTerminal() {
|
|
|
5841
5892
|
}
|
|
5842
5893
|
});
|
|
5843
5894
|
|
|
5844
|
-
// ── Window resize —
|
|
5895
|
+
// ── Window resize, an explorer opening or closing — keep the floats in the app frame, refit all terminals ──
|
|
5896
|
+
const clampFloatsToFrame = () => {
|
|
5897
|
+
const f = frameRect();
|
|
5898
|
+
const KEEP = 80; // min px of tab that must remain visible
|
|
5899
|
+
const floats = [..._detachedTabs.values()].filter(tabState => !tabState.minimized).map(tabState => tabState.el);
|
|
5900
|
+
if (_detached && _panel && !_panel.classList.contains('hidden')) floats.push(_panel);
|
|
5901
|
+
|
|
5902
|
+
for (const el of floats) {
|
|
5903
|
+
if (!el) continue;
|
|
5904
|
+
let l = parseFloat(el.style.left) || 0;
|
|
5905
|
+
let t = parseFloat(el.style.top) || 0;
|
|
5906
|
+
let w = parseFloat(el.style.width) || 700;
|
|
5907
|
+
let h = parseFloat(el.style.height) || 420;
|
|
5908
|
+
|
|
5909
|
+
// Clamp dimensions to the frame
|
|
5910
|
+
w = Math.min(w, f.width);
|
|
5911
|
+
h = Math.min(h, f.height);
|
|
5912
|
+
|
|
5913
|
+
// Clamp position so the header stays reachable, below the title bar and right of the explorers
|
|
5914
|
+
({ x: l, y: t } = clampBoxLoose(l, t, w, h, f, KEEP));
|
|
5915
|
+
|
|
5916
|
+
el.style.left = l + 'px';
|
|
5917
|
+
el.style.top = t + 'px';
|
|
5918
|
+
el.style.width = w + 'px';
|
|
5919
|
+
el.style.height = h + 'px';
|
|
5920
|
+
}
|
|
5921
|
+
|
|
5922
|
+
// Refit all terminals to new dimensions
|
|
5923
|
+
_sessions.forEach(s => _scheduleFit(s));
|
|
5924
|
+
};
|
|
5845
5925
|
window.addEventListener('resize', () => {
|
|
5846
5926
|
if (_windowResizeTimer) clearTimeout(_windowResizeTimer);
|
|
5847
5927
|
_windowResizeTimer = setTimeout(() => {
|
|
5848
5928
|
_windowResizeTimer = null;
|
|
5849
|
-
|
|
5850
|
-
const vh = window.innerHeight;
|
|
5851
|
-
const KEEP = 80; // min px of tab that must remain visible
|
|
5852
|
-
|
|
5853
|
-
for (const [, tabState] of _detachedTabs) {
|
|
5854
|
-
if (tabState.minimized) continue;
|
|
5855
|
-
const el = tabState.el;
|
|
5856
|
-
let l = parseFloat(el.style.left) || 0;
|
|
5857
|
-
let t = parseFloat(el.style.top) || 0;
|
|
5858
|
-
let w = parseFloat(el.style.width) || 700;
|
|
5859
|
-
let h = parseFloat(el.style.height) || 420;
|
|
5860
|
-
|
|
5861
|
-
// Clamp dimensions to viewport
|
|
5862
|
-
w = Math.min(w, vw);
|
|
5863
|
-
h = Math.min(h, vh);
|
|
5864
|
-
|
|
5865
|
-
// Clamp position so header stays reachable and below title bar
|
|
5866
|
-
l = Math.max(KEEP - w, Math.min(l, vw - KEEP));
|
|
5867
|
-
t = Math.max(48, Math.min(t, vh - KEEP));
|
|
5868
|
-
|
|
5869
|
-
el.style.left = l + 'px';
|
|
5870
|
-
el.style.top = t + 'px';
|
|
5871
|
-
el.style.width = w + 'px';
|
|
5872
|
-
el.style.height = h + 'px';
|
|
5873
|
-
}
|
|
5874
|
-
|
|
5875
|
-
// Refit all terminals to new dimensions
|
|
5876
|
-
_sessions.forEach(s => _scheduleFit(s));
|
|
5929
|
+
clampFloatsToFrame();
|
|
5877
5930
|
}, 150);
|
|
5878
5931
|
});
|
|
5932
|
+
onFrameChange(() => {
|
|
5933
|
+
if (_windowResizeTimer) return; // the resize pass runs shortly
|
|
5934
|
+
clampFloatsToFrame();
|
|
5935
|
+
_updateSnappedEdges();
|
|
5936
|
+
});
|
|
5879
5937
|
|
|
5880
5938
|
// ── Visibility change — flow control, warm renderers, one focus target ──
|
|
5881
5939
|
document.addEventListener('visibilitychange', () => {
|
|
@@ -6055,7 +6113,7 @@ export async function initTerminal() {
|
|
|
6055
6113
|
// Register CLI launch keybind actions (open as detached floating tab)
|
|
6056
6114
|
registerAction('launch-claude', () => launchDetached('claude-code'));
|
|
6057
6115
|
registerAction('launch-codex', () => launchDetached('codex'));
|
|
6058
|
-
registerAction('launch-
|
|
6116
|
+
registerAction('launch-antigravity', () => launchDetached('antigravity'));
|
|
6059
6117
|
registerAction('launch-opencode', () => launchDetached('opencode'));
|
|
6060
6118
|
registerAction('launch-browser', () => openBrowserSession());
|
|
6061
6119
|
registerAction('launch-youtube', () => openBrowserSession('https://www.youtube.com'));
|
|
@@ -6184,7 +6242,17 @@ export async function initTerminal() {
|
|
|
6184
6242
|
const liveBrowserMap = _streamDisabled ? new Map() : new Map(liveBrowserSessions.map(s => [s.id, s]));
|
|
6185
6243
|
|
|
6186
6244
|
// Fetch live assistant sessions (only when the registry has assistant tabs)
|
|
6187
|
-
|
|
6245
|
+
// A failed read is not an empty list: keep those tabs waiting and retry.
|
|
6246
|
+
let liveAssistantMap = new Map();
|
|
6247
|
+
if (registry.some(r => r.profile === 'assistant')) {
|
|
6248
|
+
const read = await readLiveAssistantSessions();
|
|
6249
|
+
if (read) liveAssistantMap = read;
|
|
6250
|
+
else {
|
|
6251
|
+
let layout = null;
|
|
6252
|
+
try { layout = JSON.parse(storage.getItem(KEYS.TERMINAL_SESSIONS + '-layout') || 'null'); } catch {}
|
|
6253
|
+
_waitAssistantRestore(registry.filter(r => r.profile === 'assistant'), { layout, order: registry });
|
|
6254
|
+
}
|
|
6255
|
+
}
|
|
6188
6256
|
|
|
6189
6257
|
const liveIds = new Set([...liveMap.keys(), ...liveBrowserMap.keys(), ...liveAssistantMap.keys()]);
|
|
6190
6258
|
|
|
@@ -6249,6 +6317,8 @@ export async function initTerminal() {
|
|
|
6249
6317
|
_syncRenderers();
|
|
6250
6318
|
}
|
|
6251
6319
|
|
|
6320
|
+
_markLatePaneSwitches();
|
|
6321
|
+
|
|
6252
6322
|
// Clean up dead sessions from registry
|
|
6253
6323
|
if (toReconnect.length !== registry.length) {
|
|
6254
6324
|
saveSessionRegistry();
|
|
@@ -6482,11 +6552,13 @@ async function attachDetached(terminalSessionId, profile, initialMessage, autoSu
|
|
|
6482
6552
|
if (dt?.el) {
|
|
6483
6553
|
const panelWidth = getRightPanelReservedWidth();
|
|
6484
6554
|
if (panelWidth > 0) {
|
|
6485
|
-
|
|
6486
|
-
const
|
|
6487
|
-
const
|
|
6488
|
-
|
|
6489
|
-
|
|
6555
|
+
// Beside the panel, 24px from its slot, at the top of the app frame
|
|
6556
|
+
const f = frameRect();
|
|
6557
|
+
const area = _usableArea(f);
|
|
6558
|
+
const w = Math.min(700, Math.max(0, area.right - area.left - 16) * 0.6);
|
|
6559
|
+
const h = Math.min(500, f.height - 40);
|
|
6560
|
+
dt.el.style.left = Math.max(f.left, area.right - w - 24) + 'px';
|
|
6561
|
+
dt.el.style.top = f.top + 'px';
|
|
6490
6562
|
dt.el.style.width = w + 'px';
|
|
6491
6563
|
dt.el.style.height = h + 'px';
|
|
6492
6564
|
}
|
|
@@ -6669,10 +6741,11 @@ function applyTerminalLayout(snap) {
|
|
|
6669
6741
|
const minW = 280, minH = 160;
|
|
6670
6742
|
const w = Math.max(minW, dt.width || minW);
|
|
6671
6743
|
const h = Math.max(minH, dt.height || minH);
|
|
6672
|
-
const
|
|
6673
|
-
const
|
|
6674
|
-
const
|
|
6675
|
-
const
|
|
6744
|
+
const f = frameRect();
|
|
6745
|
+
const maxL = f.right - 80;
|
|
6746
|
+
const maxT = f.bottom - 40;
|
|
6747
|
+
const l = Math.max(f.left, Math.min(dt.left || 0, maxL));
|
|
6748
|
+
const t = Math.max(f.top, Math.min(dt.top || 0, maxT));
|
|
6676
6749
|
|
|
6677
6750
|
tabState.el.style.left = l + 'px';
|
|
6678
6751
|
tabState.el.style.top = t + 'px';
|
|
@@ -6764,7 +6837,12 @@ export async function restoreTerminalSnapshot(snap) {
|
|
|
6764
6837
|
} catch {}
|
|
6765
6838
|
const liveMap = new Map(liveSessions.map(s => [s.id, s]));
|
|
6766
6839
|
const liveIds = new Set(liveMap.keys());
|
|
6767
|
-
|
|
6840
|
+
let liveAssistantMap = new Map();
|
|
6841
|
+
if (snap.sessions.some(s => s.profile === 'assistant')) {
|
|
6842
|
+
const read = await readLiveAssistantSessions();
|
|
6843
|
+
if (read) liveAssistantMap = read;
|
|
6844
|
+
else _waitAssistantRestore(snap.sessions.filter(s => s.profile === 'assistant'), { layout: snap, order: snap.sessions });
|
|
6845
|
+
}
|
|
6768
6846
|
|
|
6769
6847
|
// Disconnect current sessions without killing server PTY
|
|
6770
6848
|
disconnectAllSessions();
|
|
@@ -6801,6 +6879,7 @@ export async function restoreTerminalSnapshot(snap) {
|
|
|
6801
6879
|
const firstDocked = _sessions.findIndex(s => !_detachedTabs.has(s.id));
|
|
6802
6880
|
if (firstDocked >= 0 && !_splitMode) switchToSession(firstDocked, { force: true });
|
|
6803
6881
|
_syncRenderers();
|
|
6882
|
+
_markLatePaneSwitches();
|
|
6804
6883
|
}
|
|
6805
6884
|
|
|
6806
6885
|
// ══════════════════════════════════════════
|
|
@@ -7706,6 +7785,7 @@ function initSplitDivider() {
|
|
|
7706
7785
|
function switchToSessionInPane(idx, pane) {
|
|
7707
7786
|
if (idx < 0 || idx >= _sessions.length) return;
|
|
7708
7787
|
_activePaneIdx[pane] = idx;
|
|
7788
|
+
if (!_restoringLayout) _paneSwitches[pane]++;
|
|
7709
7789
|
|
|
7710
7790
|
// Show/hide viewports within this pane only
|
|
7711
7791
|
const paneBody = _panel?.querySelector(`.term-pane[data-pane="${pane}"] .term-pane-body`);
|