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
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
// keeps an untouched copy current:
|
|
7
7
|
//
|
|
8
8
|
// claude owned file ~/.claude/rules/synabun.md (and each Claude account's config dir)
|
|
9
|
-
// opencode owned file <opencode config dir>/synabun.md + one `instructions` entry in
|
|
9
|
+
// opencode owned file <opencode config dir>/synabun.md + one `instructions` entry in opencode.json
|
|
10
10
|
// codex block ~/.codex/AGENTS.md (account homes link to it, or get their own block)
|
|
11
|
-
//
|
|
11
|
+
// antigravity block ~/.gemini/config/GEMINI.md (Antigravity's global customization root; the block an
|
|
12
|
+
// older SynaBun wrote for Gemini CLI in ~/.gemini/GEMINI.md, which Antigravity also
|
|
13
|
+
// reads, is moved here so the rules are never loaded twice)
|
|
12
14
|
// cursor none User Rules live inside the app: copy and paste ("manual")
|
|
13
15
|
//
|
|
14
16
|
// What it will not do: create the config directory of a CLI that is not
|
|
@@ -29,7 +31,7 @@
|
|
|
29
31
|
// (the user opted out) or null (never asked). `created` lists the files and
|
|
30
32
|
// directories install made, `links` the symlinks it made and where each
|
|
31
33
|
// pointed. OpenCode's row also holds `instructionsEntry`, the exact string
|
|
32
|
-
// SynaBun added to
|
|
34
|
+
// SynaBun added to opencode.json. `removal` on a row is a removal that is not
|
|
33
35
|
// over: it is saved, with the paths it is about to take, before the first
|
|
34
36
|
// copy goes, and it stays when a copy was refused (damaged markers, an
|
|
35
37
|
// unreadable file). The next boot finishes it (reconcile), and the record is
|
|
@@ -74,6 +76,7 @@ import { loadLegacyHashes, normalise, renderRuleset, RULESET_HOSTS } from './ren
|
|
|
74
76
|
import { findBlocks, findLegacy, isPristine, removeBlock, removeRange, replaceRange, upsertBlock, wrap } from './managed-text.js';
|
|
75
77
|
import { backupFile, findBrokenLink, readBytes, readJsonStrict, unlinkIfUnchanged, writeTextAtomic } from './fs-safe.js';
|
|
76
78
|
import { addToJsonList, countJsonKey, removeFromJsonList } from './json-edit.js';
|
|
79
|
+
import { mcpServersOf, mergedOpencodeConfig, opencodeConfigDir, opencodeConfigFilePath, readOpencodeConfigDocuments } from '../opencode-config.js';
|
|
77
80
|
import { createWriterLock, DEFAULT_LOCK_TIMEOUT_MS, LOCK_FILE_NAME } from './lock.js';
|
|
78
81
|
|
|
79
82
|
export const RULESET_STATES = Object.freeze(['not-installed', 'installed', 'newer', 'outdated', 'modified', 'conflict', 'shadowed', 'error', 'manual']);
|
|
@@ -82,11 +85,18 @@ const HOSTS = Object.freeze({
|
|
|
82
85
|
claude: { label: 'Claude Code', carrier: 'file' },
|
|
83
86
|
codex: { label: 'Codex CLI', carrier: 'block' },
|
|
84
87
|
opencode: { label: 'OpenCode', carrier: 'file' },
|
|
85
|
-
|
|
88
|
+
// `legacyHosts`: the stamps an earlier SynaBun wrote for what this host replaced (Gemini CLI's rules, host=gemini).
|
|
89
|
+
antigravity: { label: 'Antigravity', carrier: 'block', legacyHosts: Object.freeze(['gemini']) },
|
|
86
90
|
cursor: { label: 'Cursor', carrier: 'none' },
|
|
87
91
|
});
|
|
88
92
|
const MANAGED_HOSTS = Object.freeze(RULESET_HOSTS.filter((host) => HOSTS[host].carrier !== 'none'));
|
|
89
|
-
const PROJECT_FILES = Object.freeze([['CLAUDE.md', 'claude'], ['AGENTS.md', 'codex'], ['GEMINI.md', '
|
|
93
|
+
const PROJECT_FILES = Object.freeze([['CLAUDE.md', 'claude'], ['AGENTS.md', 'codex'], ['GEMINI.md', 'antigravity']]);
|
|
94
|
+
// State rows an earlier SynaBun kept under a host this one replaced: read as the new host's row (readState).
|
|
95
|
+
const RENAMED_HOSTS = Object.freeze({ gemini: 'antigravity' });
|
|
96
|
+
/** Whether a block's stamp is this host's own: its name, or one it replaced. */
|
|
97
|
+
function ownStamp(host, stamped) {
|
|
98
|
+
return stamped === host || (HOSTS[host]?.legacyHosts || []).includes(stamped);
|
|
99
|
+
}
|
|
90
100
|
const RANK = Object.freeze({ missing: 0, current: 1, newer: 2, outdated: 3, modified: 4, conflict: 5, error: 6 });
|
|
91
101
|
const MAX_SCAN_BYTES = 2 * 1024 * 1024;
|
|
92
102
|
|
|
@@ -190,7 +200,7 @@ export function createRulesetInstaller({
|
|
|
190
200
|
// `hooks` are seams for tests, each a point where another program could act
|
|
191
201
|
// (or where a test holds an operation still, inside the lock):
|
|
192
202
|
// afterInspect(host, path, status) once a carrier was read and is about to be
|
|
193
|
-
// written, beforeCommit(path) right before a file (a carrier,
|
|
203
|
+
// written, beforeCommit(path) right before a file (a carrier, opencode.json,
|
|
194
204
|
// the state file) is checked against what was read and replaced or deleted,
|
|
195
205
|
// afterCheck(path) between that check and a delete, afterSave(revision) once
|
|
196
206
|
// the state file was saved.
|
|
@@ -258,6 +268,17 @@ export function createRulesetInstaller({
|
|
|
258
268
|
return view();
|
|
259
269
|
}
|
|
260
270
|
if (!isPlainObject(saved)) return view();
|
|
271
|
+
// A row kept under a host this SynaBun replaced (Gemini CLI → Antigravity) is the new host's row, marked
|
|
272
|
+
// `movedFrom` until reconcile has put the rules where the new host reads them (see reconcileHosts).
|
|
273
|
+
for (const [old, now] of Object.entries(RENAMED_HOSTS)) {
|
|
274
|
+
const hosts = isPlainObject(saved.hosts) ? saved.hosts : null;
|
|
275
|
+
if (hosts && isPlainObject(hosts[old]) && !isPlainObject(hosts[now])) {
|
|
276
|
+
saved.hosts = { ...hosts, [now]: { ...hosts[old], ...(hosts[old].managed === true ? { movedFrom: old } : {}) } };
|
|
277
|
+
delete saved.hosts[old];
|
|
278
|
+
}
|
|
279
|
+
if (Array.isArray(saved.offerAcked)) saved.offerAcked = saved.offerAcked.map((host) => (host === old ? now : host));
|
|
280
|
+
if (isPlainObject(saved.notice) && Array.isArray(saved.notice.hosts)) saved.notice = { ...saved.notice, hosts: unique(saved.notice.hosts.map((host) => (host === old ? now : host))) };
|
|
281
|
+
}
|
|
261
282
|
if (Number.isSafeInteger(saved.revision) && saved.revision > 0) state.revision = saved.revision;
|
|
262
283
|
if (typeof saved.autoUpdate === 'boolean') state.autoUpdate = saved.autoUpdate;
|
|
263
284
|
if (isPlainObject(saved.notice)) state.notice = saved.notice;
|
|
@@ -351,15 +372,20 @@ export function createRulesetInstaller({
|
|
|
351
372
|
|
|
352
373
|
// ── Where things live ──────────────────────────────────────────────────────
|
|
353
374
|
// Resolved the way the MCP toggle routes resolve them: Claude, Codex and
|
|
354
|
-
//
|
|
375
|
+
// Antigravity under the home directory, OpenCode in its configuration folder
|
|
376
|
+
// (OPENCODE_CONFIG_DIR, else XDG_CONFIG_HOME/opencode, else ~/.config/opencode),
|
|
377
|
+
// whose opencode.json OpenCode 2 reads (lib/opencode-config.js).
|
|
355
378
|
function layout() {
|
|
356
379
|
// The server passes the resolver its /api/opencode/mcp toggle uses, so both always edit the same file.
|
|
357
380
|
const opencodeConfig = opencodeConfigPath
|
|
358
381
|
? resolve(opencodeConfigPath())
|
|
359
|
-
:
|
|
382
|
+
: opencodeConfigFilePath(opencodeConfigDir({ env: env || {}, home }));
|
|
360
383
|
return {
|
|
361
384
|
claudeDir: join(home, '.claude'),
|
|
362
385
|
codexHome: join(home, '.codex'),
|
|
386
|
+
// Antigravity's global customization root (rules, skills, mcp_config.json), and the folder above it, where
|
|
387
|
+
// Gemini CLI's GEMINI.md lives (Antigravity reads that file too).
|
|
388
|
+
antigravityDir: join(home, '.gemini', 'config'),
|
|
363
389
|
geminiDir: join(home, '.gemini'),
|
|
364
390
|
opencodeDir: dirname(opencodeConfig),
|
|
365
391
|
opencodeConfig,
|
|
@@ -413,7 +439,7 @@ export function createRulesetInstaller({
|
|
|
413
439
|
...codexAccounts().filter((account) => account.kind === 'file').map(({ path, dir }) => ({ path, dir })),
|
|
414
440
|
];
|
|
415
441
|
}
|
|
416
|
-
if (host === '
|
|
442
|
+
if (host === 'antigravity') return [{ path: join(where.antigravityDir, 'GEMINI.md'), dir: where.antigravityDir, legacyBlock: join(where.geminiDir, 'GEMINI.md') }];
|
|
417
443
|
return [];
|
|
418
444
|
}
|
|
419
445
|
function projectPaths() {
|
|
@@ -425,9 +451,12 @@ export function createRulesetInstaller({
|
|
|
425
451
|
const where = layout();
|
|
426
452
|
try {
|
|
427
453
|
if (host === 'claude') return !!JSON.parse(readFileSync(join(home, '.claude.json'), 'utf8'))?.mcpServers?.SynaBun;
|
|
428
|
-
if (host === '
|
|
454
|
+
if (host === 'antigravity') {
|
|
455
|
+
const text = readFileSync(join(where.antigravityDir, 'mcp_config.json'), 'utf8').replace(/^\uFEFF/, '');
|
|
456
|
+
return text.trim() ? !!JSON.parse(text)?.mcpServers?.SynaBun : false;
|
|
457
|
+
}
|
|
429
458
|
if (host === 'codex') return /^\[mcp_servers\.SynaBun\]/m.test(readFileSync(join(where.codexHome, 'config.toml'), 'utf8'));
|
|
430
|
-
if (host === 'opencode') return !!
|
|
459
|
+
if (host === 'opencode') return !!mcpServersOf(mergedOpencodeConfig(readOpencodeConfigDocuments(where.opencodeDir))).SynaBun;
|
|
431
460
|
} catch { /* no config, no registration */ }
|
|
432
461
|
return false;
|
|
433
462
|
}
|
|
@@ -478,7 +507,7 @@ export function createRulesetInstaller({
|
|
|
478
507
|
}
|
|
479
508
|
const block = blocks[0] || null;
|
|
480
509
|
// A stamp for another tool is not this host's copy, however untouched it is: never updated, never removed.
|
|
481
|
-
if (block && block.host
|
|
510
|
+
if (block && !ownStamp(host, block.host)) return { status: 'conflict', text, bytes, detail: `${foreignBlock(host, block, target.path)} Replace does not apply here: take that block out by hand, then install again.` };
|
|
482
511
|
if (HOSTS[host].carrier === 'file') {
|
|
483
512
|
if (normalise(text) === expected.block) return { status: 'current', text, bytes, block };
|
|
484
513
|
if (!block) return { status: 'modified', text, bytes, block, detail: `${target.path} has no SynaBun markers, so SynaBun treats it as your own file and never replaces it. Move or delete it, then install again.` };
|
|
@@ -511,7 +540,7 @@ export function createRulesetInstaller({
|
|
|
511
540
|
/**
|
|
512
541
|
* The file an `instructions` entry of `configPath` names, or null when the entry is not one plain path: a URL, or
|
|
513
542
|
* a pattern with glob characters. A leading `~` is the installer's home, and a relative path starts at the
|
|
514
|
-
* directory of
|
|
543
|
+
* directory of opencode.json (never at this process's working directory).
|
|
515
544
|
*/
|
|
516
545
|
function entryFile(value, configPath) {
|
|
517
546
|
if (typeof value !== 'string' || !value) return null;
|
|
@@ -530,8 +559,7 @@ export function createRulesetInstaller({
|
|
|
530
559
|
if (path === resolve(owned)) return true;
|
|
531
560
|
try { return realpathSync(path) === realpathSync(owned); } catch { return false; }
|
|
532
561
|
}
|
|
533
|
-
function readOpencodeConfig() {
|
|
534
|
-
const path = layout().opencodeConfig;
|
|
562
|
+
function readOpencodeConfig(path = layout().opencodeConfig) {
|
|
535
563
|
const entry = opencodeEntry();
|
|
536
564
|
const refuse = (why) => ({ path, exists: true, hasEntry: false, cfg: null, text: null, bytes: null, error: `${path} ${why}. SynaBun will not rewrite it: fix the file, or add "${entry}" to its "instructions" list by hand.` });
|
|
537
565
|
let bytes;
|
|
@@ -558,7 +586,7 @@ export function createRulesetInstaller({
|
|
|
558
586
|
return { path, exists: true, hasEntry: (cfg.instructions || []).some((value) => entryIsOwnedFile(value, path)), cfg, text, bytes, error: null };
|
|
559
587
|
}
|
|
560
588
|
/**
|
|
561
|
-
* The text of
|
|
589
|
+
* The text of opencode.json after `edit()`, accepted only when it parses to
|
|
562
590
|
* exactly `cfg`. There is no other way to write this file: when the edit
|
|
563
591
|
* cannot be made on the text, SynaBun refuses rather than write the whole
|
|
564
592
|
* object out again and lose what the user's file spells its own way.
|
|
@@ -570,7 +598,7 @@ export function createRulesetInstaller({
|
|
|
570
598
|
} catch { /* text the editor could not follow */ }
|
|
571
599
|
throw new Error(`${path} could not be edited safely, so SynaBun did not write it. Change its "instructions" list by hand: the entry is "${opencodeEntry()}".`);
|
|
572
600
|
}
|
|
573
|
-
/** What install writes when there is no
|
|
601
|
+
/** What install writes when there is no opencode.json yet: remove deletes the file only while it still holds exactly this. */
|
|
574
602
|
function newConfigText(value) {
|
|
575
603
|
return addToJsonList('{}\n', 'instructions', value);
|
|
576
604
|
}
|
|
@@ -582,7 +610,7 @@ export function createRulesetInstaller({
|
|
|
582
610
|
}
|
|
583
611
|
/**
|
|
584
612
|
* The `instructions` entries that resolve to SynaBun's owned file and that SynaBun has no record of adding: the
|
|
585
|
-
* user's own lines, however they are spelled (`~/...`, relative to
|
|
613
|
+
* user's own lines, however they are spelled (`~/...`, relative to opencode.json, a symlink to the file). One listing
|
|
586
614
|
* of the recorded string is SynaBun's; every other is theirs. A URL or a glob pattern is never one of them.
|
|
587
615
|
*/
|
|
588
616
|
function userEntries(row, config) {
|
|
@@ -592,13 +620,13 @@ export function createRulesetInstaller({
|
|
|
592
620
|
return list.filter((value, index) => index !== mine && entryIsOwnedFile(value, config.path));
|
|
593
621
|
}
|
|
594
622
|
/**
|
|
595
|
-
* One change to
|
|
623
|
+
* One change to opencode.json. `plan(config)` answers null (nothing to do) or
|
|
596
624
|
* {text, done?}; `text: null` deletes the file. The file is replaced only
|
|
597
625
|
* while it still holds the bytes that were read: a change by another program
|
|
598
|
-
* in between is CHANGED_UNDERNEATH, and
|
|
626
|
+
* in between is CHANGED_UNDERNEATH, and opencode.json is left to it.
|
|
599
627
|
*/
|
|
600
|
-
function editOpencodeConfig(tally, plan) {
|
|
601
|
-
const config = readOpencodeConfig();
|
|
628
|
+
function editOpencodeConfig(tally, plan, path = layout().opencodeConfig) {
|
|
629
|
+
const config = readOpencodeConfig(path);
|
|
602
630
|
if (config.error) throw new Error(config.error);
|
|
603
631
|
const step = plan(config);
|
|
604
632
|
if (!step) return;
|
|
@@ -611,7 +639,7 @@ export function createRulesetInstaller({
|
|
|
611
639
|
tally.changed = true;
|
|
612
640
|
if (step.done) step.done();
|
|
613
641
|
}
|
|
614
|
-
/** Lists synabun.md in
|
|
642
|
+
/** Lists synabun.md in opencode.json unless it is listed already, and records the string SynaBun added. */
|
|
615
643
|
function addOpencodeEntry(row, tally) {
|
|
616
644
|
const value = opencodeEntry();
|
|
617
645
|
let listed = null;
|
|
@@ -645,7 +673,7 @@ export function createRulesetInstaller({
|
|
|
645
673
|
const mine = ownedEntry(row, config);
|
|
646
674
|
const others = theirs ? userEntries(row, config) : [];
|
|
647
675
|
if (mine === null && !others.length) return null;
|
|
648
|
-
//
|
|
676
|
+
// An opencode.json install created goes only while its bytes are still what install wrote. Anything the user
|
|
649
677
|
// added since makes it their file: the entries are edited out and the file stays.
|
|
650
678
|
if (mine !== null && row.created.includes(config.path) && config.text === newConfigText(mine)) return { text: null };
|
|
651
679
|
const dropKey = row.created.includes(`${config.path}#instructions`);
|
|
@@ -661,6 +689,60 @@ export function createRulesetInstaller({
|
|
|
661
689
|
});
|
|
662
690
|
}
|
|
663
691
|
|
|
692
|
+
// ── OpenCode 1's config.json ───────────────────────────────────────────────
|
|
693
|
+
// An older SynaBun listed synabun.md in config.json, which OpenCode 2 never reads. A copy SynaBun manages whose
|
|
694
|
+
// recorded entry is there is moved, at the next boot (reconcile) or install: listed in opencode.json, then the one
|
|
695
|
+
// string SynaBun added is taken out of config.json (the file goes when SynaBun made it and it still holds only that
|
|
696
|
+
// string). A remove takes that string out too. A line the user wrote in config.json is never touched. At a boot, a
|
|
697
|
+
// copy config.json no longer lists (the user took the line out, or the file) is an opt-out, as it was with
|
|
698
|
+
// OpenCode 1: never put back in opencode.json. An install, which the user asked for, lists it whatever config.json says.
|
|
699
|
+
function opencode1ConfigPath() {
|
|
700
|
+
return join(layout().opencodeDir, 'config.json');
|
|
701
|
+
}
|
|
702
|
+
/** The entry an older SynaBun recorded adding to config.json, or null. */
|
|
703
|
+
function opencode1Record(row) {
|
|
704
|
+
const owned = row.instructionsEntry;
|
|
705
|
+
return owned && typeof owned.value === 'string' && samePath(owned.config, opencode1ConfigPath()) ? { config: owned.config, value: owned.value } : null;
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Whether config.json still lists the copy (`legacy`: opencode1Record), by any spelling: the line SynaBun added or
|
|
709
|
+
* one of the user's. A config.json SynaBun cannot read as plain JSON cannot say it does not, so it counts as listing.
|
|
710
|
+
*/
|
|
711
|
+
function opencode1Listed(legacy) {
|
|
712
|
+
const config = readOpencodeConfig(legacy.config);
|
|
713
|
+
return !!config.error || config.hasEntry;
|
|
714
|
+
}
|
|
715
|
+
/** Takes the string of `legacy` (opencode1Record) out of config.json, and SynaBun's record of what it made there. */
|
|
716
|
+
function removeOpencode1Entry(row, tally, legacy) {
|
|
717
|
+
editOpencodeConfig(tally, (config) => {
|
|
718
|
+
if (!config.exists || !config.cfg) return null;
|
|
719
|
+
const list = [...(config.cfg.instructions || [])];
|
|
720
|
+
const at = list.lastIndexOf(legacy.value);
|
|
721
|
+
if (at < 0) return null;
|
|
722
|
+
if (row.created.includes(config.path) && config.text === newConfigText(legacy.value)) return { text: null };
|
|
723
|
+
const dropKey = row.created.includes(`${config.path}#instructions`);
|
|
724
|
+
list.splice(at, 1);
|
|
725
|
+
const cfg = { ...config.cfg, instructions: list };
|
|
726
|
+
if (!list.length && dropKey) delete cfg.instructions;
|
|
727
|
+
return { text: configText(config.path, cfg, () => removeFromJsonList(config.text, 'instructions', legacy.value, { dropEmptyKey: dropKey })) };
|
|
728
|
+
}, legacy.config);
|
|
729
|
+
row.created = row.created.filter((path) => !samePath(path, legacy.config) && path !== `${legacy.config}#instructions`);
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* A managed copy listed in config.json only: listed in opencode.json, and SynaBun's string taken out of
|
|
733
|
+
* config.json (a failure there leaves it with a warning: OpenCode 2 does not read that file). False when the row
|
|
734
|
+
* has no such record.
|
|
735
|
+
*/
|
|
736
|
+
function moveOpencode1Entry(row, tally) {
|
|
737
|
+
const legacy = opencode1Record(row);
|
|
738
|
+
if (!legacy) return false;
|
|
739
|
+
addOpencodeEntry(row, tally);
|
|
740
|
+
try { removeOpencode1Entry(row, tally, legacy); } catch (error) {
|
|
741
|
+
tally.warnings.push(`${legacy.config} still lists ${legacy.value} under "instructions" (OpenCode 2 does not read that file): ${error?.message || error}`);
|
|
742
|
+
}
|
|
743
|
+
return true;
|
|
744
|
+
}
|
|
745
|
+
|
|
664
746
|
// ── Writing ────────────────────────────────────────────────────────────────
|
|
665
747
|
/**
|
|
666
748
|
* The pasted copies in `text`, sorted by what install may do with them:
|
|
@@ -700,6 +782,45 @@ export function createRulesetInstaller({
|
|
|
700
782
|
}
|
|
701
783
|
tally.changed = true;
|
|
702
784
|
}
|
|
785
|
+
/**
|
|
786
|
+
* The block an earlier SynaBun wrote where this host's tool also reads rules, under a name this host replaced
|
|
787
|
+
* (Gemini CLI's ~/.gemini/GEMINI.md, host=gemini, which Antigravity reads beside its own ~/.gemini/config/GEMINI.md):
|
|
788
|
+
* once the rules are where the new host keeps them, an untouched old block goes, or the tool would load them twice.
|
|
789
|
+
* An edited one is the user's: it stays, with a warning. A file that held nothing else and that SynaBun created is
|
|
790
|
+
* deleted; any other file keeps everything but the block. Never forced.
|
|
791
|
+
*/
|
|
792
|
+
function moveLegacyBlock(host, file, row, tally) {
|
|
793
|
+
let bytes;
|
|
794
|
+
try { bytes = readBytes(file); } catch { return; }
|
|
795
|
+
if (bytes === null) return;
|
|
796
|
+
const text = bytes.toString('utf8');
|
|
797
|
+
const { blocks, conflict } = findBlocks(text);
|
|
798
|
+
if (conflict) {
|
|
799
|
+
tally.warnings.push(`${conflict.message} in ${file}, which ${HOSTS[host].label} also reads, so SynaBun left it as it is: remove the old SynaBun marker lines by hand.`);
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
const block = blocks[0];
|
|
803
|
+
if (!block || !ownStamp(host, block.host)) return;
|
|
804
|
+
if (!isPristine(block)) {
|
|
805
|
+
tally.warnings.push(`The SynaBun block an earlier version wrote in ${file} was edited, so it stays there. ${HOSTS[host].label} reads that file as well: take that block out by hand, or the rules are loaded twice.`);
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
const next = removeBlock(text);
|
|
809
|
+
const created = Array.isArray(row.created) && row.created.some((path) => samePath(path, file));
|
|
810
|
+
try {
|
|
811
|
+
tally.backup(backedUp(file, host, () => {
|
|
812
|
+
if (created && !isSymlink(file) && withoutBom(next).trim() === '') unlinkUnchanged(file, text);
|
|
813
|
+
else commit(file, next, text);
|
|
814
|
+
}));
|
|
815
|
+
} catch (error) {
|
|
816
|
+
if (error?.code !== 'CHANGED_UNDERNEATH') throw error;
|
|
817
|
+
tally.warnings.push(`${file} changed while SynaBun was moving its old rules out of it, so it was left as it is.`);
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
tally.changed = true;
|
|
821
|
+
row.paths = row.paths.filter((path) => !samePath(path, file));
|
|
822
|
+
row.created = row.created.filter((path) => !samePath(path, file));
|
|
823
|
+
}
|
|
703
824
|
/**
|
|
704
825
|
* One carrier. Returns the status it ended in; writes only when the copy is
|
|
705
826
|
* missing, untouched and old, or (forced) one well-formed copy that was
|
|
@@ -847,8 +968,7 @@ export function createRulesetInstaller({
|
|
|
847
968
|
if (first.block) out.installedVersion = first.block.version;
|
|
848
969
|
if (host === 'opencode') {
|
|
849
970
|
const config = readOpencodeConfig();
|
|
850
|
-
|
|
851
|
-
if (sideFiles.length) out.notes = [`OpenCode also reads ${sideFiles.join(' and ')} in ${primary.dir}; SynaBun writes config.json, the same file its MCP toggle uses.`];
|
|
971
|
+
if (existsSync(join(primary.dir, 'opencode.jsonc'))) out.notes = [`OpenCode also reads opencode.jsonc in ${primary.dir}; SynaBun writes opencode.json, the same file its MCP toggle uses.`];
|
|
852
972
|
if (config.error) return { ...out, state: 'error', error: config.error, detail: config.error };
|
|
853
973
|
if (first.status !== 'missing' && !config.hasEntry) {
|
|
854
974
|
unlisted = `${config.path} does not list it under "instructions", so OpenCode does not load it.`;
|
|
@@ -858,7 +978,7 @@ export function createRulesetInstaller({
|
|
|
858
978
|
return { ...out, state: 'not-installed', installedVersion: null, detail: `${primary.path} exists, but ${unlisted}` };
|
|
859
979
|
}
|
|
860
980
|
}
|
|
861
|
-
// A line in
|
|
981
|
+
// A line in opencode.json that SynaBun did not add points at the file: a remove keeps both unless it is forced.
|
|
862
982
|
if (first.status !== 'missing' && userEntries(row, config).length) out.entry = 'user';
|
|
863
983
|
}
|
|
864
984
|
if (first.status === 'missing' && RANK[worst.status] < RANK.error) return { ...out, installedVersion: null };
|
|
@@ -896,7 +1016,7 @@ export function createRulesetInstaller({
|
|
|
896
1016
|
};
|
|
897
1017
|
for (const target of targets('claude')) add(target.legacyFile, 'claude', 'global');
|
|
898
1018
|
for (const target of targets('codex')) add(target.path, 'codex', 'global');
|
|
899
|
-
for (const target of targets('
|
|
1019
|
+
for (const target of targets('antigravity')) { add(target.path, 'antigravity', 'global'); add(target.legacyBlock, 'antigravity', 'global'); }
|
|
900
1020
|
for (const target of targets('opencode')) add(target.legacyFile, 'opencode', 'global');
|
|
901
1021
|
for (const dir of projectPaths()) {
|
|
902
1022
|
for (const [name, host] of PROJECT_FILES) add(join(dir, name), host, 'project');
|
|
@@ -991,7 +1111,8 @@ export function createRulesetInstaller({
|
|
|
991
1111
|
stripLegacy(host, target.legacyFile, tally);
|
|
992
1112
|
}
|
|
993
1113
|
}
|
|
994
|
-
if (host === 'opencode') addOpencodeEntry(row, tally);
|
|
1114
|
+
if (host === 'opencode' && !moveOpencode1Entry(row, tally)) addOpencodeEntry(row, tally);
|
|
1115
|
+
for (const target of list) if (target.legacyBlock) moveLegacyBlock(host, target.legacyBlock, row, tally);
|
|
995
1116
|
|
|
996
1117
|
Object.assign(row, {
|
|
997
1118
|
managed: true,
|
|
@@ -1055,10 +1176,10 @@ export function createRulesetInstaller({
|
|
|
1055
1176
|
* first; damaged markers, a block stamped for another tool, a symlinked owned
|
|
1056
1177
|
* file and a file that cannot be read are refused either way.
|
|
1057
1178
|
*
|
|
1058
|
-
* OpenCode: a line in
|
|
1179
|
+
* OpenCode: a line in opencode.json that points at the owned file and that
|
|
1059
1180
|
* SynaBun did not add keeps the file too (`kept`, reason `listed-in-config`):
|
|
1060
1181
|
* nothing is ever left pointing at a file SynaBun deleted. With `force` that
|
|
1061
|
-
* line goes as well, after a backup of
|
|
1182
|
+
* line goes as well, after a backup of opencode.json, and then the file.
|
|
1062
1183
|
*
|
|
1063
1184
|
* Symlinks at a block carrier (AGENTS.md, GEMINI.md): the block is taken out
|
|
1064
1185
|
* of the file the link points at and the link stays, exactly as install wrote
|
|
@@ -1076,7 +1197,7 @@ export function createRulesetInstaller({
|
|
|
1076
1197
|
* True while a copy that keeps a removal open is still on disk: one SynaBun
|
|
1077
1198
|
* should have taken and could not. That is damaged markers, a file that
|
|
1078
1199
|
* cannot be read, an untouched copy of this host's rules (behind a symlink,
|
|
1079
|
-
* or held back by another refusal), and for OpenCode
|
|
1200
|
+
* or held back by another refusal), and for OpenCode an opencode.json that
|
|
1080
1201
|
* cannot be edited while SynaBun's entry is on record. A copy the user
|
|
1081
1202
|
* edited, a file without markers and a block stamped for another tool are
|
|
1082
1203
|
* not: the keep rule leaves the first two to the user, and the third was
|
|
@@ -1126,7 +1247,7 @@ export function createRulesetInstaller({
|
|
|
1126
1247
|
const created = new Set(row.created);
|
|
1127
1248
|
// Every place a copy can be: the host's carriers, the row's paths, and what an unfinished removal recorded.
|
|
1128
1249
|
const recorded = Array.isArray(row.removal?.paths) ? row.removal.paths.filter((path) => typeof path === 'string') : [];
|
|
1129
|
-
const paths = unique([...list.map((target) => target.path), ...row.paths, ...recorded]);
|
|
1250
|
+
const paths = unique([...list.map((target) => target.path), ...list.map((target) => target.legacyBlock).filter(Boolean), ...row.paths, ...recorded]);
|
|
1130
1251
|
/** Intent first: the paths about to go are saved before the first of them is touched. */
|
|
1131
1252
|
const recordIntent = (planned) => {
|
|
1132
1253
|
row.removal = { at: stamp(), error: INTERRUPTED, paths: unique(planned) };
|
|
@@ -1169,6 +1290,11 @@ export function createRulesetInstaller({
|
|
|
1169
1290
|
if (go && doomed.length) recordIntent(doomed.map((entry) => entry.path));
|
|
1170
1291
|
if (go && together) {
|
|
1171
1292
|
try { removeOpencodeEntry(row, tally, { theirs: force && doomed.length > 0 }); } catch (error) { refuse(layout().opencodeConfig, 'error', error?.message || String(error)); }
|
|
1293
|
+
// The string an older SynaBun added to OpenCode 1's config.json goes too (OpenCode 2 never read it).
|
|
1294
|
+
const legacy = opencode1Record(row);
|
|
1295
|
+
if (legacy) {
|
|
1296
|
+
try { removeOpencode1Entry(row, tally, legacy); } catch (error) { tally.warnings.push(`${legacy.config} still lists ${legacy.value} under "instructions": ${error?.message || error}`); }
|
|
1297
|
+
}
|
|
1172
1298
|
}
|
|
1173
1299
|
if (!(together && refused.length)) {
|
|
1174
1300
|
for (const { path, text } of go ? doomed : []) {
|
|
@@ -1196,7 +1322,7 @@ export function createRulesetInstaller({
|
|
|
1196
1322
|
if (conflict) { refuse(path, 'conflict', `${conflict.message} in ${path}. SynaBun will not guess: remove the SynaBun marker lines by hand, then remove again.`); continue; }
|
|
1197
1323
|
const block = blocks[0];
|
|
1198
1324
|
if (!block) continue;
|
|
1199
|
-
if (block.host
|
|
1325
|
+
if (!ownStamp(host, block.host)) { refuse(path, 'conflict', `${foreignBlock(host, block, path)} Take that block out by hand if you no longer want it.`); continue; }
|
|
1200
1326
|
const pristine = isPristine(block);
|
|
1201
1327
|
if (!force && !pristine) {
|
|
1202
1328
|
left.push({ path, reason: 'edited', message: `The SynaBun block in ${path} was edited, so SynaBun left it in place and no longer manages it.` });
|
|
@@ -1253,7 +1379,7 @@ export function createRulesetInstaller({
|
|
|
1253
1379
|
// (`created`, OpenCode's entry) stays on record, so a forced remove or a Replace can still clean up. The same
|
|
1254
1380
|
// row for a refusal that leaves nothing to wait for (a block stamped for another tool, a copy that turned out
|
|
1255
1381
|
// edited): the host is opted out, and no removal is kept open over a file that was never SynaBun's to take.
|
|
1256
|
-
// `paths` are places a copy of the rules is:
|
|
1382
|
+
// `paths` are places a copy of the rules is: opencode.json, which a refusal can name, is not one of them.
|
|
1257
1383
|
const config = host === 'opencode' ? layout().opencodeConfig : null;
|
|
1258
1384
|
Object.assign(row, {
|
|
1259
1385
|
managed: false, installedVersion: null, installedSha: null, path: primary.path,
|
|
@@ -1349,7 +1475,24 @@ export function createRulesetInstaller({
|
|
|
1349
1475
|
const config = host === 'opencode' ? readOpencodeConfig() : null;
|
|
1350
1476
|
if (config?.error) { states[host] = 'error'; continue; }
|
|
1351
1477
|
const first = isDir(primary.dir) ? inspect(host, primary, expected) : { status: 'missing' };
|
|
1352
|
-
|
|
1478
|
+
// Listed by an older SynaBun in OpenCode 1's config.json only: moved to opencode.json, never an opt-out. A copy
|
|
1479
|
+
// config.json does not list any more is not moved: the user took it out, which is the opt-out below.
|
|
1480
|
+
const older = config && first.status !== 'missing' && !config.hasEntry ? opencode1Record(row) : null;
|
|
1481
|
+
const moving = older !== null && opencode1Listed(older);
|
|
1482
|
+
if (first.status === 'missing' && row.movedFrom && isDir(primary.dir)) {
|
|
1483
|
+
// A host this SynaBun replaced (Gemini CLI → Antigravity) was managed: its rules go where the new host reads
|
|
1484
|
+
// them, and the old block goes (installHost moves it). Not an opt-out: nothing was deleted by the user.
|
|
1485
|
+
const moved = installHost(state, host, { force: false }, call);
|
|
1486
|
+
if (moved.ok) { delete row.movedFrom; updated.push(host); to = expected.version; from = from || row.installedVersion || null; }
|
|
1487
|
+
states[host] = hostStatus(host, state).state;
|
|
1488
|
+
continue;
|
|
1489
|
+
}
|
|
1490
|
+
if (first.status === 'missing' && row.movedFrom) {
|
|
1491
|
+
// The new host's folder is not there yet (Antigravity not installed): nothing to move to; asked again later.
|
|
1492
|
+
states[host] = 'not-installed';
|
|
1493
|
+
continue;
|
|
1494
|
+
}
|
|
1495
|
+
if (first.status === 'missing' || (config && !config.hasEntry && !moving)) {
|
|
1353
1496
|
// The user deleted it: an opt-out, never a reason to put it back. (A copy SynaBun's own removal took is
|
|
1354
1497
|
// not this case: that removal is on record and was dealt with above.)
|
|
1355
1498
|
Object.assign(row, { managed: false, optedOutAt: stamp() });
|
|
@@ -1358,6 +1501,7 @@ export function createRulesetInstaller({
|
|
|
1358
1501
|
continue;
|
|
1359
1502
|
}
|
|
1360
1503
|
const tally = call.tally(host);
|
|
1504
|
+
if (moving) moveOpencode1Entry(row, tally);
|
|
1361
1505
|
const known = new Set(row.paths.map((path) => realKey(path)));
|
|
1362
1506
|
let primaryCurrent = first.status === 'current';
|
|
1363
1507
|
for (const target of list) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SynaBun — one entry of a JSON list, edited as text (pure, no fs)
|
|
3
3
|
// ═══════════════════════════════════════════
|
|
4
4
|
//
|
|
5
|
-
// OpenCode's
|
|
5
|
+
// OpenCode's opencode.json belongs to the user. Parsing it and writing it back
|
|
6
6
|
// would re-indent it, re-space it and drop whatever JSON.stringify spells
|
|
7
7
|
// differently, all to add one string to one list. These two functions change
|
|
8
8
|
// only the characters of that entry (and of the key, when SynaBun adds or takes
|
|
@@ -18,7 +18,7 @@ import { normalise, sha12 } from './normalise.js';
|
|
|
18
18
|
|
|
19
19
|
export { normalise, sha12 };
|
|
20
20
|
|
|
21
|
-
export const RULESET_HOSTS = Object.freeze(['claude', 'codex', 'opencode', '
|
|
21
|
+
export const RULESET_HOSTS = Object.freeze(['claude', 'codex', 'opencode', 'antigravity', 'cursor']);
|
|
22
22
|
export const RULESETS_DIR = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..', 'templates', 'rulesets');
|
|
23
23
|
|
|
24
24
|
const HOST_SLOT = '<!-- host -->';
|
|
@@ -3,7 +3,7 @@ import { normalizeMemoryEvents, ingestMemoryEvents } from '../../mcp-server/dist
|
|
|
3
3
|
import { detectProject } from '../../mcp-server/dist/config.js';
|
|
4
4
|
/**
|
|
5
5
|
* Session Cache Builder — populates session_cache + session_fts for
|
|
6
|
-
* Claude Code, Codex CLI, and
|
|
6
|
+
* Claude Code, Codex CLI, OpenCode and Antigravity so the Resume surfaces can do
|
|
7
7
|
* full-body keyword search via FTS5.
|
|
8
8
|
*
|
|
9
9
|
* Per-provider rebuilders walk the provider's session storage, extract
|
|
@@ -24,7 +24,8 @@ import {
|
|
|
24
24
|
} from './db.js';
|
|
25
25
|
import { parseLine } from './session-chunker.js';
|
|
26
26
|
import { listCodexSessionsFromAccounts } from './codex-session-catalog.js';
|
|
27
|
-
import {
|
|
27
|
+
import { OPENCODE_SESSION_TABLES, hasOpencodeSessionTables, v2MessageText } from './opencode-db-schema.js';
|
|
28
|
+
import { listAntigravityConversations, parseAntigravityTranscript, readTranscriptText } from './antigravity/transcripts.js';
|
|
28
29
|
|
|
29
30
|
const MAX_BODY = 256 * 1024;
|
|
30
31
|
const MAX_MSG_CHARS = 8 * 1024;
|
|
@@ -381,18 +382,15 @@ export function rebuildCodexCache({ project, projects, accounts, onProgress } =
|
|
|
381
382
|
|
|
382
383
|
// --- OpenCode ---
|
|
383
384
|
|
|
384
|
-
//
|
|
385
|
-
//
|
|
386
|
-
|
|
387
|
-
export function rebuildOpencodeCache({ getOpencodeDb, onProgress, protocol = null } = {}) {
|
|
385
|
+
// OpenCode 2 keeps its sessions in session_v2 and their text in session_message rows
|
|
386
|
+
// (lib/opencode-db-schema.js); a file without those tables has nothing to index.
|
|
387
|
+
export function rebuildOpencodeCache({ getOpencodeDb, onProgress } = {}) {
|
|
388
388
|
const emit = onProgress || (() => {});
|
|
389
389
|
if (typeof getOpencodeDb !== 'function') return { sessions: 0, updated: 0 };
|
|
390
390
|
|
|
391
391
|
const ocdb = getOpencodeDb();
|
|
392
|
-
if (!ocdb) return { sessions: 0, updated: 0 };
|
|
393
|
-
const
|
|
394
|
-
if (!flavor) return { sessions: 0, updated: 0 };
|
|
395
|
-
const tables = sessionTablesFor(flavor);
|
|
392
|
+
if (!ocdb || !hasOpencodeSessionTables(ocdb)) return { sessions: 0, updated: 0 };
|
|
393
|
+
const tables = OPENCODE_SESSION_TABLES;
|
|
396
394
|
|
|
397
395
|
let sessions;
|
|
398
396
|
try {
|
|
@@ -409,29 +407,19 @@ export function rebuildOpencodeCache({ getOpencodeDb, onProgress, protocol = nul
|
|
|
409
407
|
let total = sessions.length;
|
|
410
408
|
let updated = 0;
|
|
411
409
|
|
|
412
|
-
//
|
|
413
|
-
//
|
|
414
|
-
// OpenCode 2: one session_message row per message, its text in `data`
|
|
415
|
-
// (v2MessageText); read as the same { part_id, part_created, pdata, mdata } rows.
|
|
410
|
+
// One session_message row per message, its text in `data` (v2MessageText); read as
|
|
411
|
+
// { part_id, part_created, pdata, mdata } rows.
|
|
416
412
|
let partStmt;
|
|
417
413
|
try {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
}).filter(Boolean),
|
|
428
|
-
};
|
|
429
|
-
})()
|
|
430
|
-
: ocdb.prepare(`SELECT p.id AS part_id, p.time_created AS part_created, p.data AS pdata, m.data AS mdata
|
|
431
|
-
FROM part p
|
|
432
|
-
LEFT JOIN message m ON m.id = p.message_id
|
|
433
|
-
WHERE p.session_id = ?
|
|
434
|
-
ORDER BY p.time_created ASC`);
|
|
414
|
+
const rows = ocdb.prepare(`SELECT id, type, time_created, data FROM session_message
|
|
415
|
+
WHERE session_id = ? AND type IN ('user', 'assistant')
|
|
416
|
+
ORDER BY seq ASC`);
|
|
417
|
+
partStmt = {
|
|
418
|
+
all: (sessionId) => rows.all(sessionId).map((row) => {
|
|
419
|
+
const said = v2MessageText(row.type, row.data);
|
|
420
|
+
return said ? { part_id: row.id, part_created: row.time_created, pdata: JSON.stringify({ type: 'text', text: said.text }), mdata: JSON.stringify({ role: said.role }) } : null;
|
|
421
|
+
}).filter(Boolean),
|
|
422
|
+
};
|
|
435
423
|
} catch { partStmt = null; }
|
|
436
424
|
|
|
437
425
|
for (const row of sessions) {
|
|
@@ -506,6 +494,68 @@ export function rebuildOpencodeCache({ getOpencodeDb, onProgress, protocol = nul
|
|
|
506
494
|
return { sessions: total, updated };
|
|
507
495
|
}
|
|
508
496
|
|
|
497
|
+
// --- Antigravity ---
|
|
498
|
+
|
|
499
|
+
// agy keeps one transcript.jsonl per conversation (lib/antigravity/transcripts.js). Every conversation it holds,
|
|
500
|
+
// SynaBun's brain and run homes included, is queued for memory capture; the user's own (the panel's and a terminal
|
|
501
|
+
// agy's, the only ones the panel can load again) also go into the Resume index, titled as Antigravity titles them.
|
|
502
|
+
// A conversation unchanged since the last pass (size, time, folder, title) is not read again. `only`: one
|
|
503
|
+
// conversation (a panel turn just ended), the others left as they are. Request/timer paths read at most
|
|
504
|
+
// MAX_BODY bytes per transcript: the index is bounded; full transcripts remain available to memory capture.
|
|
505
|
+
export function rebuildAntigravityCache({ stores = [], only = null, onProgress, list = listAntigravityConversations, read = readTranscriptText } = {}) {
|
|
506
|
+
const emit = onProgress || (() => {});
|
|
507
|
+
let conversations;
|
|
508
|
+
try { conversations = list(stores); } catch { return { sessions: 0, updated: 0 }; }
|
|
509
|
+
if (only) conversations = conversations.filter((c) => c.sessionId === only);
|
|
510
|
+
const listed = new Set(conversations.filter((c) => c.store === 'user').map((c) => c.sessionId));
|
|
511
|
+
const total = listed.size;
|
|
512
|
+
let updated = 0;
|
|
513
|
+
for (const c of conversations) {
|
|
514
|
+
try {
|
|
515
|
+
queueMemoryCapture({ host: 'antigravity', sessionId: c.sessionId, filePath: c.transcript, cwd: c.cwd || undefined, project: c.cwd ? detectProject(c.cwd) : 'global', size: c.size });
|
|
516
|
+
} catch { /* memory capture is best effort */ }
|
|
517
|
+
if (c.store !== 'user') continue;
|
|
518
|
+
const mtimeIso = new Date(c.mtimeMs).toISOString();
|
|
519
|
+
const existing = getSessionCacheEntry(c.sessionId, 'antigravity');
|
|
520
|
+
if (existing && !existing.deleted && Number(existing.file_size) === c.size && existing.file_mtime === mtimeIso
|
|
521
|
+
&& (existing.project_path || null) === (c.cwd || null) && (!c.title || existing.first_prompt === c.title)) continue;
|
|
522
|
+
const parsed = parseAntigravityTranscript(read(c.transcript, { maxBytes: MAX_BODY }));
|
|
523
|
+
let body = '';
|
|
524
|
+
for (const message of parsed.messages) {
|
|
525
|
+
if (message.role !== 'user' && message.role !== 'assistant') continue;
|
|
526
|
+
if (message.text) body = appendBody(body, message.text.slice(0, MAX_MSG_CHARS));
|
|
527
|
+
}
|
|
528
|
+
const firstPrompt = c.title || parsed.firstPrompt;
|
|
529
|
+
const project = c.cwd ? basename(c.cwd) : null;
|
|
530
|
+
upsertSessionCache({
|
|
531
|
+
session_id: c.sessionId,
|
|
532
|
+
provider: 'antigravity',
|
|
533
|
+
project,
|
|
534
|
+
project_path: c.cwd,
|
|
535
|
+
git_branch: null,
|
|
536
|
+
first_prompt: firstPrompt,
|
|
537
|
+
message_count: parsed.messageCount,
|
|
538
|
+
created: parsed.created,
|
|
539
|
+
modified: c.updatedAt || parsed.modified || mtimeIso,
|
|
540
|
+
file_path: c.transcript,
|
|
541
|
+
file_size: c.size,
|
|
542
|
+
file_mtime: mtimeIso,
|
|
543
|
+
body_size: body.length,
|
|
544
|
+
deleted: 0,
|
|
545
|
+
});
|
|
546
|
+
upsertSessionFts({ session_id: c.sessionId, provider: 'antigravity', project, first_prompt: firstPrompt, body });
|
|
547
|
+
updated++;
|
|
548
|
+
emit({ type: 'cache:session', provider: 'antigravity', sessionId: c.sessionId, done: updated, total });
|
|
549
|
+
}
|
|
550
|
+
// A conversation Antigravity no longer has (deleted there, or its folder cleared) leaves Resume.
|
|
551
|
+
if (!only) {
|
|
552
|
+
for (const cached of listSessionCache('antigravity', { limit: 100000 })) {
|
|
553
|
+
if (!listed.has(cached.session_id) && !cached.deleted) markSessionDeleted(cached.session_id, 'antigravity', true);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
return { sessions: total, updated };
|
|
557
|
+
}
|
|
558
|
+
|
|
509
559
|
// --- Single-session refresh (for piggyback from session-indexer) ---
|
|
510
560
|
|
|
511
561
|
export function updateSessionCacheEntry(provider, sessionId, opts = {}) {
|