synabun 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +121 -0
- package/README.md +1 -1
- package/docs/whatsapp.md +11 -11
- package/lib/client-config-repair.js +13 -9
- package/lib/external-tools.js +6 -5
- package/lib/update-snapshot.js +77 -3
- package/lib/virustotal.mjs +12 -1
- package/mcp-server/dist/index.js +1 -1
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -1
- package/mcp-server/dist/services/budget-judgments.js +5 -3
- package/mcp-server/dist/services/budget-judgments.js.map +1 -1
- package/mcp-server/dist/services/identity.d.ts +2 -2
- package/mcp-server/dist/services/identity.js +2 -2
- package/mcp-server/dist/services/memory-sessions.d.ts +1 -1
- package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -1
- package/mcp-server/dist/services/memory-sessions.js +28 -2
- package/mcp-server/dist/services/memory-sessions.js.map +1 -1
- package/mcp-server/dist/services/neural-interface.d.ts +2 -1
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
- package/mcp-server/dist/services/server-instructions.js +2 -1
- package/mcp-server/dist/services/server-instructions.js.map +1 -1
- package/mcp-server/dist/services/tool-catalog.js +1 -1
- package/mcp-server/dist/services/tool-catalog.js.map +1 -1
- package/mcp-server/dist/services/tool-list.d.ts +1 -1
- package/mcp-server/dist/services/tool-list.d.ts.map +1 -1
- package/mcp-server/dist/services/tool-runtime.d.ts +2 -2
- package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -1
- package/mcp-server/dist/services/tool-runtime.js +1 -1
- package/mcp-server/dist/services/tool-runtime.js.map +1 -1
- package/mcp-server/dist/services/typesafe-config.js +1 -1
- package/mcp-server/dist/services/typesafe-config.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +8 -8
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +10 -9
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/choice.d.ts +6 -0
- package/mcp-server/dist/tools/choice.d.ts.map +1 -1
- package/mcp-server/dist/tools/choice.js +18 -13
- package/mcp-server/dist/tools/choice.js.map +1 -1
- package/mcp-server/dist/tools/git-tools.js +2 -2
- package/mcp-server/dist/tools/git-tools.js.map +1 -1
- package/mcp-server/dist/tools/morelogin.d.ts.map +1 -1
- package/mcp-server/dist/tools/morelogin.js +9 -6
- package/mcp-server/dist/tools/morelogin.js.map +1 -1
- package/mcp-server/dist/tools/skill-tools.d.ts +8 -8
- package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -1
- package/mcp-server/dist/tools/skill-tools.js +11 -8
- package/mcp-server/dist/tools/skill-tools.js.map +1 -1
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/src/index.ts +1 -1
- package/mcp-server/src/services/budget-judgments.ts +5 -3
- package/mcp-server/src/services/identity.ts +2 -2
- package/mcp-server/src/services/memory-sessions.ts +24 -3
- package/mcp-server/src/services/neural-interface.ts +2 -1
- package/mcp-server/src/services/server-instructions.ts +2 -1
- package/mcp-server/src/services/tool-catalog.ts +1 -1
- package/mcp-server/src/services/tool-list.ts +1 -1
- package/mcp-server/src/services/tool-runtime.ts +2 -2
- package/mcp-server/src/services/typesafe-config.ts +1 -1
- package/mcp-server/src/tools/agents.ts +10 -9
- package/mcp-server/src/tools/choice.ts +17 -12
- package/mcp-server/src/tools/git-tools.ts +2 -2
- package/mcp-server/src/tools/morelogin.ts +6 -4
- package/mcp-server/src/tools/skill-tools.ts +11 -8
- package/neural-interface/i18n/en.json +501 -39
- package/neural-interface/i18n/pt-BR.json +501 -39
- package/neural-interface/lib/agent-sandbox-elevation.js +6 -0
- package/neural-interface/lib/antigravity/acp-client-host.js +554 -0
- package/neural-interface/lib/antigravity/acp-connection.js +299 -0
- package/neural-interface/lib/antigravity/bypass.js +100 -0
- package/neural-interface/lib/antigravity/catalog.js +273 -0
- package/neural-interface/lib/antigravity/home.js +260 -0
- package/neural-interface/lib/antigravity/migrate-gemini.js +139 -0
- package/neural-interface/lib/antigravity/panel-bridge.js +1058 -0
- package/neural-interface/lib/antigravity/policy-hook.mjs +78 -0
- package/neural-interface/lib/antigravity/policy.js +74 -0
- package/neural-interface/lib/antigravity/tool-call.js +178 -0
- package/neural-interface/lib/antigravity/transcripts.js +252 -0
- package/neural-interface/lib/antigravity/usage.js +43 -0
- package/neural-interface/lib/assistant-api.js +1 -0
- package/neural-interface/lib/assistant-brains/antigravity.js +423 -0
- package/neural-interface/lib/assistant-budget-planner.js +7 -3
- package/neural-interface/lib/assistant-budget-split.js +42 -15
- package/neural-interface/lib/assistant-catalog.js +76 -9
- package/neural-interface/lib/assistant-config.js +6 -3
- package/neural-interface/lib/assistant-dispatch.js +207 -49
- package/neural-interface/lib/assistant-envelope.js +153 -1
- package/neural-interface/lib/assistant-evidence.js +80 -0
- package/neural-interface/lib/assistant-hidden-models.js +7 -5
- package/neural-interface/lib/assistant-persona.js +16 -11
- package/neural-interface/lib/assistant-plan-permissions.js +15 -0
- package/neural-interface/lib/assistant-router.js +237 -35
- package/neural-interface/lib/assistant-runtime.js +158 -12
- package/neural-interface/lib/assistant-task-prompt.js +10 -8
- package/neural-interface/lib/assistant-tools.js +2 -2
- package/neural-interface/lib/assistant-usage.js +29 -0
- package/neural-interface/lib/backup-service.js +6 -1
- package/neural-interface/lib/browser-guard-cdp.js +5 -4
- package/neural-interface/lib/browser-network-guard.js +274 -82
- package/neural-interface/lib/browser-tool-policy.js +12 -7
- package/neural-interface/lib/claude-agent-bridge.js +7 -0
- package/neural-interface/lib/claude-history-cache.js +210 -0
- package/neural-interface/lib/claude-model-catalog.js +5 -1
- package/neural-interface/lib/cli-install-api.js +1 -1
- package/neural-interface/lib/cli-install.js +160 -31
- package/neural-interface/lib/cli-resolver.js +9 -2
- package/neural-interface/lib/cli-update-planner.js +25 -15
- package/neural-interface/lib/codex-rollout-reader.js +52 -0
- package/neural-interface/lib/codex-worker-app-server.js +25 -6
- package/neural-interface/lib/editor-git-api.js +3 -20
- package/neural-interface/lib/exec-loop-command.js +9 -2
- package/neural-interface/lib/file-explorer-api.js +74 -40
- package/neural-interface/lib/file-explorer-watch.js +9 -3
- package/neural-interface/lib/git-bash/install.js +52 -6
- package/neural-interface/lib/git-bash/manager.js +59 -17
- package/neural-interface/lib/git-bash/pins.js +12 -0
- package/neural-interface/lib/git-read.js +2 -2
- package/neural-interface/lib/git-status-runner.js +390 -0
- package/neural-interface/lib/git-status-watchdog.js +40 -0
- package/neural-interface/lib/greeting/budgets.js +1 -0
- package/neural-interface/lib/greeting/engine.js +2 -2
- package/neural-interface/lib/greeting/sources.js +10 -12
- package/neural-interface/lib/greeting/writer.js +1 -1
- package/neural-interface/lib/mcp-client-config.js +37 -6
- package/neural-interface/lib/mcp-external-servers.js +13 -4
- package/neural-interface/lib/mcp-installer.js +2 -1
- package/neural-interface/lib/memory-session-capture.js +17 -3
- package/neural-interface/lib/morelogin.js +147 -25
- package/neural-interface/lib/native-loop-providers.js +420 -21
- package/neural-interface/lib/native-loop-runtime.js +23 -2
- package/neural-interface/lib/opencode-native-boundary.js +11 -2
- package/neural-interface/lib/owner-authority.js +1 -1
- package/neural-interface/lib/path-confine.js +12 -9
- package/neural-interface/lib/peer-identity.js +32 -2
- package/neural-interface/lib/pty-host/core.js +28 -1
- package/neural-interface/lib/pty-host/lifetime.js +12 -0
- package/neural-interface/lib/pty-host/manager.js +12 -1
- package/neural-interface/lib/remote-policy.js +1 -1
- package/neural-interface/lib/request-gate.js +3 -0
- package/neural-interface/lib/rulesets/api.js +6 -5
- package/neural-interface/lib/rulesets/fs-safe.js +1 -1
- package/neural-interface/lib/rulesets/installer.js +89 -10
- package/neural-interface/lib/rulesets/render.js +1 -1
- package/neural-interface/lib/session-cache-builder.js +64 -1
- package/neural-interface/lib/skills/catalog.js +5 -1
- package/neural-interface/lib/skills/creation-brief.js +1 -1
- package/neural-interface/lib/skills/creation-sources.js +19 -1
- package/neural-interface/lib/skills/deploy.js +9 -4
- package/neural-interface/lib/skills/draft-confinement.js +3 -1
- package/neural-interface/lib/skills/eval-confinement.js +3 -1
- package/neural-interface/lib/skills/eval-trace.js +16 -0
- package/neural-interface/lib/skills/export.js +5 -2
- package/neural-interface/lib/skills/known-bridge-digests.json +58 -4
- package/neural-interface/lib/skills/ownership.js +1 -1
- package/neural-interface/lib/skills/roots.js +10 -3
- package/neural-interface/lib/skills/runtime-checks.js +6 -3
- package/neural-interface/lib/skills/service.js +15 -7
- package/neural-interface/lib/skills/telemetry.js +6 -0
- package/neural-interface/lib/synabun-version.js +1 -1
- package/neural-interface/lib/system-activity.js +1 -1
- package/neural-interface/lib/whatsapp/brain.js +7 -3
- package/neural-interface/lib/whatsapp/cards.js +22 -9
- package/neural-interface/lib/whatsapp/config.js +1 -1
- package/neural-interface/lib/worker-confinement.js +77 -1
- package/neural-interface/lib/worker-question.js +74 -0
- package/neural-interface/lib/worker-resume.js +13 -4
- package/neural-interface/lib/worker-sandbox.js +46 -16
- package/neural-interface/package-lock.json +18 -2
- package/neural-interface/package.json +2 -1
- package/neural-interface/public/onboarding.html +1 -1
- package/neural-interface/public/shared/agent-runtime-options.js +89 -11
- package/neural-interface/public/shared/agy/agy-bypass.js +47 -0
- package/neural-interface/public/shared/agy/agy-client.js +266 -0
- package/neural-interface/public/shared/agy/agy-commands.js +120 -0
- package/neural-interface/public/shared/agy/agy-copy.js +326 -0
- package/neural-interface/public/shared/agy/agy-diff.js +161 -0
- package/neural-interface/public/shared/agy/agy-events.js +469 -0
- package/neural-interface/public/shared/agy/agy-greeting.js +26 -0
- package/neural-interface/public/shared/agy/agy-options.js +232 -0
- package/neural-interface/public/shared/agy/agy-panel.js +2543 -0
- package/neural-interface/public/shared/agy/agy-render.js +392 -0
- package/neural-interface/public/shared/agy/agy-setup.js +149 -0
- package/neural-interface/public/shared/agy/agy-styles.js +604 -0
- package/neural-interface/public/shared/agy/agy-tabs-logic.js +181 -0
- package/neural-interface/public/shared/api.js +4 -4
- package/neural-interface/public/shared/assistant/asst-agents-dock.js +3 -4
- package/neural-interface/public/shared/assistant/asst-api.js +1 -1
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +56 -9
- package/neural-interface/public/shared/assistant/asst-budget.js +5 -4
- package/neural-interface/public/shared/assistant/asst-control.js +48 -0
- package/neural-interface/public/shared/assistant/asst-hosts.js +16 -7
- package/neural-interface/public/shared/assistant/asst-limit-dock.js +6 -1
- package/neural-interface/public/shared/assistant/asst-limit-wait.js +38 -5
- package/neural-interface/public/shared/assistant/asst-panel.js +45 -8
- package/neural-interface/public/shared/assistant/asst-render.js +51 -12
- package/neural-interface/public/shared/assistant/asst-route.js +237 -57
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +9 -8
- package/neural-interface/public/shared/assistant/asst-scenes.js +54 -1
- package/neural-interface/public/shared/assistant/asst-sidepanel.js +51 -7
- package/neural-interface/public/shared/assistant/asst-slash.js +8 -2
- package/neural-interface/public/shared/assistant/asst-state.js +76 -9
- package/neural-interface/public/shared/assistant/asst-styles.js +34 -0
- package/neural-interface/public/shared/assistant/asst-tool-kinds.js +34 -7
- package/neural-interface/public/shared/assistant/asst-usage.js +2 -1
- package/neural-interface/public/shared/cdx/cdx-output.js +26 -3
- package/neural-interface/public/shared/cdx/cdx-panel.js +14 -2
- package/neural-interface/public/shared/cdx/cdx-preview.js +12 -0
- package/neural-interface/public/shared/cdx/cdx-protocol.js +11 -10
- package/neural-interface/public/shared/cdx/cdx-render.js +10 -9
- package/neural-interface/public/shared/cdx/cdx-requests.js +11 -1
- package/neural-interface/public/shared/cdx/cdx-styles.js +4 -0
- package/neural-interface/public/shared/cdx/cdx-tabs.js +75 -5
- package/neural-interface/public/shared/cli-install-controller.js +218 -0
- package/neural-interface/public/shared/cli-install-view.js +7 -4
- package/neural-interface/public/shared/cli-status.js +9 -8
- package/neural-interface/public/shared/constants.js +3 -2
- package/neural-interface/public/shared/context-menu-model.js +1 -0
- package/neural-interface/public/shared/cp/cp-restore.js +162 -0
- package/neural-interface/public/shared/cp/cp-tool-cards.js +10 -3
- package/neural-interface/public/shared/desktop-bridge.js +17 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +12 -0
- package/neural-interface/public/shared/desktop-titlebar.js +13 -4
- package/neural-interface/public/shared/desktop-update-view.js +1 -0
- package/neural-interface/public/shared/explorer/fx-api.js +4 -4
- package/neural-interface/public/shared/explorer/fx-links.js +3 -3
- package/neural-interface/public/shared/explorer/fx-logic.js +1 -1
- package/neural-interface/public/shared/explorer/fx-main.js +48 -16
- package/neural-interface/public/shared/explorer/fx-tree.js +1 -0
- package/neural-interface/public/shared/greeting/greeting-card.js +2 -2
- package/neural-interface/public/shared/greeting/greeting-view.js +1 -0
- package/neural-interface/public/shared/html-shell.js +21 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +27 -7
- package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +13 -4
- package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -1
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +17 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +46 -3
- package/neural-interface/public/shared/provider-icons.js +4 -2
- package/neural-interface/public/shared/settings/settings-rules.js +2 -2
- package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +1 -1
- package/neural-interface/public/shared/settings/settings-skill-folders.js +2 -2
- package/neural-interface/public/shared/showcase-privacy.js +6 -1
- package/neural-interface/public/shared/sidepanel-session-status.js +3 -3
- package/neural-interface/public/shared/skills/ss-creation.js +6 -3
- package/neural-interface/public/shared/skills/ss-dialog.js +5 -2
- package/neural-interface/public/shared/skills/ss-lint.js +9 -1
- package/neural-interface/public/shared/skills/ss-profiles.js +44 -6
- package/neural-interface/public/shared/skills/ss-review-view.js +2 -2
- package/neural-interface/public/shared/skills/studio/sx-actions.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-create-ai.js +2 -1
- package/neural-interface/public/shared/skills/studio/sx-dom.js +2 -1
- package/neural-interface/public/shared/skills/studio/sx-fixes-view.js +359 -0
- package/neural-interface/public/shared/skills/studio/sx-fixes.js +327 -0
- package/neural-interface/public/shared/skills/studio/sx-inspector.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-install-flow.js +9 -6
- package/neural-interface/public/shared/skills/studio/sx-install.js +20 -3
- package/neural-interface/public/shared/skills/studio/sx-library-view.js +144 -35
- package/neural-interface/public/shared/skills/studio/sx-library.js +6 -2
- package/neural-interface/public/shared/skills/studio/sx-main.js +11 -2
- package/neural-interface/public/shared/skills/studio/sx-review-view.js +1 -1
- package/neural-interface/public/shared/skills/studio/sx-subject.js +7 -6
- package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +6 -5
- package/neural-interface/public/shared/state.js +1 -1
- package/neural-interface/public/shared/streaming-markdown.js +58 -0
- package/neural-interface/public/shared/styles.css +354 -34
- package/neural-interface/public/shared/text-cache.js +29 -0
- package/neural-interface/public/shared/tool-list-picker.js +2 -2
- package/neural-interface/public/shared/tool-list-view.js +2 -2
- package/neural-interface/public/shared/topright-overflow-logic.js +54 -0
- package/neural-interface/public/shared/ui-antigravity-panel.js +19 -0
- package/neural-interface/public/shared/ui-assistant.js +2 -0
- package/neural-interface/public/shared/ui-automation-studio.js +20 -12
- package/neural-interface/public/shared/ui-claude-panel.js +299 -77
- package/neural-interface/public/shared/ui-cli-banner.js +23 -167
- package/neural-interface/public/shared/ui-file-explorer.js +48 -6
- package/neural-interface/public/shared/ui-file-links.js +2 -2
- package/neural-interface/public/shared/ui-games.js +2 -2
- package/neural-interface/public/shared/ui-judgments.js +1 -1
- package/neural-interface/public/shared/ui-keybinds.js +8 -2
- package/neural-interface/public/shared/ui-link.js +3 -3
- package/neural-interface/public/shared/ui-menubar.js +2 -2
- package/neural-interface/public/shared/ui-native-loop-router.js +4 -0
- package/neural-interface/public/shared/ui-navbar.js +45 -0
- package/neural-interface/public/shared/ui-notifications.js +1 -0
- package/neural-interface/public/shared/ui-resume.js +9 -7
- package/neural-interface/public/shared/ui-schedules-studio.js +41 -10
- package/neural-interface/public/shared/ui-scroll-follow.js +16 -5
- package/neural-interface/public/shared/ui-sessions.js +22 -12
- package/neural-interface/public/shared/ui-settings.js +90 -65
- package/neural-interface/public/shared/ui-sidepanel-session-entry.js +9 -2
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +3 -3
- package/neural-interface/public/shared/ui-sidepanel-tray.js +48 -7
- package/neural-interface/public/shared/ui-sidepanel-windows.js +3 -3
- package/neural-interface/public/shared/ui-terminal.js +146 -10
- package/neural-interface/public/shared/ui-tool-updates.js +3 -3
- package/neural-interface/public/shared/ui-tooltip.js +71 -46
- package/neural-interface/public/shared/ui-topright-overflow.js +233 -0
- package/neural-interface/public/shared/ui-whiteboard.js +1 -1
- package/neural-interface/public/shared/ui-worker-end.js +1 -1
- package/neural-interface/public/shared/whatsapp/wa-view.js +2 -2
- package/neural-interface/public/shared/worker-questions.js +34 -0
- package/neural-interface/public/sidepanel-session.html +1 -1
- package/neural-interface/server.js +644 -426
- package/neural-interface/templates/rulesets/README.md +1 -1
- package/neural-interface/templates/rulesets/legacy-hashes.json +5 -5
- package/neural-interface/templates/rulesets/manifest.json +1 -1
- package/npm-shrinkwrap.json +18 -2
- package/package.json +2 -1
- package/skills/skill-forge/SKILL.md +4 -4
- package/skills/synabun/SKILL.md +1 -1
- package/skills/synabun/modules/schedule.md +3 -3
- /package/neural-interface/templates/rulesets/{gemini.md → antigravity.md} +0 -0
|
@@ -4,10 +4,24 @@ import { detectProject } from '../../mcp-server/dist/config.js';
|
|
|
4
4
|
import { normalizeMemoryEvents, ingestMemoryEvents } from '../../mcp-server/dist/services/memory-sessions.js';
|
|
5
5
|
import { maintenancePaused } from './memory-timers.js';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
/** The hosts whose transcripts are captured from a file (OpenCode's rows are taken in session-cache-builder.js). */
|
|
8
|
+
export const CAPTURE_HOSTS=Object.freeze(['claude-code','codex','antigravity']);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* `size`: the transcript's size now, when the caller knows it. A file already read to that size is left as it is
|
|
12
|
+
* (a pass over every Antigravity conversation would otherwise mark each one pending again).
|
|
13
|
+
*/
|
|
14
|
+
export function queueMemoryCapture({host,sessionId,filePath,project,cwd,size=null}) {
|
|
15
|
+
if(!filePath || !sessionId || !CAPTURE_HOSTS.includes(host))return;
|
|
16
|
+
if(size!=null) {
|
|
17
|
+
const row=getDb().prepare('SELECT file_path,byte_offset,status,cwd FROM memory_capture_files WHERE host=? AND session_id=?').get(host,sessionId);
|
|
18
|
+
if(row && row.status==='complete' && row.file_path===filePath && Number(row.byte_offset)===Number(size) && (row.cwd || null)===(cwd || null))return;
|
|
19
|
+
}
|
|
20
|
+
// An Antigravity conversation whose folder agy named only later is read again from its start: its events take the
|
|
21
|
+
// project (each step keeps its source id, so nothing is stored twice).
|
|
9
22
|
getDb().prepare(`INSERT INTO memory_capture_files(host,session_id,file_path,project,cwd) VALUES(?,?,?,?,?)
|
|
10
|
-
ON CONFLICT(host,session_id) DO UPDATE SET file_path=excluded.file_path,project=excluded.project,cwd=excluded.cwd,status='pending',error=NULL
|
|
23
|
+
ON CONFLICT(host,session_id) DO UPDATE SET file_path=excluded.file_path,project=excluded.project,cwd=excluded.cwd,status='pending',error=NULL,
|
|
24
|
+
byte_offset=CASE WHEN excluded.host='antigravity' AND memory_capture_files.cwd IS NOT excluded.cwd THEN 0 ELSE memory_capture_files.byte_offset END`)
|
|
11
25
|
.run(host,sessionId,filePath,cwd ? detectProject(cwd) : project || 'global',cwd || null);
|
|
12
26
|
}
|
|
13
27
|
|
|
@@ -47,7 +47,8 @@ export function isMoreLoginInstalled() {
|
|
|
47
47
|
} else if (process.platform === 'win32') {
|
|
48
48
|
const { LOCALAPPDATA, ProgramFiles } = process.env;
|
|
49
49
|
const PF86 = process.env['ProgramFiles(x86)'];
|
|
50
|
-
if (
|
|
50
|
+
if (process.env.MORELOGIN_APP_PATH) candidates.push(process.env.MORELOGIN_APP_PATH);
|
|
51
|
+
if (LOCALAPPDATA) candidates.push(`${LOCALAPPDATA}\\Programs\\MoreLogin\\MoreLogin.exe`, `${LOCALAPPDATA}\\Programs\\morelogin\\MoreLogin.exe`, `${LOCALAPPDATA}\\MoreLogin\\MoreLogin.exe`);
|
|
51
52
|
if (ProgramFiles) candidates.push(`${ProgramFiles}\\MoreLogin\\MoreLogin.exe`);
|
|
52
53
|
if (PF86) candidates.push(`${PF86}\\MoreLogin\\MoreLogin.exe`);
|
|
53
54
|
} else {
|
|
@@ -100,40 +101,147 @@ function buildHeaders(opts = {}) {
|
|
|
100
101
|
|
|
101
102
|
/**
|
|
102
103
|
* Low-level POST to the MoreLogin local API. Returns the `data` payload.
|
|
103
|
-
* Throws with a `.code` of MORELOGIN_UNREACHABLE | MORELOGIN_HTTP | MORELOGIN_API
|
|
104
|
+
* Throws with a `.code` of MORELOGIN_UNREACHABLE | MORELOGIN_HTTP | MORELOGIN_API | MORELOGIN_SHAPE
|
|
105
|
+
* (answered 2xx with a body that is not JSON).
|
|
106
|
+
*/
|
|
107
|
+
// Loopback hosts to try, in order. MoreLogin's local server may listen on IPv6 only
|
|
108
|
+
// (an Electron server bound to "localhost" resolves to ::1 first on Windows), so a
|
|
109
|
+
// refused 127.0.0.1 is retried on [::1]. The host that answered is remembered.
|
|
110
|
+
const LOOPBACK_HOSTS = ['127.0.0.1', '[::1]'];
|
|
111
|
+
let _preferredHost = LOOPBACK_HOSTS[0];
|
|
112
|
+
let _lastAnswerAt = 0; // when the local API last answered anything (any status, any body)
|
|
113
|
+
export function _resetMoreLoginHostForTests() { _preferredHost = LOOPBACK_HOSTS[0]; _lastAnswerAt = 0; }
|
|
114
|
+
export function _preferredMoreLoginHostForTests() { return _preferredHost; }
|
|
115
|
+
|
|
116
|
+
/** Whether the local API answered within the last `withinMs` (no request is made). */
|
|
117
|
+
export function moreLoginApiAnsweredRecently(withinMs = 120000) {
|
|
118
|
+
return _lastAnswerAt > 0 && Date.now() - _lastAnswerAt <= withinMs;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Cheap, synchronous "is MoreLogin here": the exe is in a known folder (or
|
|
123
|
+
* MORELOGIN_APP_PATH) or its local API answered recently. Callers that need a
|
|
124
|
+
* fresh answer probe first (probeMoreLoginApi).
|
|
125
|
+
*/
|
|
126
|
+
export function isMoreLoginPresent(withinMs = 120000) {
|
|
127
|
+
let exe = false;
|
|
128
|
+
try { exe = isMoreLoginInstalled().installed; } catch { exe = false; }
|
|
129
|
+
return exe || moreLoginApiAnsweredRecently(withinMs);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Error codes that prove the connection never opened, so the request was never
|
|
133
|
+
// delivered and the other loopback host may be tried even for a call that changes
|
|
134
|
+
// state (create, start). Anything else (a reset after sending, a malformed answer)
|
|
135
|
+
// may have reached MoreLogin: it is thrown, never sent a second time.
|
|
136
|
+
const NEVER_CONNECTED_CODES = new Set([
|
|
137
|
+
'ECONNREFUSED', 'EHOSTUNREACH', 'ENETUNREACH', 'EADDRNOTAVAIL', 'EAFNOSUPPORT', 'ENOTFOUND',
|
|
138
|
+
'EAI_AGAIN', 'UND_ERR_CONNECT_TIMEOUT', 'UND_ERR_CONNECT',
|
|
139
|
+
]);
|
|
140
|
+
export function _neverConnected(err) {
|
|
141
|
+
for (let e = err, i = 0; e && i < 4; e = e.cause, i++) {
|
|
142
|
+
if (NEVER_CONNECTED_CODES.has(e.code)) return true;
|
|
143
|
+
if (Array.isArray(e.errors) && e.errors.some(x => NEVER_CONNECTED_CODES.has(x?.code))) return true;
|
|
144
|
+
}
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* One deadline for the whole call (opts.timeout, default 15 s): each loopback host
|
|
150
|
+
* gets what is left of it, so two hosts never double the budget. The other host is
|
|
151
|
+
* tried while time remains when the first one provably never connected; a timeout
|
|
152
|
+
* is tried on the other host only for a read (opts.idempotent), since a timed-out
|
|
153
|
+
* write may have been received.
|
|
104
154
|
*/
|
|
105
155
|
async function request(path, body, opts = {}) {
|
|
106
156
|
const port = opts.port || getMoreLoginPort(opts.savedCfg);
|
|
107
|
-
const
|
|
157
|
+
const fetchImpl = opts.fetch || fetch;
|
|
158
|
+
const idempotent = opts.idempotent ?? (path === '/api/env/page' || path === '/api/env/status');
|
|
159
|
+
const budget = opts.timeout || 15000;
|
|
160
|
+
const deadline = Date.now() + budget;
|
|
161
|
+
const hosts = [_preferredHost, ...LOOPBACK_HOSTS.filter(h => h !== _preferredHost)];
|
|
108
162
|
let res;
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
163
|
+
let lastErr = null;
|
|
164
|
+
for (const host of hosts) {
|
|
165
|
+
const left = deadline - Date.now();
|
|
166
|
+
if (left <= 0) break;
|
|
167
|
+
try {
|
|
168
|
+
res = await fetchImpl(`http://${host}:${port}${path}`, {
|
|
169
|
+
method: 'POST',
|
|
170
|
+
headers: buildHeaders(opts),
|
|
171
|
+
body: JSON.stringify(body || {}),
|
|
172
|
+
signal: AbortSignal.timeout(left),
|
|
173
|
+
});
|
|
174
|
+
_preferredHost = host;
|
|
175
|
+
_lastAnswerAt = Date.now();
|
|
176
|
+
break;
|
|
177
|
+
} catch (err) {
|
|
178
|
+
lastErr = err;
|
|
179
|
+
const timedOut = err?.name === 'TimeoutError' || err?.name === 'AbortError';
|
|
180
|
+
const retry = _neverConnected(err) || (timedOut && idempotent);
|
|
181
|
+
if (!retry) break;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (!res) {
|
|
185
|
+
const err = lastErr;
|
|
186
|
+
const reason = !err ? `no time left of ${budget} ms` : (err?.cause?.code || err?.code || err?.message || err);
|
|
187
|
+
const e = new Error(`MoreLogin API unreachable on :${port} (${reason})`);
|
|
118
188
|
e.code = 'MORELOGIN_UNREACHABLE';
|
|
119
189
|
throw e;
|
|
120
190
|
}
|
|
121
191
|
let json = null;
|
|
192
|
+
let unparsable = false;
|
|
122
193
|
try { json = await res.json(); }
|
|
123
|
-
catch { try { await res.body?.cancel(); } catch { /* ignore */ } }
|
|
194
|
+
catch { unparsable = true; try { await res.body?.cancel(); } catch { /* ignore */ } }
|
|
124
195
|
if (!res.ok) {
|
|
125
|
-
const
|
|
196
|
+
const detail = json && (json.msg || json.message);
|
|
197
|
+
const e = new Error(`MoreLogin API ${path} → HTTP ${res.status}${detail ? ` (${detail})` : ''}${res.status === 401 || res.status === 403 ? ' (set the API ID and API Key from MoreLogin → Settings → API in SynaBun Settings → MoreLogin)' : ''}`);
|
|
126
198
|
e.code = 'MORELOGIN_HTTP';
|
|
127
199
|
e.status = res.status;
|
|
128
200
|
throw e;
|
|
129
201
|
}
|
|
130
202
|
if (json && json.code !== undefined && json.code !== 0) {
|
|
131
|
-
const
|
|
203
|
+
const msg = json.msg || json.message || `code ${json.code}`;
|
|
204
|
+
const e = new Error(`MoreLogin API ${path}: ${msg}${looksLikeAuthError(json.code, msg) ? ' (set the API ID and API Key from MoreLogin → Settings → API in SynaBun Settings → MoreLogin)' : ''}`);
|
|
132
205
|
e.code = 'MORELOGIN_API';
|
|
133
206
|
e.apiCode = json.code;
|
|
134
207
|
throw e;
|
|
135
208
|
}
|
|
136
|
-
|
|
209
|
+
if (unparsable || !json || typeof json !== 'object') {
|
|
210
|
+
const type = res.headers?.get?.('content-type') || 'no content type';
|
|
211
|
+
const e = new Error(`MoreLogin API ${path} answered HTTP ${res.status} with a body that is not JSON (${type}); is something else listening on port ${port}?`);
|
|
212
|
+
e.code = 'MORELOGIN_SHAPE';
|
|
213
|
+
throw e;
|
|
214
|
+
}
|
|
215
|
+
return json.data;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function looksLikeAuthError(code, msg) {
|
|
219
|
+
return /auth|sign|api.?key|api.?id|nonce|unauthori[sz]ed|forbidden|permission|token/i.test(String(msg || ''))
|
|
220
|
+
|| code === 401 || code === 403;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const PROFILE_LIST_KEYS = ['dataList', 'list', 'records', 'rows'];
|
|
224
|
+
|
|
225
|
+
/** Profile rows across response shapes: data.dataList | data.list | data.records | data.rows | data (array). A non-empty array wins over an empty one. */
|
|
226
|
+
export function profileRows(data) {
|
|
227
|
+
if (Array.isArray(data)) return data;
|
|
228
|
+
if (!data || typeof data !== 'object') return [];
|
|
229
|
+
const arrays = PROFILE_LIST_KEYS.map(k => data[k]).filter(Array.isArray);
|
|
230
|
+
return arrays.find(a => a.length) || arrays[0] || [];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** Whether a profile-page answer has a shape SynaBun reads (an array, a known list key, or a total). */
|
|
234
|
+
export function hasProfileShape(data) {
|
|
235
|
+
if (Array.isArray(data)) return true;
|
|
236
|
+
if (!data || typeof data !== 'object') return false;
|
|
237
|
+
return PROFILE_LIST_KEYS.some(k => Array.isArray(data[k])) || (data.total != null && Number.isFinite(Number(data.total)));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function shapeError(data) {
|
|
241
|
+
const keys = data && typeof data === 'object' ? Object.keys(data).slice(0, 8).join(', ') : typeof data;
|
|
242
|
+
const e = new Error(`MoreLogin API /api/env/page answered in a shape SynaBun does not read (data: ${keys || 'empty'}); a newer MoreLogin may have changed its API`);
|
|
243
|
+
e.code = 'MORELOGIN_SHAPE';
|
|
244
|
+
return e;
|
|
137
245
|
}
|
|
138
246
|
|
|
139
247
|
/**
|
|
@@ -171,19 +279,29 @@ function normalizeProfile(e = {}) {
|
|
|
171
279
|
/** List browser profiles (environments). Returns normalized rows. */
|
|
172
280
|
export async function listProfiles(opts = {}) {
|
|
173
281
|
const data = await request('/api/env/page', { pageNo: opts.pageNo || 1, pageSize: opts.pageSize || 100 }, opts);
|
|
174
|
-
|
|
175
|
-
return
|
|
282
|
+
if (!hasProfileShape(data)) throw shapeError(data);
|
|
283
|
+
return profileRows(data).map(normalizeProfile).filter(p => p.id);
|
|
176
284
|
}
|
|
177
285
|
|
|
178
|
-
/**
|
|
286
|
+
/**
|
|
287
|
+
* Lightweight reachability probe. Never throws — returns {running, count}.
|
|
288
|
+
* `running` means the local API answered at all: an answer that is an HTTP or API
|
|
289
|
+
* error (signature required, API disabled, ...) still proves MoreLogin is up, and its
|
|
290
|
+
* reason is returned in `apiError` instead of being reported as "not running".
|
|
291
|
+
*/
|
|
179
292
|
export async function probeMoreLoginApi(opts = {}) {
|
|
180
293
|
try {
|
|
181
294
|
const data = await request('/api/env/page', { pageNo: 1, pageSize: 1 }, { ...opts, timeout: opts.timeout || 4000 });
|
|
182
|
-
|
|
183
|
-
|
|
295
|
+
if (!hasProfileShape(data)) throw shapeError(data);
|
|
296
|
+
const total = data && !Array.isArray(data) && data.total != null ? Number(data.total) : profileRows(data).length;
|
|
184
297
|
return { running: true, count: Number.isFinite(total) ? total : 0 };
|
|
185
298
|
} catch (err) {
|
|
186
|
-
|
|
299
|
+
const answered = err?.code === 'MORELOGIN_HTTP' || err?.code === 'MORELOGIN_API' || err?.code === 'MORELOGIN_SHAPE';
|
|
300
|
+
return {
|
|
301
|
+
running: answered, count: 0,
|
|
302
|
+
error: err?.message || String(err), errCode: err?.code || null,
|
|
303
|
+
...(answered ? { apiError: err?.message || String(err) } : {}),
|
|
304
|
+
};
|
|
187
305
|
}
|
|
188
306
|
}
|
|
189
307
|
|
|
@@ -221,13 +339,17 @@ export async function getMoreLoginStatus(opts = {}) {
|
|
|
221
339
|
const port = getMoreLoginPort(opts.savedCfg);
|
|
222
340
|
const probe = await probeMoreLoginApi({ ...opts, port });
|
|
223
341
|
return {
|
|
224
|
-
|
|
342
|
+
// An answering local API is proof of an install, wherever it lives (a custom
|
|
343
|
+
// install folder on Windows is not among the known paths).
|
|
344
|
+
installed: inst.installed || probe.running,
|
|
225
345
|
appPath: inst.path,
|
|
226
346
|
port,
|
|
227
347
|
running: probe.running,
|
|
348
|
+
apiError: probe.apiError || null,
|
|
228
349
|
profileCount: probe.count || 0,
|
|
229
350
|
signed: !!((opts.appId || process.env.MORELOGIN_API_ID) && (opts.secretKey || process.env.MORELOGIN_SECRET)),
|
|
230
|
-
|
|
351
|
+
// Transport failures only: an API that answered with an error is running, and says why in apiError.
|
|
352
|
+
error: probe.running ? null : (probe.error || null),
|
|
231
353
|
};
|
|
232
354
|
}
|
|
233
355
|
|
|
@@ -259,7 +381,7 @@ export async function startProfile(envId, opts = {}) {
|
|
|
259
381
|
try {
|
|
260
382
|
data = await request('/api/env/start', { envId: String(envId), ...(opts.startArgs || {}) }, opts);
|
|
261
383
|
} catch (err) {
|
|
262
|
-
if (err?.code === 'MORELOGIN_UNREACHABLE' || err?.code === 'MORELOGIN_HTTP') throw err;
|
|
384
|
+
if (err?.code === 'MORELOGIN_UNREACHABLE' || err?.code === 'MORELOGIN_HTTP' || err?.code === 'MORELOGIN_SHAPE') throw err;
|
|
263
385
|
// MORELOGIN_API (e.g. "already running") → fall through to status recovery.
|
|
264
386
|
}
|
|
265
387
|
let port = extractDebugPort(data);
|