synabun 2.0.10 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +207 -0
- package/README.md +25 -2
- package/THIRD-PARTY-LICENSES.md +22 -0
- package/bin/synabun.js +71 -24
- package/docs/whatsapp.md +13 -13
- package/hooks/claude-code/pre-websearch.mjs +12 -1
- package/hooks/claude-code/shared.mjs +5 -0
- package/hooks/claude-code/stop.mjs +1 -1
- package/lib/claude-hooks.js +172 -18
- package/lib/client-config-repair.js +30 -17
- package/lib/desktop-app.js +7 -1
- package/lib/external-tools.js +7 -6
- package/lib/first-launch-protection.js +57 -12
- package/lib/mcp-dist.js +176 -0
- package/lib/release-npm-ci.mjs +138 -0
- package/lib/release-publish.mjs +91 -0
- package/lib/release-scan.mjs +50 -0
- package/lib/server-crash-record.js +123 -0
- package/lib/server-exit.js +318 -0
- package/lib/server-supervisor.js +508 -0
- package/lib/start-launcher.js +37 -4
- package/lib/tools-cli.js +45 -0
- package/lib/update-snapshot.js +302 -0
- package/lib/virustotal.mjs +203 -0
- package/lib/windows-crash-event.js +269 -0
- package/mcp-server/dist/http.d.ts +20 -1
- package/mcp-server/dist/http.d.ts.map +1 -1
- package/mcp-server/dist/http.js +59 -12
- package/mcp-server/dist/http.js.map +1 -1
- package/mcp-server/dist/index.d.ts +33 -27
- package/mcp-server/dist/index.d.ts.map +1 -1
- package/mcp-server/dist/index.js +128 -143
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/preload.js +1 -1
- package/mcp-server/dist/preload.js.map +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -1
- package/mcp-server/dist/services/budget-judgments.js +5 -3
- package/mcp-server/dist/services/budget-judgments.js.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.d.ts +6 -2
- package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.js +81 -28
- package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
- package/mcp-server/dist/services/identity.d.ts +2 -2
- package/mcp-server/dist/services/identity.js +2 -2
- package/mcp-server/dist/services/memory-judge-backfill.d.ts +6 -0
- package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
- package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
- package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
- package/mcp-server/dist/services/memory-sessions.d.ts +1 -1
- package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -1
- package/mcp-server/dist/services/memory-sessions.js +28 -2
- package/mcp-server/dist/services/memory-sessions.js.map +1 -1
- package/mcp-server/dist/services/neural-interface.d.ts +18 -11
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js +67 -11
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/server-instructions.d.ts +7 -2
- package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
- package/mcp-server/dist/services/server-instructions.js +22 -63
- package/mcp-server/dist/services/server-instructions.js.map +1 -1
- package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
- package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-catalog.js +339 -0
- package/mcp-server/dist/services/tool-catalog.js.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
- package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
- package/mcp-server/dist/services/tool-list.d.ts +108 -0
- package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-list.js +334 -0
- package/mcp-server/dist/services/tool-list.js.map +1 -0
- package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
- package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
- package/mcp-server/dist/services/tool-runtime.js +400 -0
- package/mcp-server/dist/services/tool-runtime.js.map +1 -0
- package/mcp-server/dist/services/typesafe-config.js +1 -1
- package/mcp-server/dist/services/typesafe-config.js.map +1 -1
- package/mcp-server/dist/services/whiteboard-geometry.d.ts +26 -2
- package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
- package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
- package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +14 -14
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +29 -19
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
- package/mcp-server/dist/tools/choice.d.ts +6 -0
- package/mcp-server/dist/tools/choice.d.ts.map +1 -1
- package/mcp-server/dist/tools/choice.js +18 -13
- package/mcp-server/dist/tools/choice.js.map +1 -1
- package/mcp-server/dist/tools/git-tools.js +2 -2
- package/mcp-server/dist/tools/git-tools.js.map +1 -1
- package/mcp-server/dist/tools/image-tools.d.ts +1 -1
- package/mcp-server/dist/tools/image-tools.js +1 -1
- package/mcp-server/dist/tools/morelogin.d.ts.map +1 -1
- package/mcp-server/dist/tools/morelogin.js +9 -6
- package/mcp-server/dist/tools/morelogin.js.map +1 -1
- package/mcp-server/dist/tools/skill-tools.d.ts +505 -0
- package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill-tools.js +642 -0
- package/mcp-server/dist/tools/skill-tools.js.map +1 -0
- package/mcp-server/dist/tools/skill.d.ts +7 -0
- package/mcp-server/dist/tools/skill.d.ts.map +1 -0
- package/mcp-server/dist/tools/skill.js +11 -0
- package/mcp-server/dist/tools/skill.js.map +1 -0
- package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
- package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
- package/mcp-server/dist/tools/tool-groups.js +147 -0
- package/mcp-server/dist/tools/tool-groups.js.map +1 -0
- package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-format.js +7 -4
- package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
- package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
- package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/src/http.ts +75 -12
- package/mcp-server/src/index.ts +147 -154
- package/mcp-server/src/preload.ts +12 -12
- package/mcp-server/src/services/budget-judgments.ts +5 -3
- package/mcp-server/src/services/codex-config-heal.ts +80 -29
- package/mcp-server/src/services/identity.ts +2 -2
- package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
- package/mcp-server/src/services/memory-sessions.ts +24 -3
- package/mcp-server/src/services/neural-interface.ts +81 -21
- package/mcp-server/src/services/server-instructions.ts +29 -64
- package/mcp-server/src/services/tool-catalog.ts +403 -0
- package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
- package/mcp-server/src/services/tool-list.ts +410 -0
- package/mcp-server/src/services/tool-runtime.ts +457 -0
- package/mcp-server/src/services/typesafe-config.ts +1 -1
- package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
- package/mcp-server/src/tools/agents.ts +29 -20
- package/mcp-server/src/tools/choice.ts +17 -12
- package/mcp-server/src/tools/git-tools.ts +2 -2
- package/mcp-server/src/tools/image-tools.ts +1 -1
- package/mcp-server/src/tools/morelogin.ts +6 -4
- package/mcp-server/src/tools/skill-tools.ts +592 -0
- package/mcp-server/src/tools/skill.ts +13 -0
- package/mcp-server/src/tools/tool-groups.ts +164 -0
- package/mcp-server/src/tools/whiteboard-format.ts +9 -3
- package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
- package/neural-interface/i18n/en.json +3953 -228
- package/neural-interface/i18n/pt-BR.json +3901 -179
- package/neural-interface/lib/agent-sandbox-elevation.js +6 -0
- package/neural-interface/lib/antigravity/acp-client-host.js +554 -0
- package/neural-interface/lib/antigravity/acp-connection.js +299 -0
- package/neural-interface/lib/antigravity/bypass.js +100 -0
- package/neural-interface/lib/antigravity/catalog.js +273 -0
- package/neural-interface/lib/antigravity/home.js +260 -0
- package/neural-interface/lib/antigravity/migrate-gemini.js +139 -0
- package/neural-interface/lib/antigravity/panel-bridge.js +1058 -0
- package/neural-interface/lib/antigravity/policy-hook.mjs +78 -0
- package/neural-interface/lib/antigravity/policy.js +74 -0
- package/neural-interface/lib/antigravity/tool-call.js +178 -0
- package/neural-interface/lib/antigravity/transcripts.js +252 -0
- package/neural-interface/lib/antigravity/usage.js +43 -0
- package/neural-interface/lib/assistant-api.js +128 -28
- package/neural-interface/lib/assistant-brains/antigravity.js +423 -0
- package/neural-interface/lib/assistant-brains/claude.js +4 -3
- package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +12 -2
- package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +32 -9
- package/neural-interface/lib/assistant-brains/codex.js +9 -5
- package/neural-interface/lib/assistant-brains/opencode.js +120 -54
- package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +28 -13
- package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +59 -19
- package/neural-interface/lib/assistant-budget-planner.js +7 -3
- package/neural-interface/lib/assistant-budget-split.js +42 -15
- package/neural-interface/lib/assistant-catalog.js +81 -15
- package/neural-interface/lib/assistant-config.js +6 -3
- package/neural-interface/lib/assistant-dispatch.js +1073 -200
- package/neural-interface/lib/assistant-envelope.js +156 -2
- package/neural-interface/lib/assistant-evidence.js +80 -0
- package/neural-interface/lib/assistant-hidden-models.js +7 -5
- package/neural-interface/lib/assistant-persona.js +93 -19
- package/neural-interface/lib/assistant-plan-permissions.js +25 -9
- package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
- package/neural-interface/lib/assistant-route-gate.js +6 -4
- package/neural-interface/lib/assistant-router.js +245 -38
- package/neural-interface/lib/assistant-runtime.js +214 -30
- package/neural-interface/lib/assistant-task-prompt.js +87 -21
- package/neural-interface/lib/assistant-tools.js +51 -0
- package/neural-interface/lib/assistant-usage.js +29 -0
- package/neural-interface/lib/backup-service.js +626 -4
- package/neural-interface/lib/backup-zip-reader.js +10 -5
- package/neural-interface/lib/backup-zip-writer.js +257 -0
- package/neural-interface/lib/browser-execution.js +10 -2
- package/neural-interface/lib/browser-guard-cdp.js +84 -0
- package/neural-interface/lib/browser-network-guard.js +476 -0
- package/neural-interface/lib/browser-policy-roots.js +64 -0
- package/neural-interface/lib/browser-tool-policy.js +198 -38
- package/neural-interface/lib/claude-agent-bridge.js +11 -2
- package/neural-interface/lib/claude-history-cache.js +210 -0
- package/neural-interface/lib/claude-hooks-status.js +103 -0
- package/neural-interface/lib/claude-model-catalog.js +5 -1
- package/neural-interface/lib/claude-temporary.js +5 -11
- package/neural-interface/lib/cli-install-api.js +1 -1
- package/neural-interface/lib/cli-install.js +163 -154
- package/neural-interface/lib/cli-resolver.js +13 -3
- package/neural-interface/lib/cli-update-planner.js +52 -41
- package/neural-interface/lib/cloudflared/tunnel.js +42 -2
- package/neural-interface/lib/codex-mcp-approvals.js +11 -0
- package/neural-interface/lib/codex-rollout-reader.js +52 -0
- package/neural-interface/lib/codex-worker-app-server.js +191 -0
- package/neural-interface/lib/confined-fs.js +30 -3
- package/neural-interface/lib/crash-notice-api.js +98 -0
- package/neural-interface/lib/editor-completion-opencode.js +68 -68
- package/neural-interface/lib/editor-git-api.js +3 -20
- package/neural-interface/lib/exec-loop-command.js +13 -10
- package/neural-interface/lib/file-explorer-api.js +74 -40
- package/neural-interface/lib/file-explorer-watch.js +9 -3
- package/neural-interface/lib/git-bash/install.js +52 -6
- package/neural-interface/lib/git-bash/manager.js +59 -17
- package/neural-interface/lib/git-bash/pins.js +12 -0
- package/neural-interface/lib/git-read.js +2 -2
- package/neural-interface/lib/git-status-runner.js +390 -0
- package/neural-interface/lib/git-status-watchdog.js +40 -0
- package/neural-interface/lib/greeting/budgets.js +1 -0
- package/neural-interface/lib/greeting/engine.js +2 -2
- package/neural-interface/lib/greeting/sources.js +10 -12
- package/neural-interface/lib/greeting/writer.js +1 -1
- package/neural-interface/lib/http-guards.js +8 -2
- package/neural-interface/lib/install-details.js +4 -1
- package/neural-interface/lib/mcp-agent-servers.js +67 -0
- package/neural-interface/lib/mcp-client-config.js +35 -33
- package/neural-interface/lib/mcp-external-servers.js +332 -0
- package/neural-interface/lib/mcp-installer.js +2 -1
- package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
- package/neural-interface/lib/memory-session-capture.js +17 -3
- package/neural-interface/lib/morelogin.js +177 -25
- package/neural-interface/lib/native-loop-providers.js +965 -66
- package/neural-interface/lib/native-loop-runtime.js +290 -42
- package/neural-interface/lib/opencode-config.js +557 -0
- package/neural-interface/lib/opencode-db-schema.js +17 -34
- package/neural-interface/lib/opencode-history.js +48 -218
- package/neural-interface/lib/opencode-mcp-ready.js +108 -0
- package/neural-interface/lib/opencode-native-boundary.js +53 -0
- package/neural-interface/lib/opencode-protocol.js +249 -112
- package/neural-interface/lib/opencode-runtime-config.js +32 -22
- package/neural-interface/lib/opencode-serve-records.js +39 -21
- package/neural-interface/lib/opencode-v2-client.js +48 -153
- package/neural-interface/lib/opencode-v2-ws-requests.js +36 -210
- package/neural-interface/lib/opencode-worker-data.js +27 -0
- package/neural-interface/lib/opencode2-client.js +73 -37
- package/neural-interface/lib/opencode2-proxy.js +23 -63
- package/neural-interface/lib/opencode2-translate.js +51 -2
- package/neural-interface/lib/owner-authority.js +249 -0
- package/neural-interface/lib/page-session.js +275 -0
- package/neural-interface/lib/path-confine.js +12 -9
- package/neural-interface/lib/peer-identity.js +793 -0
- package/neural-interface/lib/pty-host/core.js +28 -1
- package/neural-interface/lib/pty-host/lifetime.js +12 -0
- package/neural-interface/lib/pty-host/manager.js +12 -1
- package/neural-interface/lib/remote-policy.js +1 -1
- package/neural-interface/lib/request-gate.js +20 -2
- package/neural-interface/lib/rulesets/api.js +7 -6
- package/neural-interface/lib/rulesets/fs-safe.js +1 -1
- package/neural-interface/lib/rulesets/installer.js +180 -36
- package/neural-interface/lib/rulesets/json-edit.js +1 -1
- package/neural-interface/lib/rulesets/render.js +1 -1
- package/neural-interface/lib/session-cache-builder.js +81 -31
- package/neural-interface/lib/session-title-generator.js +58 -36
- package/neural-interface/lib/skills/api-v2.js +495 -0
- package/neural-interface/lib/skills/bundle.js +418 -0
- package/neural-interface/lib/skills/catalog.js +298 -0
- package/neural-interface/lib/skills/creation-api.js +191 -0
- package/neural-interface/lib/skills/creation-brief.js +247 -0
- package/neural-interface/lib/skills/creation-sources.js +285 -0
- package/neural-interface/lib/skills/creation.js +843 -0
- package/neural-interface/lib/skills/deploy.js +569 -0
- package/neural-interface/lib/skills/digest.js +119 -0
- package/neural-interface/lib/skills/discover.js +111 -0
- package/neural-interface/lib/skills/draft-confinement.js +216 -0
- package/neural-interface/lib/skills/eval-confinement.js +399 -0
- package/neural-interface/lib/skills/eval-sandbox.js +280 -0
- package/neural-interface/lib/skills/eval-trace.js +135 -0
- package/neural-interface/lib/skills/evals-api.js +212 -0
- package/neural-interface/lib/skills/evals.js +1573 -0
- package/neural-interface/lib/skills/export.js +203 -0
- package/neural-interface/lib/skills/frontmatter.js +64 -0
- package/neural-interface/lib/skills/health.js +75 -0
- package/neural-interface/lib/skills/json-edit.js +165 -0
- package/neural-interface/lib/skills/known-bridge-digests.json +441 -0
- package/neural-interface/lib/skills/known-bridges.js +96 -0
- package/neural-interface/lib/skills/library.js +823 -0
- package/neural-interface/lib/skills/local-store.js +21 -0
- package/neural-interface/lib/skills/migration.js +433 -0
- package/neural-interface/lib/skills/operations.js +45 -0
- package/neural-interface/lib/skills/ownership.js +427 -0
- package/neural-interface/lib/skills/packages.js +88 -0
- package/neural-interface/lib/skills/reviews.js +212 -0
- package/neural-interface/lib/skills/revision.js +80 -0
- package/neural-interface/lib/skills/roots.js +269 -0
- package/neural-interface/lib/skills/runtime-checks.js +358 -0
- package/neural-interface/lib/skills/scan-assets.js +252 -0
- package/neural-interface/lib/skills/scan-context.js +26 -0
- package/neural-interface/lib/skills/scan-shell.js +324 -0
- package/neural-interface/lib/skills/scan.js +364 -0
- package/neural-interface/lib/skills/scanners.js +54 -0
- package/neural-interface/lib/skills/service.js +530 -0
- package/neural-interface/lib/skills/telemetry.js +119 -0
- package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
- package/neural-interface/lib/synabun-version.js +1 -1
- package/neural-interface/lib/system-activity.js +1 -1
- package/neural-interface/lib/tool-lists.js +124 -0
- package/neural-interface/lib/whatsapp/brain.js +7 -3
- package/neural-interface/lib/whatsapp/bridge.js +6 -3
- package/neural-interface/lib/whatsapp/cards.js +22 -9
- package/neural-interface/lib/whatsapp/config.js +1 -1
- package/neural-interface/lib/worker-confinement.js +1268 -0
- package/neural-interface/lib/worker-guard-setting.js +56 -0
- package/neural-interface/lib/worker-mcp-channel.js +175 -0
- package/neural-interface/lib/worker-question.js +74 -0
- package/neural-interface/lib/worker-relay-ports.js +227 -0
- package/neural-interface/lib/worker-resume.js +238 -0
- package/neural-interface/lib/worker-sandbox.js +329 -0
- package/neural-interface/package-lock.json +34 -12
- package/neural-interface/package.json +3 -2
- package/neural-interface/public/index.html +3 -1
- package/neural-interface/public/index2d.html +19 -11
- package/neural-interface/public/onboarding.html +3 -3
- package/neural-interface/public/shared/account-menu.js +8 -5
- package/neural-interface/public/shared/agent-runtime-options.js +125 -31
- package/neural-interface/public/shared/agy/agy-bypass.js +47 -0
- package/neural-interface/public/shared/agy/agy-client.js +266 -0
- package/neural-interface/public/shared/agy/agy-commands.js +120 -0
- package/neural-interface/public/shared/agy/agy-copy.js +326 -0
- package/neural-interface/public/shared/agy/agy-diff.js +161 -0
- package/neural-interface/public/shared/agy/agy-events.js +469 -0
- package/neural-interface/public/shared/agy/agy-greeting.js +26 -0
- package/neural-interface/public/shared/agy/agy-options.js +232 -0
- package/neural-interface/public/shared/agy/agy-panel.js +2543 -0
- package/neural-interface/public/shared/agy/agy-render.js +392 -0
- package/neural-interface/public/shared/agy/agy-setup.js +149 -0
- package/neural-interface/public/shared/agy/agy-styles.js +604 -0
- package/neural-interface/public/shared/agy/agy-tabs-logic.js +181 -0
- package/neural-interface/public/shared/api.js +1527 -1336
- package/neural-interface/public/shared/app-frame.js +192 -0
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +36 -6
- package/neural-interface/public/shared/assistant/asst-api.js +1 -1
- package/neural-interface/public/shared/assistant/asst-ask-styles.js +270 -0
- package/neural-interface/public/shared/assistant/asst-ask-tail.js +118 -0
- package/neural-interface/public/shared/assistant/asst-ask.js +397 -0
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +105 -44
- package/neural-interface/public/shared/assistant/asst-budget.js +5 -4
- package/neural-interface/public/shared/assistant/asst-control.js +205 -26
- package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
- package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
- package/neural-interface/public/shared/assistant/asst-hosts.js +16 -7
- package/neural-interface/public/shared/assistant/asst-limit-dock.js +45 -0
- package/neural-interface/public/shared/assistant/asst-limit-wait.js +327 -0
- package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
- package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
- package/neural-interface/public/shared/assistant/asst-menu.js +7 -6
- package/neural-interface/public/shared/assistant/asst-panel.js +151 -19
- package/neural-interface/public/shared/assistant/asst-rack-styles.js +66 -49
- package/neural-interface/public/shared/assistant/asst-render.js +445 -82
- package/neural-interface/public/shared/assistant/asst-route.js +304 -53
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +9 -8
- package/neural-interface/public/shared/assistant/asst-scenes.js +56 -1
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +117 -10
- package/neural-interface/public/shared/assistant/asst-slash.js +17 -9
- package/neural-interface/public/shared/assistant/asst-state.js +87 -24
- package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
- package/neural-interface/public/shared/assistant/asst-styles.js +93 -21
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +190 -23
- package/neural-interface/public/shared/assistant/asst-usage.js +2 -1
- package/neural-interface/public/shared/automation-context.js +5 -2
- package/neural-interface/public/shared/cc-dropdown.js +89 -19
- package/neural-interface/public/shared/cdx/cdx-context-menu.js +10 -9
- package/neural-interface/public/shared/cdx/cdx-copy.js +16 -0
- package/neural-interface/public/shared/cdx/cdx-output-model.js +22 -1
- package/neural-interface/public/shared/cdx/cdx-output.js +34 -10
- package/neural-interface/public/shared/cdx/cdx-panel.js +59 -151
- package/neural-interface/public/shared/cdx/cdx-preview.js +12 -0
- package/neural-interface/public/shared/cdx/cdx-protocol.js +39 -11
- package/neural-interface/public/shared/cdx/cdx-render.js +57 -38
- package/neural-interface/public/shared/cdx/cdx-requests.js +14 -4
- package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
- package/neural-interface/public/shared/cdx/cdx-styles.js +15 -3
- package/neural-interface/public/shared/cdx/cdx-tabs.js +127 -44
- package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
- package/neural-interface/public/shared/cli-install-controller.js +218 -0
- package/neural-interface/public/shared/cli-install-view.js +11 -12
- package/neural-interface/public/shared/cli-status.js +11 -10
- package/neural-interface/public/shared/constants.js +5 -4
- package/neural-interface/public/shared/context-menu-areas.js +34 -0
- package/neural-interface/public/shared/context-menu-logic.js +243 -0
- package/neural-interface/public/shared/context-menu-model.js +367 -0
- package/neural-interface/public/shared/context-menu.js +372 -0
- package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
- package/neural-interface/public/shared/cp/cp-restore.js +162 -0
- package/neural-interface/public/shared/cp/cp-tool-cards.js +10 -3
- package/neural-interface/public/shared/crash-notice-view.js +168 -0
- package/neural-interface/public/shared/desktop-bridge.js +17 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +12 -0
- package/neural-interface/public/shared/desktop-titlebar.js +13 -4
- package/neural-interface/public/shared/desktop-update-view.js +21 -0
- package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
- package/neural-interface/public/shared/explorer/fx-api.js +4 -4
- package/neural-interface/public/shared/explorer/fx-links.js +3 -3
- package/neural-interface/public/shared/explorer/fx-logic.js +1 -1
- package/neural-interface/public/shared/explorer/fx-main.js +48 -16
- package/neural-interface/public/shared/explorer/fx-tree.js +1 -0
- package/neural-interface/public/shared/greeting/greeting-card.js +2 -2
- package/neural-interface/public/shared/greeting/greeting-view.js +1 -0
- package/neural-interface/public/shared/html-shell.js +30 -15
- package/neural-interface/public/shared/i18n.js +2 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +7 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +4 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +3 -101
- package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +2 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +1 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +2 -6
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +11 -11
- package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +0 -3
- package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +8 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +7 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-outcome-notifications.js +16 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +74 -259
- package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
- package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +95 -202
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +13 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +13 -22
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +4 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +8 -61
- package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +2 -91
- package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +16 -15
- package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +8 -21
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +1 -99
- package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +5 -35
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +17 -21
- package/neural-interface/public/shared/ocp-v2/{ocp-v2-profile-inheritance.js → ocp-v2-tools-inheritance.js} +16 -16
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +60 -50
- package/neural-interface/public/shared/page-session.js +96 -0
- package/neural-interface/public/shared/provider-icons.js +4 -2
- package/neural-interface/public/shared/registry.js +5 -3
- package/neural-interface/public/shared/retired-2d.js +3 -0
- package/neural-interface/public/shared/schedules-view.js +195 -61
- package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
- package/neural-interface/public/shared/settings/settings-data.js +3 -1
- package/neural-interface/public/shared/settings/settings-ia.js +6 -6
- package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
- package/neural-interface/public/shared/settings/settings-rules.js +2 -2
- package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +265 -0
- package/neural-interface/public/shared/settings/settings-skill-folders.js +130 -0
- package/neural-interface/public/shared/settings/settings-worker-guard.js +72 -0
- package/neural-interface/public/shared/showcase-privacy.js +6 -1
- package/neural-interface/public/shared/sidepanel-session-status.js +3 -3
- package/neural-interface/public/shared/skills/ss-args.js +96 -0
- package/neural-interface/public/shared/skills/ss-creation.js +222 -0
- package/neural-interface/public/shared/skills/ss-dialog.js +133 -0
- package/neural-interface/public/shared/skills/ss-doc.js +173 -0
- package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
- package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
- package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
- package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
- package/neural-interface/public/shared/skills/ss-evals.js +417 -0
- package/neural-interface/public/shared/skills/ss-form.js +159 -0
- package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
- package/neural-interface/public/shared/skills/ss-ids.js +32 -0
- package/neural-interface/public/shared/skills/ss-lint.js +149 -0
- package/neural-interface/public/shared/skills/ss-presets.js +117 -0
- package/neural-interface/public/shared/skills/ss-profiles.js +513 -0
- package/neural-interface/public/shared/skills/ss-resources.js +165 -0
- package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
- package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
- package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
- package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
- package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
- package/neural-interface/public/shared/skills/studio/sx-create-ai.js +237 -0
- package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
- package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
- package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
- package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
- package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
- package/neural-interface/public/shared/skills/studio/sx-dom.js +230 -0
- package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
- package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
- package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
- package/neural-interface/public/shared/skills/studio/sx-fixes-view.js +359 -0
- package/neural-interface/public/shared/skills/studio/sx-fixes.js +327 -0
- package/neural-interface/public/shared/skills/studio/sx-geometry.js +82 -0
- package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
- package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
- package/neural-interface/public/shared/skills/studio/sx-install-flow.js +282 -0
- package/neural-interface/public/shared/skills/studio/sx-install.js +313 -0
- package/neural-interface/public/shared/skills/studio/sx-library-view.js +748 -0
- package/neural-interface/public/shared/skills/studio/sx-library.js +479 -0
- package/neural-interface/public/shared/skills/studio/sx-main.js +690 -0
- package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
- package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
- package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
- package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
- package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
- package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
- package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
- package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
- package/neural-interface/public/shared/skills/studio/sx-subject.js +249 -0
- package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
- package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
- package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
- package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +426 -0
- package/neural-interface/public/shared/state.js +1 -1
- package/neural-interface/public/shared/streaming-markdown.js +58 -0
- package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
- package/neural-interface/public/shared/styles.css +1822 -1756
- package/neural-interface/public/shared/synabun-mascot.js +1115 -9
- package/neural-interface/public/shared/text-cache.js +29 -0
- package/neural-interface/public/shared/tool-list-picker.js +55 -0
- package/neural-interface/public/shared/tool-list-storage.js +24 -0
- package/neural-interface/public/shared/tool-list-view.js +112 -0
- package/neural-interface/public/shared/topright-overflow-logic.js +54 -0
- package/neural-interface/public/shared/tour/tour-actor.js +268 -0
- package/neural-interface/public/shared/tour/tour-beats.js +336 -0
- package/neural-interface/public/shared/tour/tour-engine.js +884 -0
- package/neural-interface/public/shared/tour/tour-ink.js +390 -0
- package/neural-interface/public/shared/tour/tour-stage.js +440 -0
- package/neural-interface/public/shared/tour/tour-state.js +40 -0
- package/neural-interface/public/shared/tour/tour-tips.js +99 -0
- package/neural-interface/public/shared/tour/tour.css +144 -0
- package/neural-interface/public/shared/ui-antigravity-panel.js +19 -0
- package/neural-interface/public/shared/ui-assistant.js +2 -0
- package/neural-interface/public/shared/ui-automation-studio.js +111 -140
- package/neural-interface/public/shared/ui-claude-panel.js +376 -82
- package/neural-interface/public/shared/ui-cli-banner.js +23 -167
- package/neural-interface/public/shared/ui-command-runner.js +6 -3
- package/neural-interface/public/shared/ui-context-menu.js +295 -0
- package/neural-interface/public/shared/ui-cost-widget.js +57 -59
- package/neural-interface/public/shared/ui-crash-notice.js +187 -0
- package/neural-interface/public/shared/ui-detail.js +15 -3
- package/neural-interface/public/shared/ui-file-explorer.js +48 -6
- package/neural-interface/public/shared/ui-file-links.js +2 -2
- package/neural-interface/public/shared/ui-games.js +2 -2
- package/neural-interface/public/shared/ui-image-gallery.js +50 -47
- package/neural-interface/public/shared/ui-judgments.js +1 -1
- package/neural-interface/public/shared/ui-keybinds.js +33 -2
- package/neural-interface/public/shared/ui-link.js +3 -3
- package/neural-interface/public/shared/ui-menubar.js +10 -20
- package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
- package/neural-interface/public/shared/ui-native-loop-router.js +11 -1
- package/neural-interface/public/shared/ui-navbar.js +49 -24
- package/neural-interface/public/shared/ui-notifications.js +1 -0
- package/neural-interface/public/shared/ui-panels.js +96 -65
- package/neural-interface/public/shared/ui-resume.js +9 -7
- package/neural-interface/public/shared/ui-schedules-studio.js +546 -431
- package/neural-interface/public/shared/ui-scroll-follow.js +16 -5
- package/neural-interface/public/shared/ui-sessions.js +27 -15
- package/neural-interface/public/shared/ui-settings.js +683 -526
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +9 -2
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +4 -4
- package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
- package/neural-interface/public/shared/ui-sidepanel-tray.js +48 -7
- package/neural-interface/public/shared/ui-sidepanel-windows.js +18 -13
- package/neural-interface/public/shared/ui-skills.js +33 -2830
- package/neural-interface/public/shared/ui-styleguide.js +5 -2
- package/neural-interface/public/shared/ui-sync.js +15 -5
- package/neural-interface/public/shared/ui-terminal.js +270 -190
- package/neural-interface/public/shared/ui-tool-updates.js +6 -4
- package/neural-interface/public/shared/ui-tooltip.js +81 -51
- package/neural-interface/public/shared/ui-topright-overflow.js +233 -0
- package/neural-interface/public/shared/ui-trash.js +6 -4
- package/neural-interface/public/shared/ui-tutorial-layout.js +3 -117
- package/neural-interface/public/shared/ui-tutorial-preview.js +103 -0
- package/neural-interface/public/shared/ui-tutorial-steps.js +3 -65
- package/neural-interface/public/shared/ui-tutorial.css +47 -100
- package/neural-interface/public/shared/ui-tutorial.js +285 -509
- package/neural-interface/public/shared/ui-update.js +38 -2
- package/neural-interface/public/shared/ui-whiteboard.js +312 -59
- package/neural-interface/public/shared/ui-worker-end.js +5 -1
- package/neural-interface/public/shared/ui-workspaces.js +3 -2
- package/neural-interface/public/shared/view-variant.js +66 -0
- package/neural-interface/public/shared/whatsapp/wa-view.js +3 -3
- package/neural-interface/public/shared/whiteboard-list.js +172 -0
- package/neural-interface/public/shared/worker-end.js +10 -3
- package/neural-interface/public/shared/worker-questions.js +34 -0
- package/neural-interface/public/shared/worker-restart.js +12 -0
- package/neural-interface/public/sidepanel-session.html +2 -2
- package/neural-interface/public/variant/2d/background.js +2 -1
- package/neural-interface/public/variant/2d/context-menu.js +8 -2
- package/neural-interface/public/variant/2d/graph.js +42 -20
- package/neural-interface/public/variant/2d/hulls.js +14 -9
- package/neural-interface/public/variant/2d/lasso.js +11 -7
- package/neural-interface/public/variant/2d/main.js +32 -1
- package/neural-interface/public/variant/2d/minimap.js +11 -13
- package/neural-interface/public/variant/3d/main.js +69 -6
- package/neural-interface/public/variant/3d/map-controls.js +24 -9
- package/neural-interface/public/vendor/caveat/OFL.txt +93 -0
- package/neural-interface/public/vendor/caveat/caveat-latin-400-normal.woff2 +0 -0
- package/neural-interface/public/vendor/caveat/caveat-latin-700-normal.woff2 +0 -0
- package/neural-interface/public/vendor/caveat/caveat.css +17 -0
- package/neural-interface/public/vendor/caveat/manifest.json +12 -0
- package/neural-interface/public/vendor/yaml/LICENSE +13 -0
- package/neural-interface/public/vendor/yaml/manifest.json +4 -0
- package/neural-interface/public/vendor/yaml/yaml-2.9.1.min.js +137 -0
- package/neural-interface/scripts/build-vendor.mjs +32 -0
- package/neural-interface/server.js +4553 -2855
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/neural-interface/templates/rulesets/core.md +1 -1
- package/neural-interface/templates/rulesets/legacy-hashes.json +23 -5
- package/neural-interface/templates/rulesets/manifest.json +8 -8
- package/npm-shrinkwrap.json +34 -12
- package/package.json +17 -3
- package/postinstall.js +9 -4
- package/preuninstall.js +1 -1
- package/setup.js +97 -322
- package/skills/skill-forge/SKILL.md +177 -0
- package/skills/skill-forge/evals/evals.json +54 -0
- package/skills/skill-forge/references/package.md +105 -0
- package/skills/skill-forge/references/review-and-recovery.md +63 -0
- package/skills/skill-forge/references/runtime-profiles.md +20 -0
- package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
- package/skills/synabun/SKILL.md +10 -7
- package/skills/synabun/modules/audit.md +1 -5
- package/skills/synabun/modules/changelog.md +1 -5
- package/skills/synabun/modules/idea.md +1 -1
- package/skills/synabun/modules/memorize.md +6 -9
- package/skills/synabun/modules/schedule.md +6 -6
- package/mcp-server/dist/services/profiles.d.ts +0 -120
- package/mcp-server/dist/services/profiles.d.ts.map +0 -1
- package/mcp-server/dist/services/profiles.js +0 -387
- package/mcp-server/dist/services/profiles.js.map +0 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +0 -97
- package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +0 -1
- package/mcp-server/dist/tools/leonardo-browser-tools.js +0 -228
- package/mcp-server/dist/tools/leonardo-browser-tools.js.map +0 -1
- package/mcp-server/dist/tools/leonardo.d.ts +0 -13
- package/mcp-server/dist/tools/leonardo.d.ts.map +0 -1
- package/mcp-server/dist/tools/leonardo.js +0 -21
- package/mcp-server/dist/tools/leonardo.js.map +0 -1
- package/mcp-server/dist/tools/profile.d.ts +0 -17
- package/mcp-server/dist/tools/profile.d.ts.map +0 -1
- package/mcp-server/dist/tools/profile.js +0 -114
- package/mcp-server/dist/tools/profile.js.map +0 -1
- package/mcp-server/src/services/profiles.ts +0 -428
- package/mcp-server/src/tools/leonardo-browser-tools.ts +0 -291
- package/mcp-server/src/tools/leonardo.ts +0 -30
- package/mcp-server/src/tools/profile.ts +0 -122
- package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +0 -47
- package/neural-interface/lib/assistant-brains/opencode-route-gate.js +0 -62
- package/neural-interface/lib/mcp-profile-servers.js +0 -120
- package/neural-interface/public/shared/ui-tutorial-draw.js +0 -311
- package/skills/leonardo/SKILL.md +0 -168
- package/skills/leonardo/icon.svg +0 -1
- package/skills/leonardo/modules/browser-guide.md +0 -378
- package/skills/leonardo/modules/image-prompter.md +0 -283
- package/skills/leonardo/modules/model-advisor.md +0 -100
- package/skills/leonardo/modules/prompt-library.md +0 -110
- package/skills/leonardo/modules/style-guide.md +0 -186
- package/skills/leonardo/modules/video-prompter.md +0 -317
- /package/neural-interface/templates/rulesets/{gemini.md → antigravity.md} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { toolListView } from './tool-list-view.js';
|
|
1
2
|
// SynaBun Neural Interface — what the Schedules window shows, without the page.
|
|
2
3
|
// Which schedules a view lists and in which order, how a schedule's state reads, and the cron
|
|
3
4
|
// in plain words. ui-schedules-studio.js draws it; tests import this file under Node, so it
|
|
@@ -11,49 +12,161 @@ export const OVERDUE_AFTER = 5 * MINUTE;
|
|
|
11
12
|
// "Up next" looks this far ahead.
|
|
12
13
|
export const UP_NEXT_WINDOW = DAY;
|
|
13
14
|
|
|
14
|
-
const DAY_SHORT = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
15
|
-
|
|
16
15
|
export const VIEW_SCOPES = ['upcoming', 'all', 'attention', 'paused', 'timers', 'activity'];
|
|
17
16
|
export const LIST_SCOPES = ['upcoming', 'all', 'attention', 'paused'];
|
|
18
17
|
export const SORTS = ['next', 'name', 'last'];
|
|
19
18
|
|
|
19
|
+
// ── Words ──
|
|
20
|
+
// SCHEDULES_VIEW_COPY is the English of every word this file shows: `schedules.view.*` in
|
|
21
|
+
// i18n/en.json must equal it, and every locale file holds the same keys (the test checks both).
|
|
22
|
+
// A `{ one, other }` entry is counted, as i18n's tp() counts. Without a translator (tests, Node)
|
|
23
|
+
// the English reads as written; the window installs i18n's t() and the app's locale with
|
|
24
|
+
// setSchedulesViewTranslator.
|
|
25
|
+
export const SCHEDULES_VIEW_COPY = Object.freeze({
|
|
26
|
+
everyDay: 'Every day',
|
|
27
|
+
weekdays: 'Weekdays',
|
|
28
|
+
weekends: 'Weekends',
|
|
29
|
+
dayRange: '{from}–{to}',
|
|
30
|
+
monthDays: { one: 'Day {days} of every month', other: 'Days {days} of every month' },
|
|
31
|
+
everyMinutes: { one: 'every minute', other: 'every {count} minutes' },
|
|
32
|
+
everyHoursAt: { one: 'every hour at :{minute}', other: 'every {count} hours at :{minute}' },
|
|
33
|
+
everyHourBetween: 'every hour from {from} to {to}',
|
|
34
|
+
daysAt: '{days} at {times}',
|
|
35
|
+
daysEvery: '{days}, {every}',
|
|
36
|
+
listAnd: '{list} and {last}',
|
|
37
|
+
dayShort: { sun: 'Sun', mon: 'Mon', tue: 'Tue', wed: 'Wed', thu: 'Thu', fri: 'Fri', sat: 'Sat' },
|
|
38
|
+
dayLong: { sun: 'Sunday', mon: 'Monday', tue: 'Tuesday', wed: 'Wednesday', thu: 'Thursday', fri: 'Friday', sat: 'Saturday' },
|
|
39
|
+
runNever: 'Not run yet',
|
|
40
|
+
runCompleted: 'Completed',
|
|
41
|
+
runStarted: 'Started',
|
|
42
|
+
runAutomationMissing: 'Automation missing',
|
|
43
|
+
runAutomationMissingReason: 'The automation this schedule launches no longer exists.',
|
|
44
|
+
runFailed: 'Failed',
|
|
45
|
+
runFailedReason: 'The run failed.',
|
|
46
|
+
runStopped: 'Stopped',
|
|
47
|
+
runStoppedByYou: 'Stopped by you',
|
|
48
|
+
runInterrupted: 'Interrupted',
|
|
49
|
+
notScheduled: 'Not scheduled',
|
|
50
|
+
dueNow: 'Due now',
|
|
51
|
+
overdue: 'Overdue',
|
|
52
|
+
inSeconds: 'in {n} s',
|
|
53
|
+
inMinutes: 'in {n} min',
|
|
54
|
+
inHoursMinutes: 'in {h} h {m} min',
|
|
55
|
+
inHours: 'in {h} h',
|
|
56
|
+
inDaysHours: 'in {d} d {h} h',
|
|
57
|
+
inDays: 'in {d} d',
|
|
58
|
+
justNow: 'just now',
|
|
59
|
+
minutesAgo: '{n} min ago',
|
|
60
|
+
hoursAgo: '{n} h ago',
|
|
61
|
+
yesterdayAgo: 'yesterday',
|
|
62
|
+
daysAgo: '{n} d ago',
|
|
63
|
+
today: 'Today',
|
|
64
|
+
tomorrow: 'Tomorrow',
|
|
65
|
+
yesterday: 'Yesterday',
|
|
66
|
+
dayAt: '{day} {time}',
|
|
67
|
+
tomorrowAt: 'Tomorrow {time}',
|
|
68
|
+
weekdayAt: '{day} {time}',
|
|
69
|
+
factCli: 'CLI',
|
|
70
|
+
factModel: 'Model',
|
|
71
|
+
factContext: 'Context',
|
|
72
|
+
factThinking: 'Thinking',
|
|
73
|
+
factMcp: 'Tools and MCP servers',
|
|
74
|
+
factAccount: 'OpenAI account',
|
|
75
|
+
factBrowser: 'Browser',
|
|
76
|
+
valueDefault: 'Default',
|
|
77
|
+
valueOn: 'On',
|
|
78
|
+
valueOff: 'Off',
|
|
79
|
+
context1m: '1M tokens',
|
|
80
|
+
contextExtended: 'Extended',
|
|
81
|
+
effort: { none: 'None', minimal: 'Minimal', low: 'Low', medium: 'Medium', high: 'High', xhigh: 'Xhigh', max: 'Max', ultra: 'Ultra', thinking: 'Thinking' },
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
let _translate = null;
|
|
85
|
+
let _locale = null;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The page's translator, `(key, params) => t('schedules.view.' + key, params)`, and the app's locale
|
|
89
|
+
* (a code or a function that returns one). An answer that is empty, or the key itself (i18n's word for
|
|
90
|
+
* "no such string"), falls back to the English.
|
|
91
|
+
*/
|
|
92
|
+
export function setSchedulesViewTranslator(fn, locale = null) {
|
|
93
|
+
_translate = typeof fn === 'function' ? fn : null;
|
|
94
|
+
_locale = locale;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const copyAt = (key) => key.split('.').reduce((node, part) => node?.[part], SCHEDULES_VIEW_COPY);
|
|
98
|
+
const fill = (text, params) => String(text).replace(/\{(\w+)\}/g, (whole, name) => (params?.[name] != null ? params[name] : whole));
|
|
99
|
+
|
|
100
|
+
/** A SCHEDULES_VIEW_COPY sentence in the page's language (the translator above, else the English). */
|
|
101
|
+
export function scheduleWord(key, params) {
|
|
102
|
+
if (_translate) {
|
|
103
|
+
try {
|
|
104
|
+
const text = _translate(key, params);
|
|
105
|
+
if (typeof text === 'string' && text && text !== key && text !== `schedules.view.${key}`) return text;
|
|
106
|
+
} catch { /* the English below */ }
|
|
107
|
+
}
|
|
108
|
+
const english = copyAt(key);
|
|
109
|
+
return typeof english === 'string' ? fill(english, params) : key;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** A counted sentence: `key.one` for exactly one, `key.other` otherwise (i18n's tp rule). */
|
|
113
|
+
const countWord = (key, count, params) => scheduleWord(`${key}.${count === 1 ? 'one' : 'other'}`, { count, ...params });
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The locale dates and times are written in. English keeps en-GB: the 24-hour clock and day-first dates
|
|
117
|
+
* ("Wed 22 Oct 09:00") the cron descriptions use. Any other language writes them its own way.
|
|
118
|
+
*/
|
|
119
|
+
export function scheduleDateLocale() {
|
|
120
|
+
const locale = typeof _locale === 'function' ? _locale() : _locale;
|
|
121
|
+
return !locale || /^en(-|$)/i.test(locale) ? 'en-GB' : locale;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const DAY_KEYS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
|
125
|
+
|
|
126
|
+
/** A weekday (0 = Sunday … 6 = Saturday; 7 is Sunday too, as in cron): "Mon", or "Monday" with `long`. */
|
|
127
|
+
export function weekdayName(index, { long = false } = {}) {
|
|
128
|
+
const key = DAY_KEYS[Number(index) % 7];
|
|
129
|
+
return key ? scheduleWord(`${long ? 'dayLong' : 'dayShort'}.${key}`) : '';
|
|
130
|
+
}
|
|
131
|
+
|
|
20
132
|
const pad = (n) => String(n).padStart(2, '0');
|
|
21
133
|
const time = (t) => (Number.isFinite(t) ? t : NaN);
|
|
22
134
|
const parse = (iso) => (iso ? time(Date.parse(iso)) : NaN);
|
|
23
135
|
|
|
24
|
-
/** "a", "a and b", "a, b and c". */
|
|
136
|
+
/** "a", "a and b", "a, b and c" (the last joint in the page's language). */
|
|
25
137
|
export function listJoin(items) {
|
|
26
|
-
const list = items.filter(
|
|
138
|
+
const list = items.filter(item => item || item === 0).map(String);
|
|
27
139
|
if (list.length <= 1) return list.join('');
|
|
28
|
-
return
|
|
140
|
+
return scheduleWord('listAnd', { list: list.slice(0, -1).join(', '), last: list.at(-1) });
|
|
29
141
|
}
|
|
30
142
|
|
|
143
|
+
/** The days of a cron's day-of-week field: `{ text, everyDay }`, or null when it cannot be said plainly. */
|
|
31
144
|
function dayList(field) {
|
|
32
|
-
if (field === '*' || field === '?') return '
|
|
33
|
-
if (field === '1-5') return '
|
|
34
|
-
if (field === '0,6' || field === '6,0' || field === '6,7') return '
|
|
145
|
+
if (field === '*' || field === '?') return { text: scheduleWord('everyDay'), everyDay: true };
|
|
146
|
+
if (field === '1-5') return { text: scheduleWord('weekdays') };
|
|
147
|
+
if (field === '0,6' || field === '6,0' || field === '6,7') return { text: scheduleWord('weekends') };
|
|
35
148
|
const parts = field.split(',');
|
|
36
149
|
const names = [];
|
|
37
150
|
for (const part of parts) {
|
|
38
151
|
const range = part.match(/^(\d)-(\d)$/);
|
|
39
152
|
if (range) {
|
|
40
|
-
const from =
|
|
153
|
+
const from = weekdayName(range[1]), to = weekdayName(range[2]);
|
|
41
154
|
if (!from || !to) return null;
|
|
42
|
-
names.push(
|
|
155
|
+
names.push(scheduleWord('dayRange', { from, to }));
|
|
43
156
|
} else if (/^\d$/.test(part)) {
|
|
44
|
-
names.push(
|
|
157
|
+
names.push(weekdayName(part));
|
|
45
158
|
} else {
|
|
46
159
|
return null;
|
|
47
160
|
}
|
|
48
161
|
}
|
|
49
|
-
return listJoin(names);
|
|
162
|
+
return { text: listJoin(names) };
|
|
50
163
|
}
|
|
51
164
|
|
|
52
165
|
function timesOf(minute, hour) {
|
|
53
166
|
const m = /^\d{1,2}$/.test(minute) ? +minute : null;
|
|
54
|
-
if (minute === '*' && hour === '*') return { every: '
|
|
167
|
+
if (minute === '*' && hour === '*') return { every: countWord('everyMinutes', 1) };
|
|
55
168
|
const minStep = minute.match(/^\*\/(\d+)$/);
|
|
56
|
-
if (minStep && hour === '*') return { every:
|
|
169
|
+
if (minStep && hour === '*') return { every: countWord('everyMinutes', +minStep[1]) };
|
|
57
170
|
if (m == null) {
|
|
58
171
|
// Several minutes in one hour: "at 09:00 and 09:30".
|
|
59
172
|
if (/^\d{1,2}(,\d{1,2})+$/.test(minute) && /^\d{1,2}$/.test(hour)) {
|
|
@@ -61,15 +174,18 @@ function timesOf(minute, hour) {
|
|
|
61
174
|
}
|
|
62
175
|
return null;
|
|
63
176
|
}
|
|
64
|
-
if (hour === '*') return { every:
|
|
177
|
+
if (hour === '*') return { every: countWord('everyHoursAt', 1, { minute: pad(m) }) };
|
|
65
178
|
const hourStep = hour.match(/^\*\/(\d+)$/);
|
|
66
|
-
if (hourStep) return { every:
|
|
179
|
+
if (hourStep) return { every: countWord('everyHoursAt', +hourStep[1], { minute: pad(m) }) };
|
|
67
180
|
const hourRange = hour.match(/^(\d{1,2})-(\d{1,2})$/);
|
|
68
|
-
if (hourRange) return { every:
|
|
181
|
+
if (hourRange) return { every: scheduleWord('everyHourBetween', { from: `${pad(+hourRange[1])}:${pad(m)}`, to: `${pad(+hourRange[2])}:${pad(m)}` }) };
|
|
69
182
|
if (/^\d{1,2}(,\d{1,2})*$/.test(hour)) return { at: listJoin(hour.split(',').map(h => `${pad(+h)}:${pad(m)}`)) };
|
|
70
183
|
return null;
|
|
71
184
|
}
|
|
72
185
|
|
|
186
|
+
// A sentence that starts with a phrase written for its middle ("every 15 minutes").
|
|
187
|
+
const capitalize = (text) => text.charAt(0).toLocaleUpperCase(scheduleDateLocale()) + text.slice(1);
|
|
188
|
+
|
|
73
189
|
/**
|
|
74
190
|
* A five-field cron in plain words: "Every day at 06:55, 14:55 and 20:55", "Weekdays at 09:00",
|
|
75
191
|
* "Every 15 minutes". Anything it cannot say plainly comes back as the expression itself.
|
|
@@ -84,13 +200,12 @@ export function describeCron(cron) {
|
|
|
84
200
|
if (dom === '*' || dom === '?') days = dayList(dow);
|
|
85
201
|
else if (dow === '*' && /^\d{1,2}(,\d{1,2})*$/.test(dom)) {
|
|
86
202
|
const dates = dom.split(',').map(Number);
|
|
87
|
-
days =
|
|
203
|
+
days = { text: countWord('monthDays', dates.length, { days: listJoin(dates) }) };
|
|
88
204
|
} else return expr;
|
|
89
205
|
const times = timesOf(minute, hour);
|
|
90
206
|
if (!days || !times) return expr;
|
|
91
|
-
if (times.at) return
|
|
92
|
-
|
|
93
|
-
return days === 'Every day' ? every : `${days}, ${times.every}`;
|
|
207
|
+
if (times.at) return scheduleWord('daysAt', { days: days.text, times: times.at });
|
|
208
|
+
return days.everyDay ? capitalize(times.every) : scheduleWord('daysEvery', { days: days.text, every: times.every });
|
|
94
209
|
}
|
|
95
210
|
|
|
96
211
|
/** One line of text from a run result: no newlines, no runs of spaces. */
|
|
@@ -104,17 +219,18 @@ export function oneLine(text) {
|
|
|
104
219
|
*/
|
|
105
220
|
export function lastRunState(schedule) {
|
|
106
221
|
const raw = schedule?.lastRunResult;
|
|
107
|
-
if (raw == null || raw === '') return { kind: 'never', label: '
|
|
222
|
+
if (raw == null || raw === '') return { kind: 'never', label: scheduleWord('runNever'), reason: '' };
|
|
108
223
|
const text = String(raw);
|
|
109
|
-
if (text === 'completed') return { kind: 'ok', label: '
|
|
110
|
-
if (text === 'launched' || text === 'running' || text === 'started') return { kind: 'started', label: '
|
|
111
|
-
if (text === 'template_missing') return { kind: 'failed', label: '
|
|
224
|
+
if (text === 'completed') return { kind: 'ok', label: scheduleWord('runCompleted'), reason: '' };
|
|
225
|
+
if (text === 'launched' || text === 'running' || text === 'started') return { kind: 'started', label: scheduleWord('runStarted'), reason: '' };
|
|
226
|
+
if (text === 'template_missing') return { kind: 'failed', label: scheduleWord('runAutomationMissing'), reason: scheduleWord('runAutomationMissingReason') };
|
|
227
|
+
// What follows the colon is the server's own message: it shows as it came.
|
|
112
228
|
const colon = text.indexOf(':');
|
|
113
229
|
const head = (colon >= 0 ? text.slice(0, colon) : text).trim();
|
|
114
230
|
const reason = colon >= 0 ? text.slice(colon + 1).trim() : '';
|
|
115
|
-
if (head === 'error') return { kind: 'failed', label: '
|
|
116
|
-
if (head === 'stopped') return { kind: 'stopped', label: '
|
|
117
|
-
if (head === 'interrupted') return { kind: 'interrupted', label: '
|
|
231
|
+
if (head === 'error') return { kind: 'failed', label: scheduleWord('runFailed'), reason: reason || scheduleWord('runFailedReason') };
|
|
232
|
+
if (head === 'stopped') return { kind: 'stopped', label: scheduleWord('runStopped'), reason: reason === 'user' ? scheduleWord('runStoppedByYou') : reason };
|
|
233
|
+
if (head === 'interrupted') return { kind: 'interrupted', label: scheduleWord('runInterrupted'), reason };
|
|
118
234
|
return { kind: 'other', label: head.charAt(0).toUpperCase() + head.slice(1), reason };
|
|
119
235
|
}
|
|
120
236
|
|
|
@@ -215,17 +331,17 @@ export function sortSchedules(list, sort = 'next') {
|
|
|
215
331
|
/** "in 45 s", "in 26 min", "in 3 h 5 min", "in 2 d 4 h"; "Due now"; "Overdue". */
|
|
216
332
|
export function formatCountdown(iso, now = Date.now()) {
|
|
217
333
|
const next = parse(iso);
|
|
218
|
-
if (!Number.isFinite(next)) return { text: '
|
|
334
|
+
if (!Number.isFinite(next)) return { text: scheduleWord('notScheduled'), state: 'none' };
|
|
219
335
|
const diff = next - now;
|
|
220
|
-
if (diff <= 0) return diff > -OVERDUE_AFTER ? { text: '
|
|
221
|
-
if (diff < MINUTE) return { text:
|
|
222
|
-
if (diff < HOUR) return { text:
|
|
336
|
+
if (diff <= 0) return diff > -OVERDUE_AFTER ? { text: scheduleWord('dueNow'), state: 'due' } : { text: scheduleWord('overdue'), state: 'overdue' };
|
|
337
|
+
if (diff < MINUTE) return { text: scheduleWord('inSeconds', { n: Math.ceil(diff / 1000) }), state: 'soon' };
|
|
338
|
+
if (diff < HOUR) return { text: scheduleWord('inMinutes', { n: Math.floor(diff / MINUTE) }), state: diff < 15 * MINUTE ? 'soon' : 'future' };
|
|
223
339
|
if (diff < DAY) {
|
|
224
340
|
const h = Math.floor(diff / HOUR), m = Math.floor((diff % HOUR) / MINUTE);
|
|
225
|
-
return { text: m ?
|
|
341
|
+
return { text: m ? scheduleWord('inHoursMinutes', { h, m }) : scheduleWord('inHours', { h }), state: 'future' };
|
|
226
342
|
}
|
|
227
343
|
const d = Math.floor(diff / DAY), h = Math.floor((diff % DAY) / HOUR);
|
|
228
|
-
return { text: h ?
|
|
344
|
+
return { text: h ? scheduleWord('inDaysHours', { d, h }) : scheduleWord('inDays', { d }), state: 'future' };
|
|
229
345
|
}
|
|
230
346
|
|
|
231
347
|
/** "just now", "5 min ago", "2 h ago", "yesterday", "3 d ago". */
|
|
@@ -233,59 +349,77 @@ export function formatAgo(iso, now = Date.now()) {
|
|
|
233
349
|
const then = parse(iso);
|
|
234
350
|
if (!Number.isFinite(then)) return '';
|
|
235
351
|
const diff = Math.max(0, now - then);
|
|
236
|
-
if (diff < MINUTE) return '
|
|
237
|
-
if (diff < HOUR) return
|
|
238
|
-
if (diff < DAY) return
|
|
352
|
+
if (diff < MINUTE) return scheduleWord('justNow');
|
|
353
|
+
if (diff < HOUR) return scheduleWord('minutesAgo', { n: Math.floor(diff / MINUTE) });
|
|
354
|
+
if (diff < DAY) return scheduleWord('hoursAgo', { n: Math.floor(diff / HOUR) });
|
|
239
355
|
const days = Math.floor(diff / DAY);
|
|
240
|
-
return days === 1 ? '
|
|
356
|
+
return days === 1 ? scheduleWord('yesterdayAgo') : scheduleWord('daysAgo', { n: days });
|
|
241
357
|
}
|
|
242
358
|
|
|
243
359
|
const sameDay = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
244
|
-
// The window's words are English, so are its dates: "Wed 22 Oct", never half in another language.
|
|
245
|
-
const LOCALE = 'en-GB';
|
|
246
360
|
|
|
247
361
|
/** "Today", "Tomorrow", "Yesterday" or the weekday and date, for a heading or a time. */
|
|
248
|
-
export function dayLabel(iso, now = Date.now(), locale =
|
|
362
|
+
export function dayLabel(iso, now = Date.now(), locale = scheduleDateLocale()) {
|
|
249
363
|
const then = new Date(parse(iso));
|
|
250
364
|
if (Number.isNaN(then.getTime())) return '';
|
|
251
365
|
const today = new Date(now);
|
|
252
|
-
if (sameDay(then, today)) return '
|
|
253
|
-
if (sameDay(then, new Date(now + DAY))) return '
|
|
254
|
-
if (sameDay(then, new Date(now - DAY))) return '
|
|
366
|
+
if (sameDay(then, today)) return scheduleWord('today');
|
|
367
|
+
if (sameDay(then, new Date(now + DAY))) return scheduleWord('tomorrow');
|
|
368
|
+
if (sameDay(then, new Date(now - DAY))) return scheduleWord('yesterday');
|
|
255
369
|
return then.toLocaleDateString(locale, { weekday: 'short', day: 'numeric', month: 'short' });
|
|
256
370
|
}
|
|
257
371
|
|
|
258
372
|
/** 24-hour clock, as the cron descriptions are: "14:55". */
|
|
259
|
-
export function clockTime(iso, locale =
|
|
373
|
+
export function clockTime(iso, locale = scheduleDateLocale()) {
|
|
260
374
|
const then = new Date(parse(iso));
|
|
261
375
|
if (Number.isNaN(then.getTime())) return '';
|
|
262
376
|
return then.toLocaleTimeString(locale, { hour: '2-digit', minute: '2-digit', hourCycle: 'h23' });
|
|
263
377
|
}
|
|
264
378
|
|
|
265
379
|
/** "Today 14:55", "Tomorrow 09:00", "Wed 22 Oct 09:00". */
|
|
266
|
-
export function whenLabel(iso, now = Date.now(), locale =
|
|
380
|
+
export function whenLabel(iso, now = Date.now(), locale = scheduleDateLocale()) {
|
|
267
381
|
const day = dayLabel(iso, now, locale);
|
|
268
382
|
const clock = clockTime(iso, locale);
|
|
269
|
-
return day && clock ?
|
|
383
|
+
return day && clock ? scheduleWord('dayAt', { day, time: clock }) : '';
|
|
270
384
|
}
|
|
271
385
|
|
|
272
386
|
/** A run time in the fewest words: "14:55" today, "Tomorrow 09:00", "Wed 09:00" this week, then "22 Oct". */
|
|
273
|
-
export function shortWhen(iso, now = Date.now(), locale =
|
|
387
|
+
export function shortWhen(iso, now = Date.now(), locale = scheduleDateLocale()) {
|
|
274
388
|
const at = parse(iso);
|
|
275
389
|
if (!Number.isFinite(at)) return '';
|
|
276
390
|
const then = new Date(at);
|
|
277
391
|
const clock = clockTime(iso, locale);
|
|
278
392
|
if (sameDay(then, new Date(now))) return clock;
|
|
279
|
-
if (sameDay(then, new Date(now + DAY))) return
|
|
280
|
-
if (at > now && at - now < 6 * DAY) return
|
|
393
|
+
if (sameDay(then, new Date(now + DAY))) return scheduleWord('tomorrowAt', { time: clock });
|
|
394
|
+
if (at > now && at - now < 6 * DAY) return scheduleWord('weekdayAt', { day: then.toLocaleDateString(locale, { weekday: 'short' }), time: clock });
|
|
281
395
|
return then.toLocaleDateString(locale, { day: 'numeric', month: 'short' });
|
|
282
396
|
}
|
|
283
397
|
|
|
398
|
+
/** A date and time in full, for a tooltip: "22/10/2026, 14:55:03" in English, the locale's own way otherwise. */
|
|
399
|
+
export function fullDateTime(iso, locale = scheduleDateLocale()) {
|
|
400
|
+
const then = new Date(parse(iso));
|
|
401
|
+
return Number.isNaN(then.getTime()) ? '' : then.toLocaleString(locale);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const capitalized = (value) => String(value).charAt(0).toUpperCase() + String(value).slice(1);
|
|
405
|
+
|
|
406
|
+
/** A context choice in words: "1M tokens", "Extended"; one this file does not know reads as its id. */
|
|
407
|
+
export function contextWord(value) {
|
|
408
|
+
if (value === '1m') return scheduleWord('context1m');
|
|
409
|
+
if (value === 'extended') return scheduleWord('contextExtended');
|
|
410
|
+
return capitalized(value);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/** A thinking level in words: "Low", "High"; one this file does not know reads as its id. */
|
|
414
|
+
export function effortWord(value) {
|
|
415
|
+
return Object.prototype.hasOwnProperty.call(SCHEDULES_VIEW_COPY.effort, value) ? scheduleWord(`effort.${value}`) : capitalized(value);
|
|
416
|
+
}
|
|
417
|
+
|
|
284
418
|
/**
|
|
285
419
|
* The launch settings a run will use and where each comes from: the schedule's own value wins,
|
|
286
|
-
* then its group's, then the automation's. `labels` names CLIs (`profiles`) and
|
|
420
|
+
* then its group's, then the automation's. `labels` names CLIs (`profiles`) and tool groups.
|
|
287
421
|
*/
|
|
288
|
-
export function launchFacts(schedule, { group = null, template = null, profiles = [],
|
|
422
|
+
export function launchFacts(schedule, { group = null, template = null, profiles = [], toolCatalog = null, translate } = {}) {
|
|
289
423
|
const pick = (field) => {
|
|
290
424
|
for (const [source, owner] of [['schedule', schedule], ['group', group], ['automation', template]]) {
|
|
291
425
|
const value = owner?.[field];
|
|
@@ -296,23 +430,23 @@ export function launchFacts(schedule, { group = null, template = null, profiles
|
|
|
296
430
|
const facts = [];
|
|
297
431
|
const profile = pick('profile');
|
|
298
432
|
const profileId = profile.value || 'claude-code';
|
|
299
|
-
facts.push({ key: 'profile', label: '
|
|
433
|
+
facts.push({ key: 'profile', label: scheduleWord('factCli'), value: profiles.find(p => p.id === profileId)?.label || profileId, source: profile.value ? profile.source : 'default' });
|
|
300
434
|
const model = pick('model');
|
|
301
|
-
facts.push({ key: 'model', label: '
|
|
435
|
+
facts.push({ key: 'model', label: scheduleWord('factModel'), value: model.value || scheduleWord('valueDefault'), source: model.source, mono: !!model.value });
|
|
302
436
|
const context = pick('contextMode');
|
|
303
|
-
if (context.value && context.value !== 'default') facts.push({ key: 'contextMode', label: '
|
|
437
|
+
if (context.value && context.value !== 'default') facts.push({ key: 'contextMode', label: scheduleWord('factContext'), value: contextWord(context.value), source: context.source });
|
|
304
438
|
const effort = pick('effort');
|
|
305
|
-
if (effort.value && effort.value !== 'off') facts.push({ key: 'effort', label: '
|
|
306
|
-
const mcp = pick('
|
|
439
|
+
if (effort.value && effort.value !== 'off') facts.push({ key: 'effort', label: scheduleWord('factThinking'), value: effortWord(effort.value), source: effort.source });
|
|
440
|
+
const mcp = pick('tools');
|
|
307
441
|
if (mcp.value) {
|
|
308
|
-
const value =
|
|
309
|
-
facts.push({ key: '
|
|
442
|
+
const value = toolCatalog ? toolListView(toolCatalog, mcp.value, { translate }).summary : mcp.value.filter(id => !id.startsWith('mcp:')).join(', ') || scheduleWord('valueDefault');
|
|
443
|
+
facts.push({ key: 'tools', label: scheduleWord('factMcp'), value, source: mcp.source });
|
|
310
444
|
}
|
|
311
445
|
if (profileId === 'codex') {
|
|
312
446
|
const account = pick('codexAccountId');
|
|
313
|
-
if (account.value) facts.push({ key: 'codexAccountId', label: '
|
|
447
|
+
if (account.value) facts.push({ key: 'codexAccountId', label: scheduleWord('factAccount'), value: account.value, source: account.source });
|
|
314
448
|
}
|
|
315
449
|
const browser = pick('usesBrowser');
|
|
316
|
-
facts.push({ key: 'usesBrowser', label: '
|
|
450
|
+
facts.push({ key: 'usesBrowser', label: scheduleWord('factBrowser'), value: scheduleWord(browser.value === true ? 'valueOn' : 'valueOff'), source: browser.source });
|
|
317
451
|
return facts;
|
|
318
452
|
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SETTINGS — SynaBun's Claude Code hooks, in words
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// What `GET /api/claude-code/integrations` says in `claudeHooks` (lib/claude-hooks-status.js) about Settings →
|
|
6
|
+
// Automations → Automation behavior → SynaBun hooks in Claude Code: whether a Claude Code session the owner starts
|
|
7
|
+
// by themselves runs SynaBun's hooks, what stands in the way, and whether the switch can change it. Pure: no DOM
|
|
8
|
+
// and no import, so node runs it (tests/settings-claude-hooks-view.test.mjs).
|
|
9
|
+
//
|
|
10
|
+
// readClaudeHooksResponse({ status, body, error }) what the server answered → a reading
|
|
11
|
+
// describeClaudeHooks(reading, { tx }) the row as ui-settings.js draws it
|
|
12
|
+
// describeClaudeHooksSaveFailure(input, { tx }) the sentence for a change that could not be made
|
|
13
|
+
//
|
|
14
|
+
// `tx(key, params)` is the caller's translate function over the settings.redesign.* strings (the kit's `tx`).
|
|
15
|
+
// The row never shows "off" for what it could not read: a refusal (SynaBun's automation browser), a server started
|
|
16
|
+
// before this, an unreadable settings file each say what they are, with the switch disabled.
|
|
17
|
+
|
|
18
|
+
const K = 'settings.redesign.hooks.claudeHooks';
|
|
19
|
+
|
|
20
|
+
/** The rows of the "Hooks for standalone Claude Code" list: one per moment, the guards over two events. */
|
|
21
|
+
export const CLAUDE_HOOK_ROWS = Object.freeze([
|
|
22
|
+
Object.freeze({ key: 'SessionStart', events: ['SessionStart'] }),
|
|
23
|
+
Object.freeze({ key: 'UserPromptSubmit', events: ['UserPromptSubmit'] }),
|
|
24
|
+
Object.freeze({ key: 'PreCompact', events: ['PreCompact'] }),
|
|
25
|
+
Object.freeze({ key: 'Stop', events: ['Stop'] }),
|
|
26
|
+
Object.freeze({ key: 'PreToolUse', events: ['PreToolUse', 'PostToolBatch'] }),
|
|
27
|
+
Object.freeze({ key: 'PostToolUse', events: ['PostToolUse'] }),
|
|
28
|
+
Object.freeze({ key: 'SubagentStart', events: ['SubagentStart'] }),
|
|
29
|
+
Object.freeze({ key: 'SubagentStop', events: ['SubagentStop'] }),
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
/** The refusals of SynaBun's owner-only routes for a browser that is not the owner's (lib/owner-authority.js). */
|
|
33
|
+
const REFUSED_CODES = new Set(['WORKER_BROWSER', 'PEER_REFUSED']);
|
|
34
|
+
|
|
35
|
+
const clean = (value, max = 240) => {
|
|
36
|
+
const text = String(value ?? '').replace(/\s+/g, ' ').trim();
|
|
37
|
+
return text.length > max ? `${text.slice(0, max - 1)}…` : text;
|
|
38
|
+
};
|
|
39
|
+
const names = (list) => [...new Set((list || []).map((p) => clean(p.label || String(p.path || '').split(/[\\/]/).filter(Boolean).pop() || p.path, 60)))].join(', ');
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* What the server answered.
|
|
43
|
+
*
|
|
44
|
+
* ready `hooks` is the server's claudeHooks
|
|
45
|
+
* old-server an answer without claudeHooks: the running server was started before it (public/ is served live,
|
|
46
|
+
* lib/ only after a restart), and its own reading of the settings may be wrong
|
|
47
|
+
* refused 403 WORKER_BROWSER / PEER_REFUSED: SynaBun's automation browser, never the owner's own window
|
|
48
|
+
* forbidden 403 otherwise (a guest)
|
|
49
|
+
* unreadable anything else (no answer, an error, a body that is not the payload)
|
|
50
|
+
*/
|
|
51
|
+
export function readClaudeHooksResponse({ status = 0, body = null, error = null } = {}) {
|
|
52
|
+
const code = Number(status) || 0;
|
|
53
|
+
if (code >= 200 && code < 300 && body && typeof body === 'object' && body.ok === true) {
|
|
54
|
+
const hooks = body.claudeHooks;
|
|
55
|
+
if (hooks && typeof hooks === 'object' && Number(hooks.version) >= 1 && typeof hooks.state === 'string') return { state: 'ready', hooks, reason: null };
|
|
56
|
+
return { state: 'old-server', hooks: null, reason: null };
|
|
57
|
+
}
|
|
58
|
+
if (code === 403) {
|
|
59
|
+
const refusal = String(body?.code || '');
|
|
60
|
+
return { state: REFUSED_CODES.has(refusal) ? 'refused' : 'forbidden', hooks: null, reason: clean(body?.error) || null, code: refusal || null };
|
|
61
|
+
}
|
|
62
|
+
return { state: 'unreadable', hooks: null, reason: clean(error || body?.error || (code ? `HTTP ${code}` : '')) || null };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Which list rows are on: every event of the row has all of SynaBun's handlers. */
|
|
66
|
+
export function claudeHookRowsOn(events) {
|
|
67
|
+
return Object.fromEntries(CLAUDE_HOOK_ROWS.map((row) => [row.key, row.events.every((event) => events?.[event] === true)]));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The row: { state, ready, disabled, on, notes: [{ text, tone }], note: { text, tone } | null, repair, applies,
|
|
72
|
+
* rows: { [rowKey]: boolean } | null (the list below; null when nothing could be read), onRows, totalRows }.
|
|
73
|
+
* `note` says why nothing below can be trusted or changed; `notes` describe what is installed.
|
|
74
|
+
*/
|
|
75
|
+
export function describeClaudeHooks(reading, { tx }) {
|
|
76
|
+
const r = reading || readClaudeHooksResponse({ status: 0 });
|
|
77
|
+
const view = { state: r.state, ready: false, disabled: true, on: false, notes: [], note: null, repair: false, applies: tx(`${K}.applies`), rows: null, onRows: 0, totalRows: CLAUDE_HOOK_ROWS.length };
|
|
78
|
+
if (r.state === 'old-server') { view.note = { text: tx(`${K}.restart`), tone: 'warn' }; return view; }
|
|
79
|
+
if (r.state === 'refused') { view.note = { text: tx(`${K}.refused`), tone: 'warn' }; return view; }
|
|
80
|
+
if (r.state === 'forbidden') { view.note = { text: tx(`${K}.forbidden`), tone: 'warn' }; return view; }
|
|
81
|
+
if (r.state !== 'ready') {
|
|
82
|
+
view.note = { text: r.reason ? tx(`${K}.unreadable`, { reason: r.reason }) : tx(`${K}.unreadableNoReason`), tone: 'warn' };
|
|
83
|
+
return view;
|
|
84
|
+
}
|
|
85
|
+
const h = r.hooks;
|
|
86
|
+
if (h.state === 'error') {
|
|
87
|
+
view.note = { text: tx(`${K}.settingsUnreadable`, { path: h.settingsPath || '~/.claude/settings.json', reason: clean(h.error) || '?' }), tone: 'warn' };
|
|
88
|
+
return view;
|
|
89
|
+
}
|
|
90
|
+
const path = h.settingsPath || '~/.claude/settings.json';
|
|
91
|
+
const rows = claudeHookRowsOn(h.events);
|
|
92
|
+
const onRows = Object.values(rows).filter(Boolean).length;
|
|
93
|
+
const installed = h.state === 'on' || h.state === 'partial';
|
|
94
|
+
const managed = h.blockedBy?.scope === 'managed';
|
|
95
|
+
view.ready = true;
|
|
96
|
+
view.rows = rows;
|
|
97
|
+
view.onRows = onRows;
|
|
98
|
+
// On means "a session the owner starts runs them": installed and not switched off by Claude Code itself.
|
|
99
|
+
view.on = installed && !h.blockedBy;
|
|
100
|
+
// The organization's managed settings, and a packaged app started from a temporary place, cannot be switched here.
|
|
101
|
+
view.disabled = managed || !!h.installBlocker;
|
|
102
|
+
|
|
103
|
+
if (h.installBlocker) view.notes.push({ text: clean(h.installBlocker, 400), tone: 'warn' });
|
|
104
|
+
if (managed) view.notes.push({ text: tx(`${K}.blocked.managed.${h.blockedBy.setting === 'allowManagedHooksOnly' ? 'managedOnly' : 'disableAll'}`, { path: h.blockedBy.path }), tone: 'warn' });
|
|
105
|
+
else if (h.blockedBy) view.notes.push({ text: tx(`${K}.blocked.user`, { path: h.blockedBy.path || path }), tone: 'warn' });
|
|
106
|
+
else if (h.state === 'on') view.notes.push({ text: tx(`${K}.on`, { path }), tone: 'info' });
|
|
107
|
+
else if (h.state === 'partial') view.notes.push({ text: tx(`${K}.partial`, { on: onRows, total: CLAUDE_HOOK_ROWS.length }), tone: 'info' });
|
|
108
|
+
else view.notes.push({ text: tx(`${K}.off`), tone: 'info' });
|
|
109
|
+
|
|
110
|
+
if (h.needsRepair && !managed) {
|
|
111
|
+
view.repair = !h.installBlocker;
|
|
112
|
+
if (h.current < h.installed) view.notes.push({ text: tx(`${K}.repair.stale`, { count: h.installed - h.current }), tone: 'warn' });
|
|
113
|
+
if (h.duplicates > 0) view.notes.push({ text: tx(`${K}.repair.duplicates`, { count: h.duplicates }), tone: 'warn' });
|
|
114
|
+
const different = (h.projects || []).filter((p) => p.issue === 'different');
|
|
115
|
+
if (different.length) view.notes.push({ text: tx(`${K}.repair.projects`, { names: names(different) }), tone: 'warn' });
|
|
116
|
+
if (h.nodeMissing) view.notes.push({ text: tx(`${K}.repair.node`), tone: 'warn' });
|
|
117
|
+
}
|
|
118
|
+
const off = (h.projects || []).filter((p) => p.issue === 'disableAllHooks');
|
|
119
|
+
if (off.length) view.notes.push({ text: tx(`${K}.projectsOff`, { names: names(off) }), tone: 'warn' });
|
|
120
|
+
const stillOn = (h.projects || []).filter((p) => p.issue === 'project-only');
|
|
121
|
+
if (stillOn.length) view.notes.push({ text: tx(`${K}.projectsStillOn`, { names: names(stillOn) }), tone: 'warn' });
|
|
122
|
+
return view;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The sentence for a change that could not be made: { action: 'on' | 'off' | 'repair', status, body, error }.
|
|
127
|
+
* An answer without claudeHooks after a change that worked is a server started before this (said as such).
|
|
128
|
+
*/
|
|
129
|
+
export function describeClaudeHooksSaveFailure({ action = 'on', status = 0, body = null, error = null } = {}, { tx }) {
|
|
130
|
+
const verb = ['on', 'off', 'repair'].includes(action) ? action : 'on';
|
|
131
|
+
const code = Number(status) || 0;
|
|
132
|
+
if (!code) return tx(`${K}.save.noAnswer.${verb}`);
|
|
133
|
+
if (code === 403 && REFUSED_CODES.has(String(body?.code || ''))) return tx(`${K}.save.refused.${verb}`);
|
|
134
|
+
return tx(`${K}.save.failed.${verb}`, { reason: clean(body?.error || error) || `HTTP ${code}` });
|
|
135
|
+
}
|
|
@@ -21,7 +21,8 @@ const okBody = (body) => !!body && typeof body === 'object' && body.ok !== false
|
|
|
21
21
|
export const SETTINGS_READS = Object.freeze({
|
|
22
22
|
settings: { url: '/api/settings', accept: okBody },
|
|
23
23
|
connections: { url: '/api/connections', accept: (body) => Array.isArray(body?.connections) },
|
|
24
|
-
|
|
24
|
+
// Raw: the hooks' row tells a refusal, an old server and an unreadable file apart (settings-claude-hooks.js).
|
|
25
|
+
integrations: { url: '/api/claude-code/integrations', raw: true },
|
|
25
26
|
skills: { url: '/api/claude-code/skills', accept: (body) => body?.ok === true },
|
|
26
27
|
// The tunnel changes by itself (starting, stopping from the Share menu): asked again after a few seconds.
|
|
27
28
|
tunnel: { url: '/api/tunnel/status', accept: (body) => body?.ok === true, ttlMs: 10_000 },
|
|
@@ -38,6 +39,7 @@ export const SETTINGS_READS = Object.freeze({
|
|
|
38
39
|
youtube: { url: '/api/youtube/config', accept: (body) => body?.ok === true },
|
|
39
40
|
typesafe: { url: '/api/typesafe/config', accept: (body) => body?.ok === true },
|
|
40
41
|
userContext: { url: '/api/assistant/user-context', raw: true },
|
|
42
|
+
workerGuard: { url: '/api/assistant/worker-guard', raw: true },
|
|
41
43
|
});
|
|
42
44
|
|
|
43
45
|
const caches = Object.fromEntries(Object.entries(SETTINGS_READS).map(([name, spec]) => [name, createDataCache(`settings:${name}`, {
|
|
@@ -103,7 +103,7 @@ export const SETTINGS_PAGES = [
|
|
|
103
103
|
id: 'connected-tools', key: 'connected_tools', group: 'tools', icon: 'mcp',
|
|
104
104
|
panes: [{ id: 'mcp' }, { id: 'morelogin', titleKey: k('pane.morelogin') }],
|
|
105
105
|
sections: [
|
|
106
|
-
{ id: 'stg-sec-
|
|
106
|
+
{ id: 'stg-sec-default-tools', key: 'default_tools', state: 'open' },
|
|
107
107
|
{ id: 'stg-sec-added-servers', key: 'added_servers', state: 'open' },
|
|
108
108
|
{ id: 'stg-sec-ml-connection', key: 'morelogin_connection', state: 'open' },
|
|
109
109
|
{ id: 'stg-sec-ml-profiles', key: 'morelogin_profiles', state: 'open' },
|
|
@@ -253,7 +253,7 @@ export const SETTINGS_CONTROLS = {
|
|
|
253
253
|
'stg-sec-manual-setup': 'SET029 SET030 SET031 SET032',
|
|
254
254
|
'cc-cli-paths': 'CLI001 CLI002 CLI007 CLI003 CLI004 CLI005 CLI006',
|
|
255
255
|
'stg-sec-opencode-service': 'OCP001 OCP002 OCP003 OCP004 OCP005 OCP021 OCP022 OCP019',
|
|
256
|
-
'stg-sec-opencode-behavior': 'OCP013
|
|
256
|
+
'stg-sec-opencode-behavior': 'OCP013 OCP015 OCP016',
|
|
257
257
|
'stg-sec-opencode-tools': 'OCP017',
|
|
258
258
|
'stg-sec-opencode-history': 'OCP023 OCP018',
|
|
259
259
|
'stg-sec-database': 'GEN015 GEN001 GEN002 GEN003 GEN016 GEN004 GEN005 GEN006 GEN017 DB003',
|
|
@@ -268,18 +268,18 @@ export const SETTINGS_CONTROLS = {
|
|
|
268
268
|
'bcg-identity': 'BRW021 BRW022 BRW023 BRW024 BRW025',
|
|
269
269
|
'bcg-viewport': 'BRW026 BRW027 BRW028 BRW029 BRW030 BRW031 BRW032',
|
|
270
270
|
'bcg-advanced': 'BRW033 BRW034 BRW035 BRW036 BRW037 BRW038 BRW039 BRW040 BRW041 BRW042 BRW043 BRW044 BRW045 BRW046 BRW047 BRW048 BRW049 BRW050 BRW051 BRW052 BRW053 BRW054 BRW055 BRW056 BRW057 BRW058 BRW059 BRW060 BRW061 BRW062 BRW063 BRW064 BRW065 BRW066 BRW067 BRW068 BRW069 BRW070 BRW071 BRW072 BRW073 BRW074 BRW075 BRW076 BRW077 BRW078 BRW079 BRW080',
|
|
271
|
-
'stg-sec-
|
|
271
|
+
'stg-sec-default-tools': 'MCP022 MCP024 MCP005 MCP004',
|
|
272
272
|
'stg-sec-added-servers': 'MCP026 MCP006 MCP007 MCP008 MCP009 MCP010 MCP011 MCP012 MCP013 MCP014 MCP015 MCP027 MCP016 MCP017 MCP018 MCP019 MCP020 MCP021',
|
|
273
273
|
'stg-sec-ml-connection': 'ML015 ML001 ML002 ML003',
|
|
274
274
|
'stg-sec-ml-profiles': 'ML004 ML005 ML006 ML016 ML017 ML018 ML019',
|
|
275
275
|
'stg-sec-ml-credentials': 'ML007 ML008 ML009 ML010 ML011',
|
|
276
276
|
'stg-sec-ml-server': 'ML012 ML013 ML014',
|
|
277
277
|
'stg-sec-skills': 'SKL004 SKL001',
|
|
278
|
-
'stg-sec-tool-permissions': 'PER012 PER001 PER002 PER003 PER004 PER005 PER006
|
|
278
|
+
'stg-sec-tool-permissions': 'PER012 PER001 PER002 PER003 PER004 PER005 PER006 PER008 PER009 PER010 PER011',
|
|
279
279
|
'stg-sec-editor-editing': 'EDT014 EDT015 EDT016 EDT017 EDT018 EDT019 EDT020 EDT021 EDT022 EDT023',
|
|
280
280
|
'stg-sec-editor-ai': 'EDT001 EDT002 EDT003 EDT004 EDT005 EDT006 EDT007 EDT008 EDT009 EDT010 EDT011 EDT012 EDT013',
|
|
281
281
|
'stg-sec-greetings': 'AUT058 AUT059 AUT060',
|
|
282
|
-
'stg-sec-automation-behavior': 'AUT053 AUT054 AUT055 AUT056 AUT057 AUT046 AUT036 AUT037 AUT038 AUT039 AUT040 AUT041 AUT028 AUT029 AUT030 AUT031 AUT032 AUT033 AUT034 AUT035',
|
|
282
|
+
'stg-sec-automation-behavior': 'AUT053 AUT054 AUT055 AUT061 AUT062 AUT056 AUT057 AUT046 AUT036 AUT037 AUT038 AUT039 AUT040 AUT041 AUT028 AUT029 AUT030 AUT031 AUT032 AUT033 AUT034 AUT035',
|
|
283
283
|
'stg-sec-online-access': 'AUT048 AUT042 AUT043 AUT044 AUT045 AUT049 AUT050 AUT051 AUT052',
|
|
284
284
|
'stg-sec-social': 'SOC003 SOC001 SOC002',
|
|
285
285
|
'stg-sec-youtube': 'YT017 YT001 YT002 YT003 YT004 YT005 YT006 YT007 YT008 YT009 YT010 YT011 YT012 YT013 YT014 YT015 YT016 YT018',
|
|
@@ -349,7 +349,7 @@ export const SETTINGS_TAB_ALIASES = {
|
|
|
349
349
|
judgments: { page: 'ai-decisions', section: 'jv-sec-connection' },
|
|
350
350
|
projects: { page: 'projects', section: 'stg-sec-workspaces' },
|
|
351
351
|
browser: { page: 'browser', section: 'setup-browser' },
|
|
352
|
-
mcp: { page: 'connected-tools', section: 'stg-sec-
|
|
352
|
+
mcp: { page: 'connected-tools', section: 'stg-sec-default-tools' },
|
|
353
353
|
morelogin: { page: 'connected-tools', section: 'stg-sec-ml-connection' },
|
|
354
354
|
skills: { page: 'tool-access', section: 'stg-sec-skills' },
|
|
355
355
|
permissions: { page: 'tool-access', section: 'stg-sec-tool-permissions' },
|