synabun 2.1.0 → 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 +121 -0
- package/README.md +1 -1
- package/docs/whatsapp.md +11 -11
- package/lib/client-config-repair.js +13 -9
- package/lib/external-tools.js +6 -5
- package/lib/update-snapshot.js +77 -3
- package/lib/virustotal.mjs +12 -1
- package/mcp-server/dist/index.js +1 -1
- package/mcp-server/dist/index.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/identity.d.ts +2 -2
- package/mcp-server/dist/services/identity.js +2 -2
- 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 +2 -1
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
- package/mcp-server/dist/services/server-instructions.js +2 -1
- package/mcp-server/dist/services/server-instructions.js.map +1 -1
- package/mcp-server/dist/services/tool-catalog.js +1 -1
- package/mcp-server/dist/services/tool-catalog.js.map +1 -1
- package/mcp-server/dist/services/tool-list.d.ts +1 -1
- package/mcp-server/dist/services/tool-list.d.ts.map +1 -1
- package/mcp-server/dist/services/tool-runtime.d.ts +2 -2
- package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -1
- package/mcp-server/dist/services/tool-runtime.js +1 -1
- package/mcp-server/dist/services/tool-runtime.js.map +1 -1
- 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/tools/agents.d.ts +8 -8
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +10 -9
- package/mcp-server/dist/tools/agents.js.map +1 -1
- 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/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 +8 -8
- package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/skill-tools.js +11 -8
- package/mcp-server/dist/tools/skill-tools.js.map +1 -1
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/src/index.ts +1 -1
- package/mcp-server/src/services/budget-judgments.ts +5 -3
- package/mcp-server/src/services/identity.ts +2 -2
- package/mcp-server/src/services/memory-sessions.ts +24 -3
- package/mcp-server/src/services/neural-interface.ts +2 -1
- package/mcp-server/src/services/server-instructions.ts +2 -1
- package/mcp-server/src/services/tool-catalog.ts +1 -1
- package/mcp-server/src/services/tool-list.ts +1 -1
- package/mcp-server/src/services/tool-runtime.ts +2 -2
- package/mcp-server/src/services/typesafe-config.ts +1 -1
- package/mcp-server/src/tools/agents.ts +10 -9
- package/mcp-server/src/tools/choice.ts +17 -12
- package/mcp-server/src/tools/git-tools.ts +2 -2
- package/mcp-server/src/tools/morelogin.ts +6 -4
- package/mcp-server/src/tools/skill-tools.ts +11 -8
- package/neural-interface/i18n/en.json +501 -39
- package/neural-interface/i18n/pt-BR.json +501 -39
- 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 +1 -0
- package/neural-interface/lib/assistant-brains/antigravity.js +423 -0
- 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 +76 -9
- package/neural-interface/lib/assistant-config.js +6 -3
- package/neural-interface/lib/assistant-dispatch.js +207 -49
- package/neural-interface/lib/assistant-envelope.js +153 -1
- 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 +16 -11
- package/neural-interface/lib/assistant-plan-permissions.js +15 -0
- package/neural-interface/lib/assistant-router.js +237 -35
- package/neural-interface/lib/assistant-runtime.js +158 -12
- package/neural-interface/lib/assistant-task-prompt.js +10 -8
- package/neural-interface/lib/assistant-tools.js +2 -2
- package/neural-interface/lib/assistant-usage.js +29 -0
- package/neural-interface/lib/backup-service.js +6 -1
- package/neural-interface/lib/browser-guard-cdp.js +5 -4
- package/neural-interface/lib/browser-network-guard.js +274 -82
- package/neural-interface/lib/browser-tool-policy.js +12 -7
- package/neural-interface/lib/claude-agent-bridge.js +7 -0
- package/neural-interface/lib/claude-history-cache.js +210 -0
- package/neural-interface/lib/claude-model-catalog.js +5 -1
- package/neural-interface/lib/cli-install-api.js +1 -1
- package/neural-interface/lib/cli-install.js +160 -31
- package/neural-interface/lib/cli-resolver.js +9 -2
- package/neural-interface/lib/cli-update-planner.js +25 -15
- package/neural-interface/lib/codex-rollout-reader.js +52 -0
- package/neural-interface/lib/codex-worker-app-server.js +25 -6
- package/neural-interface/lib/editor-git-api.js +3 -20
- package/neural-interface/lib/exec-loop-command.js +9 -2
- 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/mcp-client-config.js +37 -6
- package/neural-interface/lib/mcp-external-servers.js +13 -4
- package/neural-interface/lib/mcp-installer.js +2 -1
- package/neural-interface/lib/memory-session-capture.js +17 -3
- package/neural-interface/lib/morelogin.js +147 -25
- package/neural-interface/lib/native-loop-providers.js +420 -21
- package/neural-interface/lib/native-loop-runtime.js +23 -2
- package/neural-interface/lib/opencode-native-boundary.js +11 -2
- package/neural-interface/lib/owner-authority.js +1 -1
- package/neural-interface/lib/path-confine.js +12 -9
- package/neural-interface/lib/peer-identity.js +32 -2
- 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 +3 -0
- package/neural-interface/lib/rulesets/api.js +6 -5
- package/neural-interface/lib/rulesets/fs-safe.js +1 -1
- package/neural-interface/lib/rulesets/installer.js +89 -10
- package/neural-interface/lib/rulesets/render.js +1 -1
- package/neural-interface/lib/session-cache-builder.js +64 -1
- package/neural-interface/lib/skills/catalog.js +5 -1
- package/neural-interface/lib/skills/creation-brief.js +1 -1
- package/neural-interface/lib/skills/creation-sources.js +19 -1
- package/neural-interface/lib/skills/deploy.js +9 -4
- package/neural-interface/lib/skills/draft-confinement.js +3 -1
- package/neural-interface/lib/skills/eval-confinement.js +3 -1
- package/neural-interface/lib/skills/eval-trace.js +16 -0
- package/neural-interface/lib/skills/export.js +5 -2
- package/neural-interface/lib/skills/known-bridge-digests.json +58 -4
- package/neural-interface/lib/skills/ownership.js +1 -1
- package/neural-interface/lib/skills/roots.js +10 -3
- package/neural-interface/lib/skills/runtime-checks.js +6 -3
- package/neural-interface/lib/skills/service.js +15 -7
- package/neural-interface/lib/skills/telemetry.js +6 -0
- package/neural-interface/lib/synabun-version.js +1 -1
- package/neural-interface/lib/system-activity.js +1 -1
- package/neural-interface/lib/whatsapp/brain.js +7 -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 +77 -1
- package/neural-interface/lib/worker-question.js +74 -0
- package/neural-interface/lib/worker-resume.js +13 -4
- package/neural-interface/lib/worker-sandbox.js +46 -16
- package/neural-interface/package-lock.json +18 -2
- package/neural-interface/package.json +2 -1
- package/neural-interface/public/onboarding.html +1 -1
- package/neural-interface/public/shared/agent-runtime-options.js +89 -11
- 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 +4 -4
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +3 -4
- package/neural-interface/public/shared/assistant/asst-api.js +1 -1
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +56 -9
- package/neural-interface/public/shared/assistant/asst-budget.js +5 -4
- package/neural-interface/public/shared/assistant/asst-control.js +48 -0
- package/neural-interface/public/shared/assistant/asst-hosts.js +16 -7
- package/neural-interface/public/shared/assistant/asst-limit-dock.js +6 -1
- package/neural-interface/public/shared/assistant/asst-limit-wait.js +38 -5
- package/neural-interface/public/shared/assistant/asst-panel.js +45 -8
- package/neural-interface/public/shared/assistant/asst-render.js +51 -12
- package/neural-interface/public/shared/assistant/asst-route.js +237 -57
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +9 -8
- package/neural-interface/public/shared/assistant/asst-scenes.js +54 -1
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +51 -7
- package/neural-interface/public/shared/assistant/asst-slash.js +8 -2
- package/neural-interface/public/shared/assistant/asst-state.js +76 -9
- package/neural-interface/public/shared/assistant/asst-styles.js +34 -0
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +34 -7
- package/neural-interface/public/shared/assistant/asst-usage.js +2 -1
- package/neural-interface/public/shared/cdx/cdx-output.js +26 -3
- package/neural-interface/public/shared/cdx/cdx-panel.js +14 -2
- package/neural-interface/public/shared/cdx/cdx-preview.js +12 -0
- package/neural-interface/public/shared/cdx/cdx-protocol.js +11 -10
- package/neural-interface/public/shared/cdx/cdx-render.js +10 -9
- package/neural-interface/public/shared/cdx/cdx-requests.js +11 -1
- package/neural-interface/public/shared/cdx/cdx-styles.js +4 -0
- package/neural-interface/public/shared/cdx/cdx-tabs.js +75 -5
- package/neural-interface/public/shared/cli-install-controller.js +218 -0
- package/neural-interface/public/shared/cli-install-view.js +7 -4
- package/neural-interface/public/shared/cli-status.js +9 -8
- package/neural-interface/public/shared/constants.js +3 -2
- package/neural-interface/public/shared/context-menu-model.js +1 -0
- 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/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 +1 -0
- 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 +21 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +27 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +13 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +17 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +46 -3
- package/neural-interface/public/shared/provider-icons.js +4 -2
- package/neural-interface/public/shared/settings/settings-rules.js +2 -2
- package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +1 -1
- package/neural-interface/public/shared/settings/settings-skill-folders.js +2 -2
- 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-creation.js +6 -3
- package/neural-interface/public/shared/skills/ss-dialog.js +5 -2
- package/neural-interface/public/shared/skills/ss-lint.js +9 -1
- package/neural-interface/public/shared/skills/ss-profiles.js +44 -6
- package/neural-interface/public/shared/skills/ss-review-view.js +2 -2
- package/neural-interface/public/shared/skills/studio/sx-actions.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-create-ai.js +2 -1
- package/neural-interface/public/shared/skills/studio/sx-dom.js +2 -1
- 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-inspector.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-install-flow.js +9 -6
- package/neural-interface/public/shared/skills/studio/sx-install.js +20 -3
- package/neural-interface/public/shared/skills/studio/sx-library-view.js +144 -35
- package/neural-interface/public/shared/skills/studio/sx-library.js +6 -2
- package/neural-interface/public/shared/skills/studio/sx-main.js +11 -2
- package/neural-interface/public/shared/skills/studio/sx-review-view.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-subject.js +7 -6
- package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +6 -5
- package/neural-interface/public/shared/state.js +1 -1
- package/neural-interface/public/shared/streaming-markdown.js +58 -0
- package/neural-interface/public/shared/styles.css +354 -34
- package/neural-interface/public/shared/text-cache.js +29 -0
- package/neural-interface/public/shared/tool-list-picker.js +2 -2
- package/neural-interface/public/shared/tool-list-view.js +2 -2
- package/neural-interface/public/shared/topright-overflow-logic.js +54 -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 +20 -12
- package/neural-interface/public/shared/ui-claude-panel.js +299 -77
- package/neural-interface/public/shared/ui-cli-banner.js +23 -167
- 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-judgments.js +1 -1
- package/neural-interface/public/shared/ui-keybinds.js +8 -2
- package/neural-interface/public/shared/ui-link.js +3 -3
- package/neural-interface/public/shared/ui-menubar.js +2 -2
- package/neural-interface/public/shared/ui-native-loop-router.js +4 -0
- package/neural-interface/public/shared/ui-navbar.js +45 -0
- package/neural-interface/public/shared/ui-notifications.js +1 -0
- package/neural-interface/public/shared/ui-resume.js +9 -7
- package/neural-interface/public/shared/ui-schedules-studio.js +41 -10
- package/neural-interface/public/shared/ui-scroll-follow.js +16 -5
- package/neural-interface/public/shared/ui-sessions.js +22 -12
- package/neural-interface/public/shared/ui-settings.js +90 -65
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +9 -2
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +3 -3
- package/neural-interface/public/shared/ui-sidepanel-tray.js +48 -7
- package/neural-interface/public/shared/ui-sidepanel-windows.js +3 -3
- package/neural-interface/public/shared/ui-terminal.js +146 -10
- package/neural-interface/public/shared/ui-tool-updates.js +3 -3
- package/neural-interface/public/shared/ui-tooltip.js +71 -46
- package/neural-interface/public/shared/ui-topright-overflow.js +233 -0
- package/neural-interface/public/shared/ui-whiteboard.js +1 -1
- package/neural-interface/public/shared/ui-worker-end.js +1 -1
- package/neural-interface/public/shared/whatsapp/wa-view.js +2 -2
- package/neural-interface/public/shared/worker-questions.js +34 -0
- package/neural-interface/public/sidepanel-session.html +1 -1
- package/neural-interface/server.js +644 -426
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/neural-interface/templates/rulesets/legacy-hashes.json +5 -5
- package/neural-interface/templates/rulesets/manifest.json +1 -1
- package/npm-shrinkwrap.json +18 -2
- package/package.json +2 -1
- package/skills/skill-forge/SKILL.md +4 -4
- package/skills/synabun/SKILL.md +1 -1
- package/skills/synabun/modules/schedule.md +3 -3
- /package/neural-interface/templates/rulesets/{gemini.md → antigravity.md} +0 -0
|
@@ -177,10 +177,10 @@ export function getSharedHTML() {
|
|
|
177
177
|
<span class="menu-text"><span class="menu-icon"><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></span> ${t('menu.apps.codexCli')} <span class="count-badge count-badge--green menu-update-badge" id="codex-menu-update-badge"></span></span>
|
|
178
178
|
<span class="menu-shortcut" data-keybind-for="launch-codex"></span>
|
|
179
179
|
</div>
|
|
180
|
-
<div class="menu-item" id="menu-terminal-
|
|
180
|
+
<div class="menu-item" id="menu-terminal-antigravity">
|
|
181
181
|
<span class="menu-check"></span>
|
|
182
|
-
<span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="
|
|
183
|
-
<span class="menu-shortcut" data-keybind-for="launch-
|
|
182
|
+
<span class="menu-text"><span class="menu-icon"><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></span> ${t('menu.apps.antigravityCli')} <span class="count-badge count-badge--green menu-update-badge" id="antigravity-menu-update-badge"></span></span>
|
|
183
|
+
<span class="menu-shortcut" data-keybind-for="launch-antigravity"></span>
|
|
184
184
|
</div>
|
|
185
185
|
<div class="menu-item" id="menu-terminal-opencode">
|
|
186
186
|
<span class="menu-check"></span>
|
|
@@ -495,7 +495,8 @@ ${is3D ? '' : `
|
|
|
495
495
|
</div>
|
|
496
496
|
|
|
497
497
|
<!-- Top-Right Controls: one row. The glass dock (workspace switcher, then the tools), then #topright-buttons: the
|
|
498
|
-
|
|
498
|
+
⋯ (#topright-overflow-btn: what does not fit the band, ui-topright-overflow.js), the tools toggle
|
|
499
|
+
(#topright-tools-btn, shows and hides the dock) and the agent side panels. Always one row, never wrapped.
|
|
499
500
|
Snap to grid and Tile terminals are on the whiteboard rail (#wb-toolbar) and in View. The session pills
|
|
500
501
|
(#term-minimized-tray) are a row under the bar, right-aligned with it (styles.css: "Fit"). -->
|
|
501
502
|
<div id="topright-controls">
|
|
@@ -569,6 +570,10 @@ ${is3D ? '' : `
|
|
|
569
570
|
</button>
|
|
570
571
|
</div>
|
|
571
572
|
<div id="topright-buttons">
|
|
573
|
+
<button id="topright-overflow-btn" class="topright-icon-btn" type="button" aria-haspopup="menu" aria-expanded="false" aria-controls="topright-overflow-menu" aria-label="${t('toolbar.more')}" data-tooltip="${t('toolbar.more')}">
|
|
574
|
+
<svg viewBox="0 0 24 24"><circle cx="5" cy="12" r="1.4" fill="currentColor" stroke="none"/><circle cx="12" cy="12" r="1.4" fill="currentColor" stroke="none"/><circle cx="19" cy="12" r="1.4" fill="currentColor" stroke="none"/></svg>
|
|
575
|
+
</button>
|
|
576
|
+
<div id="topright-overflow-menu" role="menu" aria-label="${t('toolbar.more')}" hidden></div>
|
|
572
577
|
<button id="topright-tools-btn" class="topright-icon-btn" type="button" aria-expanded="true" aria-controls="topright-inner" aria-label="${t('toolbar.hideTools')}" data-tooltip="${t('toolbar.hideTools')}">
|
|
573
578
|
<svg viewBox="0 0 24 24"><path d="M13 17l5-5-5-5"/><path d="M6 17l5-5-5-5"/></svg>
|
|
574
579
|
<span class="topright-tools-dot" aria-hidden="true"></span>
|
|
@@ -588,9 +593,16 @@ ${is3D ? '' : `
|
|
|
588
593
|
<svg viewBox="0 0 24 30" fill="currentColor"><path d="M18 6H6V24H18V6ZM24 30H0V0H24V30Z"/></svg>
|
|
589
594
|
<span class="count-badge count-badge--green" id="opencode-update-badge"></span>
|
|
590
595
|
</button>
|
|
596
|
+
<button id="topright-antigravity-panel-btn" class="topright-icon-btn" data-tooltip="${t('antigravityPanel.toolbar')}">
|
|
597
|
+
<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>
|
|
598
|
+
<span class="count-badge count-badge--green" id="antigravity-update-badge"></span>
|
|
599
|
+
</button>
|
|
591
600
|
</div>
|
|
592
601
|
<div id="term-minimized-tray"></div>
|
|
593
602
|
</div>
|
|
603
|
+
<button id="toolbar-show-btn" type="button" aria-pressed="true" aria-controls="wb-toolbar" aria-label="${t('toolbar.showWhiteboardToolbar')}" data-tooltip="${t('toolbar.showWhiteboardToolbar')}" hidden>
|
|
604
|
+
<img src="logo-synabun.png" alt="" draggable="false">
|
|
605
|
+
</button>
|
|
594
606
|
|
|
595
607
|
<!-- Help Modal -->
|
|
596
608
|
<div id="help-overlay">
|
|
@@ -701,6 +713,7 @@ ${is3D ? '' : `
|
|
|
701
713
|
<span class="fe-branch-btn-name" id="fe-branch-btn-name"></span>
|
|
702
714
|
<span class="fe-branch-btn-badge" id="fe-branch-btn-badge"></span>
|
|
703
715
|
</button>
|
|
716
|
+
<span class="fe-git-scan-live" id="fe-git-scan-live" role="status" aria-live="polite"></span>
|
|
704
717
|
</div>
|
|
705
718
|
<div class="fe-filter">
|
|
706
719
|
<svg class="fe-filter-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 5h18l-7 8v6l-4-2v-4z"/></svg>
|
|
@@ -821,6 +834,10 @@ ${getEditorPanelHTML()}
|
|
|
821
834
|
<button class="wb-tool wb-tool-sm" id="wb-toggle-logo" data-tooltip="Toggle logo">
|
|
822
835
|
<img src="logo-synabun.png" alt="" style="width:18px;height:auto;opacity:0.6;">
|
|
823
836
|
</button>
|
|
837
|
+
<div class="wb-tool-sep"></div>
|
|
838
|
+
<button class="wb-tool" id="wb-hide-btn" type="button" aria-pressed="false" aria-controls="wb-toolbar" aria-label="${t('toolbar.hideWhiteboardToolbar')}" data-tooltip="${t('toolbar.hideWhiteboardToolbar')}">
|
|
839
|
+
<svg viewBox="0 0 24 24" fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M15 6l-6 6 6 6"/></svg>
|
|
840
|
+
</button>
|
|
824
841
|
</div>
|
|
825
842
|
|
|
826
843
|
<div id="wb-canvas">
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { syncOpenCodeWorkerQuestions, forgetWorkerQuestions } from './ocp-v2-ws.js';
|
|
1
2
|
import { workerRestart } from '../worker-restart.js';
|
|
2
3
|
import { t } from '../i18n.js';
|
|
3
4
|
import { hostedSidepanelId, sidepanelHost } from '../ui-sidepanel-runtime.js';
|
|
@@ -1616,7 +1617,12 @@ async function boot() {
|
|
|
1616
1617
|
// the session on screen stays.
|
|
1617
1618
|
renderPill();
|
|
1618
1619
|
} else if (liveTabs.length) {
|
|
1619
|
-
const
|
|
1620
|
+
const pendingSid = globalThis.__synabunPendingTab?.provider === 'opencode'
|
|
1621
|
+
? String(globalThis.__synabunPendingTab.tabId || '')
|
|
1622
|
+
: '';
|
|
1623
|
+
const targetSid = (pendingSid && liveTabs.includes(pendingSid))
|
|
1624
|
+
? pendingSid
|
|
1625
|
+
: liveTabs[liveTabs.length - 1];
|
|
1620
1626
|
const targetInfo = _tabInfoCache.get(targetSid) || null;
|
|
1621
1627
|
bootNav.apply(() => {
|
|
1622
1628
|
setSession(targetSid, targetInfo);
|
|
@@ -2233,6 +2239,8 @@ function removeTab(sessionId, { byUser = false } = {}) {
|
|
|
2233
2239
|
forgetWorkerEnd(_automationRunIds.get(sessionId));
|
|
2234
2240
|
_workerEnds.delete(sessionId);
|
|
2235
2241
|
_automationRunIds.delete(sessionId);
|
|
2242
|
+
forgetWorkerQuestions(sessionId);
|
|
2243
|
+
forgetWorkerQuestions(sessionId);
|
|
2236
2244
|
unregisterAutomationSession(sessionId);
|
|
2237
2245
|
_automationRunning.delete(sessionId);
|
|
2238
2246
|
_automationTurn.delete(sessionId);
|
|
@@ -2273,7 +2281,7 @@ function createTabPill(sessionId) {
|
|
|
2273
2281
|
});
|
|
2274
2282
|
pill.querySelector('.term-minimized-pill-close')?.addEventListener('click', (event) => {
|
|
2275
2283
|
event.stopPropagation();
|
|
2276
|
-
closeTabByUser(sessionId, 'pill close');
|
|
2284
|
+
closeTabByUser(sessionId, 'pill close', { deleteBeforeClose: true });
|
|
2277
2285
|
});
|
|
2278
2286
|
tray.appendChild(pill);
|
|
2279
2287
|
return pill;
|
|
@@ -2283,10 +2291,16 @@ function createTabPill(sessionId) {
|
|
|
2283
2291
|
// continued the terminal automation manually; backend cleanup is best-effort.
|
|
2284
2292
|
// Asked first when prompts are still waiting in that session; declined: the
|
|
2285
2293
|
// tab stays, nothing is deleted, and this resolves false.
|
|
2286
|
-
async function closeTabByUser(sessionId, context) {
|
|
2294
|
+
async function closeTabByUser(sessionId, context, { deleteBeforeClose = false } = {}) {
|
|
2287
2295
|
if (!(await mayCloseTab(sessionId))) return false;
|
|
2288
|
-
|
|
2289
|
-
|
|
2296
|
+
// Only the tray X waits for deletion, including a turn in a background tab.
|
|
2297
|
+
// Worker tabs retain their existing stop/dismiss and transcript ownership.
|
|
2298
|
+
const deletePillSession = deleteBeforeClose && !_automationRunIds.has(sessionId);
|
|
2299
|
+
const wasRunning = sessionId === getState().sessionId
|
|
2300
|
+
? !!getState().running
|
|
2301
|
+
: deletePillSession && _sessionBusy.get(sessionId) === true;
|
|
2302
|
+
const backendClose = closeSessionBackend(sessionId, { wasRunning, context }).catch(() => {});
|
|
2303
|
+
if (deletePillSession) await backendClose;
|
|
2290
2304
|
try { await handlePillClose(sessionId, { byUser: true }); }
|
|
2291
2305
|
catch (err) { console.warn(`[ocp-v2-panel] local ${context} failed`, err); }
|
|
2292
2306
|
return true;
|
|
@@ -2436,9 +2450,13 @@ async function handlePillClose(sessionId, { byUser = false } = {}) {
|
|
|
2436
2450
|
}
|
|
2437
2451
|
|
|
2438
2452
|
// Sub-agent child panel coordination ─────────────────────────────────────────
|
|
2439
|
-
on('opencode-panel:show', async () => {
|
|
2453
|
+
on('opencode-panel:show', async (data) => {
|
|
2440
2454
|
try {
|
|
2455
|
+
const requestedId = typeof data?.tabId === 'string' ? data.tabId : '';
|
|
2441
2456
|
await showPrimaryOpencodePanel();
|
|
2457
|
+
if (requestedId && _tabSessionIds.includes(requestedId)) {
|
|
2458
|
+
await switchToSession(requestedId, _tabInfoCache.get(requestedId) || null);
|
|
2459
|
+
}
|
|
2442
2460
|
} catch (err) {
|
|
2443
2461
|
console.warn('[ocp-v2-panel] show request failed', err);
|
|
2444
2462
|
}
|
|
@@ -2457,7 +2475,7 @@ on('opencode-panel:request-show', async () => {
|
|
|
2457
2475
|
on('opencode-panel:request-new-session', () => { beginNewSession(); });
|
|
2458
2476
|
|
|
2459
2477
|
// Whiteboard "Send to Panel" → attach image to compose footer if OCP v2 is the
|
|
2460
|
-
// active sidepanel. Mirrors the gating used by Claude/Codex/
|
|
2478
|
+
// active sidepanel. Mirrors the gating used by Claude/Codex/Antigravity so the event
|
|
2461
2479
|
// is consumed by exactly one panel.
|
|
2462
2480
|
on('wb:send-to-panel', async ({ dataUrl }) => {
|
|
2463
2481
|
if (!dataUrl) return;
|
|
@@ -2527,6 +2545,7 @@ export async function attachOpenCodeAutomation(run, { focus = !!run?.focus, isCa
|
|
|
2527
2545
|
&& (_automationContinuedManually.has(sessionId) || _automationManualSendInFlight.has(sessionId));
|
|
2528
2546
|
_automationRunIds.set(sessionId, run.runId);
|
|
2529
2547
|
registerAutomationSession(sessionId, run.runId);
|
|
2548
|
+
syncOpenCodeWorkerQuestions(run);
|
|
2530
2549
|
if (running || previousRunId !== run.runId) {
|
|
2531
2550
|
_automationContinuedManually.delete(sessionId);
|
|
2532
2551
|
_automationManualSendInFlight.delete(sessionId);
|
|
@@ -2595,6 +2614,7 @@ export async function detachOpenCodeAutomation(runId) {
|
|
|
2595
2614
|
if (!entry) return false;
|
|
2596
2615
|
const [sessionId] = entry;
|
|
2597
2616
|
_automationRunIds.delete(sessionId);
|
|
2617
|
+
forgetWorkerQuestions(sessionId);
|
|
2598
2618
|
_automationRunning.delete(sessionId);
|
|
2599
2619
|
_automationTurn.delete(sessionId);
|
|
2600
2620
|
_automationContinuedManually.delete(sessionId);
|
|
@@ -284,20 +284,29 @@ export async function rehydratePanelSession(store, api, {
|
|
|
284
284
|
const left = () => { out.moved = true; return out; };
|
|
285
285
|
if (!current()) return left();
|
|
286
286
|
|
|
287
|
-
if (refreshInfo) {
|
|
287
|
+
if (refreshInfo && requireInfo) {
|
|
288
288
|
let res;
|
|
289
289
|
try { res = await api.sessionGet(sessionId); } catch (err) { res = { ok: false, error: err?.message || String(err) }; }
|
|
290
290
|
if (!current()) return left();
|
|
291
291
|
if (!replyFailed(res) && res.data) { store.setSession(sessionId, res.data); out.info = true; }
|
|
292
|
-
else
|
|
292
|
+
else {
|
|
293
293
|
out.unavailable = true;
|
|
294
294
|
out.error = (typeof res?.error === 'string' && res.error) || `Session ${String(sessionId).slice(0, 8)} is unavailable`;
|
|
295
295
|
return out;
|
|
296
296
|
}
|
|
297
|
-
// Otherwise the transcript may still answer.
|
|
298
297
|
}
|
|
298
|
+
const infoTask = (refreshInfo && !requireInfo)
|
|
299
|
+
? (async () => {
|
|
300
|
+
let res;
|
|
301
|
+
try { res = await api.sessionGet(sessionId); } catch (err) { res = { ok: false, error: err?.message || String(err) }; }
|
|
302
|
+
if (!current()) return false;
|
|
303
|
+
if (!replyFailed(res) && res.data) { store.setSession(sessionId, res.data); out.info = true; }
|
|
304
|
+
return true;
|
|
305
|
+
})()
|
|
306
|
+
: null;
|
|
299
307
|
const transcript = await hydrateTranscript(store, api, { sessionId, isCurrent: current });
|
|
300
|
-
if (
|
|
308
|
+
if (infoTask) await infoTask;
|
|
309
|
+
if (!current() || transcript.superseded) return left();
|
|
301
310
|
out.transcript = transcript.applied;
|
|
302
311
|
if (!transcript.applied) out.error = transcript.error;
|
|
303
312
|
const s = store.getState();
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
11
11
|
|
|
12
12
|
import { getDefaultStore } from './ocp-v2-state.js';
|
|
13
|
-
import { api, supports, isDescendantSession, isKnownDescendantSession, onEvent } from './ocp-v2-ws.js';
|
|
13
|
+
import { hasWorkerQuestions, api, supports, isDescendantSession, isKnownDescendantSession, onEvent } from './ocp-v2-ws.js';
|
|
14
14
|
import {
|
|
15
15
|
permissionCardView, ALWAYS_ALLOW_SCOPE, replyToPermission, FOREIGN_REQUEST_MESSAGE,
|
|
16
16
|
transcriptQuestionCard, answerQuestion, skipQuestion,
|
|
@@ -1001,6 +1001,12 @@ function renderToolPart(part, store) {
|
|
|
1001
1001
|
done.textContent = 'Question answered.';
|
|
1002
1002
|
return done;
|
|
1003
1003
|
}
|
|
1004
|
+
if (hasWorkerQuestions(store.getState().sessionId)) {
|
|
1005
|
+
const stub = document.createElement('div');
|
|
1006
|
+
stub.className = 'ocpv2-part ocpv2-part-question-stub';
|
|
1007
|
+
stub.textContent = store.getState().pendingQuestions?.length ? 'Awaiting your answer…' : 'Question answered.';
|
|
1008
|
+
return stub;
|
|
1009
|
+
}
|
|
1004
1010
|
// Dedup: if an SSE-driven QuestionRequest exists whose tool.callID matches
|
|
1005
1011
|
// this tool part, let the pendingQuestions render handle it instead.
|
|
1006
1012
|
const partCallId = part.callID || part.id;
|
|
@@ -45,6 +45,10 @@ const CSS = `
|
|
|
45
45
|
opacity: 1;
|
|
46
46
|
overflow: visible;
|
|
47
47
|
}
|
|
48
|
+
/* Windows: the shell is 92% opaque, so the blur behind it barely shows, yet Chromium recomputes it on every
|
|
49
|
+
repaint inside the panel (a transcript rendering, a stream). There it goes; the colour stays. */
|
|
50
|
+
html.platform-win32 .ocpv2-panel,
|
|
51
|
+
html.desktop-titlebar--win32 .ocpv2-panel { backdrop-filter: none; -webkit-backdrop-filter: none; }
|
|
48
52
|
/* Keep footer menus above focused floating terminal windows. */
|
|
49
53
|
.ocpv2-panel:has(.ocpv2-dropdown.open) {
|
|
50
54
|
z-index: 99999;
|
|
@@ -464,6 +468,19 @@ const CSS = `
|
|
|
464
468
|
rgba(232,224,220,0.0) 100%
|
|
465
469
|
);
|
|
466
470
|
}
|
|
471
|
+
html.platform-win32 .ocpv2-session-pill.ocpv2-pill-running,
|
|
472
|
+
html.desktop-titlebar--win32 .ocpv2-session-pill.ocpv2-pill-running {
|
|
473
|
+
border-color: rgba(232, 224, 220, 0.38);
|
|
474
|
+
}
|
|
475
|
+
html.platform-win32 .ocpv2-session-pill.ocpv2-pill-running:hover,
|
|
476
|
+
html.desktop-titlebar--win32 .ocpv2-session-pill.ocpv2-pill-running:hover {
|
|
477
|
+
border-color: rgba(232, 224, 220, 0.58);
|
|
478
|
+
}
|
|
479
|
+
html.platform-win32 .ocpv2-session-pill.ocpv2-pill-running::before,
|
|
480
|
+
html.desktop-titlebar--win32 .ocpv2-session-pill.ocpv2-pill-running::before {
|
|
481
|
+
animation: none;
|
|
482
|
+
opacity: 0;
|
|
483
|
+
}
|
|
467
484
|
.ocpv2-session-pill.ocpv2-pill-running .term-minimized-pill-label::before {
|
|
468
485
|
content: '';
|
|
469
486
|
display: inline-block;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { t } from '../i18n.js';
|
|
2
|
+
import { answerWorkerQuestion } from '../worker-questions.js';
|
|
1
3
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
4
|
// OpenCode V2 — WebSocket client (multi-panel)
|
|
3
5
|
// One WS connection serves every OCP v2 panel on the page. Panels register a
|
|
@@ -27,6 +29,12 @@ const _outcomes = createOutcomeNotifications();
|
|
|
27
29
|
|
|
28
30
|
function _fireOutcomeNotify(store, type) {
|
|
29
31
|
const s = store.getState();
|
|
32
|
+
// A sub-agent finishing is an intermediate step of its parent's task, not
|
|
33
|
+
// news on its own: ensureChildSpawn gives every Task/subagent call its own
|
|
34
|
+
// panel and store, so without this a multi-step turn popped one "done" per
|
|
35
|
+
// sub-agent plus one for the task itself. Its own errors still surface —
|
|
36
|
+
// those need attention wherever they happen.
|
|
37
|
+
if (type !== NOTIF_TYPE.ERROR && s.parentSessionId) return;
|
|
30
38
|
if (!_outcomes.take(s, type === NOTIF_TYPE.ERROR ? 'error' : 'done')) return;
|
|
31
39
|
const baseLabel = s.sessionInfo?.title || s.sessionInfo?.info?.title || 'OpenCode';
|
|
32
40
|
const label = s.parentSessionId ? `↳ ${baseLabel}` : baseLabel;
|
|
@@ -627,6 +635,41 @@ function request(payload, timeoutMs = 30000, { turnOf = '' } = {}) {
|
|
|
627
635
|
});
|
|
628
636
|
}
|
|
629
637
|
|
|
638
|
+
const workerQuestionRuns = new Map();
|
|
639
|
+
export const hasWorkerQuestions = (sessionId) => workerQuestionRuns.has(sessionId);
|
|
640
|
+
export const forgetWorkerQuestions = (sessionId) => workerQuestionRuns.delete(sessionId);
|
|
641
|
+
const workerQuestions = (run) => (run?.pending || []).filter((p) => p.kind === 'question').map((p) => ({ ...p.input, id: p.protocol?.id, sessionID: run.providerSessionId, _workerRequestId: p.requestId }));
|
|
642
|
+
|
|
643
|
+
export function syncOpenCodeWorkerQuestions(run) {
|
|
644
|
+
if (run.runMode !== 'task') return;
|
|
645
|
+
const sid = run.providerSessionId;
|
|
646
|
+
const previous = workerQuestions(workerQuestionRuns.get(sid));
|
|
647
|
+
workerQuestionRuns.set(sid, run);
|
|
648
|
+
const next = workerQuestions(run);
|
|
649
|
+
for (const req of previous) if (!next.some((n) => n.id === req.id)) _asks.note('question.replied', { id: req.id, sessionID: sid });
|
|
650
|
+
for (const req of next) _asks.note('question.asked', req);
|
|
651
|
+
for (const store of _storesBySession.get(sid) || []) {
|
|
652
|
+
for (const req of previous) if (!next.some((n) => n.id === req.id)) store.removePendingQuestion(req.id);
|
|
653
|
+
for (const req of next) store.addPendingQuestion(req);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
async function answerOpenCodeWorker({ sessionId, requestId, answers }, reject = false) {
|
|
658
|
+
let run = workerQuestionRuns.get(sessionId);
|
|
659
|
+
let pending = workerQuestions(run).find((q) => q.id === requestId);
|
|
660
|
+
// An SSE question can precede the run update. Read the authoritative pending request before answering.
|
|
661
|
+
if (!pending) {
|
|
662
|
+
const res = await fetch(`/api/assistant/runs/${encodeURIComponent(run.runId)}`);
|
|
663
|
+
if (!res.ok) throw new Error(t('workerQuestion.deliveryFailed'));
|
|
664
|
+
const body = await res.json();
|
|
665
|
+
if (!body.run) throw new Error(t('workerQuestion.deliveryFailed'));
|
|
666
|
+
run = body.run; pending = workerQuestions(run).find((q) => q.id === requestId);
|
|
667
|
+
}
|
|
668
|
+
if (pending) await answerWorkerQuestion(run.runId, pending._workerRequestId, { decision: reject ? 'deny' : 'answer', answers });
|
|
669
|
+
for (const store of _storesBySession.get(sessionId) || []) store.removePendingQuestion(requestId);
|
|
670
|
+
return { ok: true, data: true };
|
|
671
|
+
}
|
|
672
|
+
|
|
630
673
|
export const api = {
|
|
631
674
|
init: () => request({ type: 'init', windowId: nativeLoopWindowId }),
|
|
632
675
|
// options: { search, archived, roots, limit }. A server without
|
|
@@ -645,9 +688,9 @@ export const api = {
|
|
|
645
688
|
compact: ({ sessionId, cwd, tools } = {}) => request({ type: 'session:compact', sessionId, cwd, tools }, 5 * 60 * 1000),
|
|
646
689
|
permissionReply: ({ sessionId, permissionId, response, cwd, message }) =>
|
|
647
690
|
request({ type: 'permission:reply', sessionId, permissionId, response, cwd, message }),
|
|
648
|
-
questionList: ({ cwd, sessionId } = {}) => request({ type: 'question:list', cwd, sessionId }),
|
|
649
|
-
questionReply: ({ requestId, answers, cwd, sessionId }) => request({ type: 'question:reply', requestId, answers, cwd, sessionId }),
|
|
650
|
-
questionReject: ({ requestId, sessionId }) => request({ type: 'question:reject', requestId, sessionId }),
|
|
691
|
+
questionList: ({ cwd, sessionId } = {}) => workerQuestionRuns.has(sessionId) ? Promise.resolve({ data: workerQuestions(workerQuestionRuns.get(sessionId)) }) : request({ type: 'question:list', cwd, sessionId }),
|
|
692
|
+
questionReply: ({ requestId, answers, cwd, sessionId }) => workerQuestionRuns.has(sessionId) ? answerOpenCodeWorker({ requestId, answers, sessionId }) : request({ type: 'question:reply', requestId, answers, cwd, sessionId }),
|
|
693
|
+
questionReject: ({ requestId, sessionId }) => workerQuestionRuns.has(sessionId) ? answerOpenCodeWorker({ requestId, sessionId }, true) : request({ type: 'question:reject', requestId, sessionId }),
|
|
651
694
|
toolsGet: (sessionId) => gated({ type: 'mcp:tools:get', sessionId }),
|
|
652
695
|
toolsSet: (sessionId, tools) => gated({ type: 'mcp:tools:set', sessionId, tools }, 45_000),
|
|
653
696
|
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
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>';
|
|
6
6
|
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 0 0-.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 0 1 .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 0 1 4.21 6.327v5.423c0 .333.143.571.428.738l5.947 3.449-1.95 1.118a.432.432 0 0 1-.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 0 0 5.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 0 0 10.205 0a5.947 5.947 0 0 0-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 0 0 4.162 1.713z"/></svg>';
|
|
7
|
-
|
|
7
|
+
// A line drawing: its paths carry fill="none" themselves, because some places fill every icon they hold
|
|
8
|
+
// (`.resume-provider-icon svg { fill: currentColor }`), which would turn the strokes into a solid triangle.
|
|
9
|
+
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" fill="none"/><path d="M8.2 20a3.8 3.8 0 0 1 7.6 0" fill="none"/></svg>';
|
|
8
10
|
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>';
|
|
9
11
|
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>';
|
|
10
12
|
const SVG_BROWSER = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>';
|
|
@@ -15,7 +17,7 @@ const PROVIDER_META = {
|
|
|
15
17
|
'claude-code': { id: 'claude-code', label: 'Claude Code', shortLabel: 'Claude', icon: SVG_CLAUDE, color: '#D4A27F' },
|
|
16
18
|
codex: { id: 'codex', label: 'Codex', shortLabel: 'Codex', icon: SVG_OPENAI, color: '#74C7A5' },
|
|
17
19
|
opencode: { id: 'opencode', label: 'OpenCode', shortLabel: 'OpenCode', icon: SVG_OPENCODE, color: '#E8E0DC' },
|
|
18
|
-
|
|
20
|
+
antigravity: { id: 'antigravity', label: 'Antigravity', shortLabel: 'Antigravity', icon: SVG_ANTIGRAVITY, color: '#669DF6' },
|
|
19
21
|
synabun: { id: 'synabun', label: 'SynaBun', shortLabel: 'SynaBun', icon: SVG_SYNABUN, color: '#FFD23C' },
|
|
20
22
|
shell: { id: 'shell', label: 'Shell', shortLabel: 'Shell', icon: SVG_SHELL, color: '#AAAAAA' },
|
|
21
23
|
browser: { id: 'browser', label: 'Browser', shortLabel: 'Browser', icon: SVG_BROWSER, color: '#4FC3F7' },
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
// `tx` in Settings; the wizard reads the same catalogue, i18n/en.json).
|
|
21
21
|
|
|
22
22
|
/** The tools SynaBun installs rules for, in the order both surfaces list them. Cursor is copy-only. */
|
|
23
|
-
export const RULES_INSTALL_HOSTS = Object.freeze(['claude', '
|
|
23
|
+
export const RULES_INSTALL_HOSTS = Object.freeze(['claude', 'antigravity', 'codex', 'opencode']);
|
|
24
24
|
|
|
25
|
-
export const RULES_HOST_LABELS = Object.freeze({ claude: 'Claude Code', codex: 'Codex', opencode: 'OpenCode',
|
|
25
|
+
export const RULES_HOST_LABELS = Object.freeze({ claude: 'Claude Code', codex: 'Codex', opencode: 'OpenCode', antigravity: 'Antigravity', cursor: 'Cursor', coexistence: 'coexistence' });
|
|
26
26
|
|
|
27
27
|
/** The states that count as "the rules are in place". `shadowed` is installed too, only not loaded (Codex's override file). */
|
|
28
28
|
export const RULES_IN_PLACE = Object.freeze(['installed', 'newer', 'shadowed']);
|
|
@@ -66,7 +66,7 @@ export async function refreshSkillChips(root) {
|
|
|
66
66
|
const skill = byDir.get(chip.dataset.ccSkill);
|
|
67
67
|
if (!skill || chip.style.pointerEvents === 'none') continue;
|
|
68
68
|
const target = chip.dataset.ccTarget;
|
|
69
|
-
const installed = skill.installedTargets || { claude: !!skill.installed, codex: false, opencode: false };
|
|
69
|
+
const installed = skill.installedTargets || { claude: !!skill.installed, codex: false, opencode: false, antigravity: false };
|
|
70
70
|
const now = chipState(skill.targetStates?.[target], !!installed[target]);
|
|
71
71
|
chip.classList.toggle('on', now.on);
|
|
72
72
|
chip.dataset.state = now.on ? 'on' : 'off';
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// each runtime chip's state (a native folder, an old bridge, someone else's folder). Every sentence is a
|
|
9
9
|
// settings.redesign.skills.* key; the pane (settings-skill-folders-pane.js) draws it.
|
|
10
10
|
|
|
11
|
-
const RUNTIME = { claude: 'settings.redesign.product.claude', codex: 'settings.redesign.product.codex', opencode: 'settings.redesign.product.opencode' };
|
|
11
|
+
const RUNTIME = { claude: 'settings.redesign.product.claude', codex: 'settings.redesign.product.codex', opencode: 'settings.redesign.product.opencode', antigravity: 'settings.redesign.product.antigravity' };
|
|
12
12
|
|
|
13
13
|
/** What the status answer says, or that the server cannot say it yet (one from before the Skills Service). */
|
|
14
14
|
export function readFoldersStatus(answer) {
|
|
@@ -26,7 +26,7 @@ export function readFoldersStatus(answer) {
|
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const ASSISTANTS = ['claude', 'codex', 'opencode'];
|
|
29
|
+
const ASSISTANTS = ['claude', 'codex', 'opencode', 'antigravity'];
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* The owner's assistants (GET /v2/config `assistants`: chosen, detected, effective): one chip per runtime, on when
|
|
@@ -55,13 +55,18 @@ export const WHOLESALE_SELECTORS = [
|
|
|
55
55
|
// OpenCode side panel transcript
|
|
56
56
|
'.ocpv2-part-text', '.ocpv2-reasoning-body', '.ocpv2-tc-summary', '.ocpv2-tc-meta', '.ocpv2-tc-body',
|
|
57
57
|
'.ocpv2-tool-input', '.ocpv2-tool-output', '.ocpv2-sb-summary',
|
|
58
|
+
// Antigravity side panel: session names, the transcript, tool and request cards, the plan, what waits to be sent
|
|
59
|
+
'.agy-session-label', '.agy-tab-label', '.agy-sess-list .agy-pop-item-title', '.agy-sess-list .agy-pop-item-meta',
|
|
60
|
+
'.agy-msg-text', '.agy-msg .agy-md', '.agy-msg-image', '.agy-thought-body',
|
|
61
|
+
'.agy-card-title', '.agy-card-subtitle', '.agy-card-text', '.agy-card-body', '.agy-card-error', '.agy-plan-text',
|
|
62
|
+
'.agy-queue-text', '.agy-chip', '.agy-folder-chip',
|
|
58
63
|
// Assistant transcript, run and worker cards
|
|
59
64
|
'.asst-msg-text', '.asst-md', '.asst-thinking-content', '.asst-run-title', '.asst-run-summary', '.asst-run-escalate-reason',
|
|
60
65
|
'.asst-tool-detail', '.asst-tool-body', '.asst-tool-section', '.asst-tl-said', '.asst-tl-subject', '.asst-bubble-text',
|
|
61
66
|
'.asst-station-sub', '.asst-station-log', '.asst-auto-title', '.asst-auto-summary', '.asst-auto-detail',
|
|
62
67
|
// Composers, once they hold text (an empty one keeps its placeholder sharp)
|
|
63
68
|
'#cp-input:not(:placeholder-shown)', '#cxp-input:not(:placeholder-shown)', '.ocpv2-compose-input:not(:placeholder-shown)',
|
|
64
|
-
'.asst-input:not(:placeholder-shown)',
|
|
69
|
+
'.asst-input:not(:placeholder-shown)', '.agy-input:not(:placeholder-shown)',
|
|
65
70
|
// Terminal output (the WebGL canvas and the DOM renderer alike) and the terminal's browser tab
|
|
66
71
|
'.term-viewport .xterm-screen', '.term-float-tab-body .xterm', '.browser-canvas', '.browser-url-input', '.browser-title-label',
|
|
67
72
|
// Resume results
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
// Assistant (sessionStatus). The same source as the tray pills, never a second
|
|
9
9
|
// guess. DOM-free.
|
|
10
10
|
|
|
11
|
-
const WORKING = /^(cp|cxp|ocpv2|asp)-pill-running$/;
|
|
12
|
-
const NEEDS_YOU = /^((cp|cxp|asp)-pill-attention|ocpv2-pill-waiting)$/;
|
|
11
|
+
const WORKING = /^(cp|cxp|ocpv2|agy|asp)-pill-running$/;
|
|
12
|
+
const NEEDS_YOU = /^((cp|cxp|agy|asp)-pill-attention|ocpv2-pill-waiting)$/;
|
|
13
13
|
|
|
14
14
|
/** The states a detached window's pill shows: a session in it needs you > one works > none. */
|
|
15
15
|
export const SESSION_WINDOW_STATES = Object.freeze(['action', 'working', 'idle']);
|
|
@@ -44,6 +44,6 @@ export function normalizeSessionWindowStatus(status) {
|
|
|
44
44
|
*/
|
|
45
45
|
export function runAwaitsAnswer(run) {
|
|
46
46
|
if (run?.status !== 'starting' && run?.status !== 'running') return false;
|
|
47
|
-
if (run.turnState === 'needs_input') return true;
|
|
47
|
+
if (run.turnState === 'needs_input' || run.turnState === 'awaiting_permission' || run.pending?.some((p) => p.kind === 'question')) return true;
|
|
48
48
|
return run.turnState === 'idle' && (run.outcome || run.lastResult?.status) === 'needs_input';
|
|
49
49
|
}
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
// one reading of a request for the page and the server. No DOM and no imports.
|
|
9
9
|
//
|
|
10
10
|
// describe the owner's words only
|
|
11
|
-
// conversation one session transcript of Claude Code, Codex or
|
|
11
|
+
// conversation one session transcript of Claude Code, Codex, OpenCode or Antigravity (read by the server, as data)
|
|
12
12
|
// url a web page, read by the server with the SynaBun browser before the worker starts (as data)
|
|
13
13
|
// repo a registered project, read by the server: its file tree, docs, manifests and the files named
|
|
14
14
|
// memory a recall over SynaBun's memory
|
|
15
15
|
// import an imported skill (a staged import), or a skill of the catalog or the library, as the starting point
|
|
16
16
|
|
|
17
17
|
export const SOURCE_KINDS = Object.freeze(['describe', 'conversation', 'url', 'repo', 'memory', 'import']);
|
|
18
|
-
export const CONVERSATION_PROVIDERS = Object.freeze(['claude-code', 'codex', 'opencode']);
|
|
18
|
+
export const CONVERSATION_PROVIDERS = Object.freeze(['claude-code', 'codex', 'opencode', 'antigravity']);
|
|
19
19
|
/**
|
|
20
20
|
* Who drafts: Claude Code only. A drafting worker reads hostile sources, so it is held to its folder with file tools
|
|
21
21
|
* only (lib/skills/draft-confinement.js), which Claude Code enforces before any permission mode; Codex starts MCP
|
|
@@ -23,7 +23,8 @@ export const CONVERSATION_PROVIDERS = Object.freeze(['claude-code', 'codex', 'op
|
|
|
23
23
|
*/
|
|
24
24
|
/** The providers a drafting run can be held to its folder on (lib/skills/draft-confinement.js draftConfinementSupport). */
|
|
25
25
|
export const DRAFT_PROVIDERS = Object.freeze(['claude-code', 'codex', 'opencode']);
|
|
26
|
-
|
|
26
|
+
/** Where a drafted skill may be installed later (a deploy.js target): Antigravity too, though no Antigravity worker drafts. */
|
|
27
|
+
export const CREATION_TARGET_RUNTIMES = Object.freeze(['claude', 'codex', 'opencode', 'antigravity', 'agents']);
|
|
27
28
|
|
|
28
29
|
/** The stages of a creation, in order; the last four end it. */
|
|
29
30
|
export const CREATION_STAGES = Object.freeze(['queued', 'gathering', 'drafting', 'checking', 'submitting', 'done', 'failed', 'cancelled', 'interrupted']);
|
|
@@ -184,6 +185,8 @@ export function normalizeCreationRequest(body, { submitDefault = true } = {}) {
|
|
|
184
185
|
const scope = t.scope === undefined || t.scope === null || t.scope === '' ? 'user' : t.scope;
|
|
185
186
|
if (scope !== 'user' && scope !== 'project') { problems.push({ field: `${at}.scope`, code: 'targets-scope' }); return; }
|
|
186
187
|
if (t.runtime === 'agents' && scope !== 'user') { problems.push({ field: `${at}.scope`, code: 'targets-agents-scope' }); return; }
|
|
188
|
+
// Antigravity reads a project's .agents/skills, which is the codex target with scope project.
|
|
189
|
+
if (t.runtime === 'antigravity' && scope !== 'user') { problems.push({ field: `${at}.scope`, code: 'targets-antigravity-scope' }); return; }
|
|
187
190
|
const accountId = t.accountId === undefined || t.accountId === null || t.accountId === '' ? 'default' : t.accountId;
|
|
188
191
|
if (typeof accountId !== 'string' || !ACCOUNT_RE.test(accountId)) { problems.push({ field: `${at}.accountId`, code: 'targets-account' }); return; }
|
|
189
192
|
let projectPath = null;
|
|
@@ -30,9 +30,11 @@ export function closeDialog() { _open?.giveUp(); }
|
|
|
30
30
|
* @param {string|null} [o.cancelId] what Escape and a click outside answer; null: they answer null
|
|
31
31
|
* @param {HTMLElement|null} [o.extra] more content after the text (a checkbox, a list)
|
|
32
32
|
* @param {(answer: string, ui: object) => boolean} [o.accept] called before the answer is given: false keeps it open
|
|
33
|
+
* @param {(ui: object) => void} [o.onOpen] called once it is drawn, with { box, body, bar, byId, setDisabled, done }
|
|
34
|
+
* @param {string} [o.className] one more class on the dialog (a variant: `ss-dlg--confirm`)
|
|
33
35
|
* @returns {Promise<string|null>} the id of the button, or `cancelId` / null
|
|
34
36
|
*/
|
|
35
|
-
export function askInPanel({ host, title, lines = [], buttons, focus = null, cancelId = 'cancel', extra = null, accept = null, wide = false }) {
|
|
37
|
+
export function askInPanel({ host, title, lines = [], buttons, focus = null, cancelId = 'cancel', extra = null, accept = null, wide = false, onOpen = null, className = '' }) {
|
|
36
38
|
return new Promise((resolve) => {
|
|
37
39
|
_open?.giveUp();
|
|
38
40
|
const before = document.activeElement;
|
|
@@ -41,7 +43,7 @@ export function askInPanel({ host, title, lines = [], buttons, focus = null, can
|
|
|
41
43
|
const backdrop = document.createElement('div');
|
|
42
44
|
backdrop.className = 'ss-fd-backdrop';
|
|
43
45
|
const box = document.createElement('div');
|
|
44
|
-
box.className = `ss-file-dialog ss-dlg${wide ? ' ss-dlg--wide' : ''}`;
|
|
46
|
+
box.className = `ss-file-dialog ss-dlg${wide ? ' ss-dlg--wide' : ''}${className ? ` ${className}` : ''}`;
|
|
45
47
|
const uid = `ss-dlg-${Math.random().toString(36).slice(2, 8)}`;
|
|
46
48
|
box.setAttribute('role', 'alertdialog');
|
|
47
49
|
box.setAttribute('aria-modal', 'true');
|
|
@@ -126,5 +128,6 @@ export function askInPanel({ host, title, lines = [], buttons, focus = null, can
|
|
|
126
128
|
const start = (focus && byId.get(focus)) || [...buttons].reverse().map((b) => byId.get(b.id)).find((n) => n && !n.disabled && !n.classList.contains('ss-dlg-btn--danger')) || enabled()[0];
|
|
127
129
|
start?.focus({ preventScroll: true });
|
|
128
130
|
ui.done = done;
|
|
131
|
+
if (typeof onOpen === 'function') onOpen(ui);
|
|
129
132
|
});
|
|
130
133
|
}
|
|
@@ -81,7 +81,12 @@ export function lintArtifact({ type, parsed, folderName = '', knownNames = [] })
|
|
|
81
81
|
if (typeof desc !== 'string') add('description-type', 'error', `"description" must be text; it is ${kindOf(desc)}.`, lineOf('description'));
|
|
82
82
|
else if (!desc.trim()) add('description-empty', 'error', '"description" is empty.', lineOf('description'));
|
|
83
83
|
else {
|
|
84
|
-
|
|
84
|
+
// The 1024-character limit is the skill format's (Claude Code, Codex and the portable format refuse a longer
|
|
85
|
+
// SKILL.md). An agent or a command has none: a long description only costs context, which is no error.
|
|
86
|
+
if (desc.length > DESCRIPTION_MAX) {
|
|
87
|
+
if (type === 'skill') add('description-length', 'error', `"description" is ${desc.length} characters; the limit is ${DESCRIPTION_MAX}.`, lineOf('description'));
|
|
88
|
+
else add('description-length', 'info', `"description" is ${desc.length} characters: every session carries it, so a shorter one leaves more room.`, lineOf('description'));
|
|
89
|
+
}
|
|
85
90
|
const hidden = findHiddenChars(desc);
|
|
86
91
|
if (hidden.length) add('description-hidden-chars', 'error', `"description" holds characters nobody can see: ${hidden.slice(0, 5).map((h) => h.label).join(', ')}${hidden.length > 5 ? '…' : ''}.`, lineOf('description'));
|
|
87
92
|
}
|
|
@@ -99,6 +104,9 @@ export function lintArtifact({ type, parsed, folderName = '', knownNames = [] })
|
|
|
99
104
|
if (has(key) && typeof data[key] !== 'boolean') add(`${key}-type`, 'error', `"${key}" must be true or false; it is ${kindOf(data[key])}.`, lineOf(key));
|
|
100
105
|
}
|
|
101
106
|
for (const key of STRING_KEYS) {
|
|
107
|
+
// `argument-hint: [message]` is the form Claude Code's own documentation writes: YAML reads the brackets as a
|
|
108
|
+
// list of text and Claude Code shows it as written. Only another kind of value is an error.
|
|
109
|
+
if (key === 'argument-hint' && Array.isArray(data[key]) && data[key].every((v) => typeof v === 'string' || typeof v === 'number')) continue;
|
|
102
110
|
if (has(key) && data[key] !== null && typeof data[key] !== 'string') add(`${key}-type`, 'error', `"${key}" must be text; it is ${kindOf(data[key])}.`, lineOf(key));
|
|
103
111
|
}
|
|
104
112
|
for (const key of TOOL_KEYS) {
|