synabun 2.0.5 → 2.0.7
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 +40 -0
- package/README.md +2 -1
- package/THIRD-PARTY-LICENSES.md +13 -0
- package/docs/whatsapp.md +151 -16
- package/hooks/claude-code/shared.mjs +6 -3
- package/lib/child-path.js +303 -0
- package/lib/claude-hooks.js +2 -1
- package/lib/data-home-migration.js +2 -0
- package/lib/desktop-app.js +265 -0
- package/lib/external-tools.js +7 -3
- package/lib/log-redact.js +102 -0
- package/lib/packaged-runtime.js +138 -11
- package/mcp-server/dist/http.d.ts +3 -1
- package/mcp-server/dist/http.d.ts.map +1 -1
- package/mcp-server/dist/http.js +15 -4
- package/mcp-server/dist/http.js.map +1 -1
- package/mcp-server/dist/index.d.ts.map +1 -1
- package/mcp-server/dist/index.js +9 -6
- package/mcp-server/dist/index.js.map +1 -1
- package/mcp-server/dist/services/budget-judgments.d.ts +108 -0
- package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -0
- package/mcp-server/dist/services/budget-judgments.js +153 -0
- package/mcp-server/dist/services/budget-judgments.js.map +1 -0
- package/mcp-server/dist/services/codex-config-heal.d.ts +5 -1
- package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
- package/mcp-server/dist/services/codex-config-heal.js +41 -4
- package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
- package/mcp-server/dist/services/identity.d.ts +11 -0
- package/mcp-server/dist/services/identity.d.ts.map +1 -1
- package/mcp-server/dist/services/identity.js +24 -0
- package/mcp-server/dist/services/identity.js.map +1 -1
- package/mcp-server/dist/services/neural-interface.d.ts +13 -0
- package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
- package/mcp-server/dist/services/neural-interface.js +34 -2
- package/mcp-server/dist/services/neural-interface.js.map +1 -1
- package/mcp-server/dist/services/typesafe-config.d.ts +1 -1
- package/mcp-server/dist/services/typesafe-config.d.ts.map +1 -1
- package/mcp-server/dist/services/typesafe-config.js +4 -1
- package/mcp-server/dist/services/typesafe-config.js.map +1 -1
- package/mcp-server/dist/tools/agents.d.ts +10 -7
- package/mcp-server/dist/tools/agents.d.ts.map +1 -1
- package/mcp-server/dist/tools/agents.js +34 -13
- package/mcp-server/dist/tools/agents.js.map +1 -1
- package/mcp-server/dist/tools/whatsapp-send-file.d.ts +17 -0
- package/mcp-server/dist/tools/whatsapp-send-file.d.ts.map +1 -0
- package/mcp-server/dist/tools/whatsapp-send-file.js +44 -0
- package/mcp-server/dist/tools/whatsapp-send-file.js.map +1 -0
- package/mcp-server/dist/tui.js +2 -1
- package/mcp-server/dist/tui.js.map +1 -1
- package/mcp-server/dist/version.d.ts +5 -0
- package/mcp-server/dist/version.d.ts.map +1 -0
- package/mcp-server/dist/version.js +21 -0
- package/mcp-server/dist/version.js.map +1 -0
- package/mcp-server/package-lock.json +2 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/run.mjs +15 -9
- package/mcp-server/src/http.ts +18 -3
- package/mcp-server/src/index.ts +9 -6
- package/mcp-server/src/services/budget-judgments.ts +183 -0
- package/mcp-server/src/services/codex-config-heal.ts +35 -4
- package/mcp-server/src/services/identity.ts +27 -0
- package/mcp-server/src/services/neural-interface.ts +34 -2
- package/mcp-server/src/services/typesafe-config.ts +4 -1
- package/mcp-server/src/tools/agents.ts +33 -14
- package/mcp-server/src/tools/whatsapp-send-file.ts +51 -0
- package/mcp-server/src/tui.ts +2 -1
- package/mcp-server/src/version.ts +22 -0
- package/neural-interface/i18n/en.json +627 -57
- package/neural-interface/i18n/pt-BR.json +626 -56
- package/neural-interface/lib/account-usage.js +163 -0
- package/neural-interface/lib/assistant-api.js +255 -52
- package/neural-interface/lib/assistant-brains/claude.js +15 -2
- package/neural-interface/lib/assistant-brains/codex.js +3 -0
- package/neural-interface/lib/assistant-brains/opencode.js +17 -4
- package/neural-interface/lib/assistant-budget-planner.js +390 -0
- package/neural-interface/lib/assistant-budget-split.js +408 -0
- package/neural-interface/lib/assistant-budget.js +94 -95
- package/neural-interface/lib/assistant-config.js +62 -14
- package/neural-interface/lib/assistant-dispatch.js +432 -125
- package/neural-interface/lib/assistant-jev.js +26 -3
- package/neural-interface/lib/assistant-persona.js +68 -11
- package/neural-interface/lib/assistant-plan-permissions.js +8 -1
- package/neural-interface/lib/assistant-route-accounts.js +14 -0
- package/neural-interface/lib/assistant-route-gate.js +19 -3
- package/neural-interface/lib/assistant-router.js +373 -42
- package/neural-interface/lib/assistant-runtime.js +307 -47
- package/neural-interface/lib/assistant-user-writer.js +4 -2
- package/neural-interface/lib/augmented-path.js +317 -53
- package/neural-interface/lib/claude-accounts.js +342 -31
- package/neural-interface/lib/claude-agent-bridge.js +90 -3
- package/neural-interface/lib/claude-executable.js +6 -1
- package/neural-interface/lib/claude-model-catalog.js +3 -3
- package/neural-interface/lib/claude-panel-auth.js +221 -0
- package/neural-interface/lib/claude-profile-api-key.js +62 -0
- package/neural-interface/lib/cli-install-api.js +137 -0
- package/neural-interface/lib/cli-install.js +797 -0
- package/neural-interface/lib/cli-path.js +130 -0
- package/neural-interface/lib/cli-resolver.js +744 -0
- package/neural-interface/lib/cli-update-planner.js +143 -7
- package/neural-interface/lib/codex-account-auth.js +178 -0
- package/neural-interface/lib/codex-accounts.js +489 -0
- package/neural-interface/lib/codex-capabilities.js +2 -1
- package/neural-interface/lib/codex-compat-rpc.js +8 -2
- package/neural-interface/lib/codex-mcp-approvals.js +5 -1
- package/neural-interface/lib/codex-panel-auth.js +62 -0
- package/neural-interface/lib/codex-session-settings.js +1 -1
- package/neural-interface/lib/codex-settings-schema.js +120 -0
- package/neural-interface/lib/desktop/config.js +3 -0
- package/neural-interface/lib/git-bash/bzip2.js +339 -0
- package/neural-interface/lib/git-bash/claude-settings.js +73 -0
- package/neural-interface/lib/git-bash/extract-worker.js +34 -0
- package/neural-interface/lib/git-bash/install.js +529 -0
- package/neural-interface/lib/git-bash/licenses/COPYING +360 -0
- package/neural-interface/lib/git-bash/licenses/LGPL-2.1 +511 -0
- package/neural-interface/lib/git-bash/manager.js +268 -0
- package/neural-interface/lib/git-bash/pins.js +206 -0
- package/neural-interface/lib/git-bash/pins.json +34 -0
- package/neural-interface/lib/git-bash/resolver.js +194 -0
- package/neural-interface/lib/git-read.js +34 -2
- package/neural-interface/lib/install-details.js +145 -0
- package/neural-interface/lib/mcp-installer.js +14 -2
- package/neural-interface/lib/native-loop-providers.js +16 -3
- package/neural-interface/lib/native-loop-runtime.js +9 -4
- package/neural-interface/lib/os-path.js +319 -0
- package/neural-interface/lib/provider-panel-api-key-auth.js +92 -0
- package/neural-interface/lib/provider-panel-terminal-auth.js +95 -0
- package/neural-interface/lib/pty-host/core.js +2 -1
- package/neural-interface/lib/pty-host/manager.js +27 -2
- package/neural-interface/lib/remote-policy.js +20 -11
- package/neural-interface/lib/session-title-generator.js +4 -3
- package/neural-interface/lib/system-about.js +340 -0
- package/neural-interface/lib/system-activity.js +66 -0
- package/neural-interface/lib/terminal-env.js +11 -3
- package/neural-interface/lib/terminal-path.js +55 -0
- package/neural-interface/lib/virtual-socket.js +12 -1
- package/neural-interface/lib/whatsapp/baileys-adapter.js +165 -45
- package/neural-interface/lib/whatsapp/bridge.js +78 -34
- package/neural-interface/lib/whatsapp/commands.js +13 -14
- package/neural-interface/lib/whatsapp/config.js +134 -20
- package/neural-interface/lib/whatsapp/fake-baileys.js +99 -14
- package/neural-interface/lib/whatsapp/host-core.js +168 -35
- package/neural-interface/lib/whatsapp/inbound.js +5 -3
- package/neural-interface/lib/whatsapp/local-file.js +524 -0
- package/neural-interface/lib/whatsapp/manager.js +92 -32
- package/neural-interface/lib/whatsapp/paths.js +11 -1
- package/neural-interface/lib/whatsapp/protocol.js +65 -5
- package/neural-interface/lib/whatsapp/redact.js +63 -0
- package/neural-interface/lib/whatsapp/service.js +343 -91
- package/neural-interface/lib/whatsapp/transcription.js +463 -0
- package/neural-interface/package-lock.json +2 -2
- package/neural-interface/package.json +1 -1
- package/neural-interface/public/index.html +2 -0
- package/neural-interface/public/index2d.html +2 -0
- package/neural-interface/public/offline.html +16 -1
- package/neural-interface/public/onboarding.html +96 -2
- package/neural-interface/public/shared/account-i18n.js +7 -0
- package/neural-interface/public/shared/account-menu.js +539 -0
- package/neural-interface/public/shared/account-usage.js +19 -0
- package/neural-interface/public/shared/account-view.js +335 -0
- package/neural-interface/public/shared/agent-runtime-options.js +28 -8
- package/neural-interface/public/shared/assistant/asst-accounts.js +182 -184
- package/neural-interface/public/shared/assistant/asst-api.js +32 -2
- package/neural-interface/public/shared/assistant/asst-brain-picker.js +124 -25
- package/neural-interface/public/shared/assistant/asst-budget.js +259 -303
- package/neural-interface/public/shared/assistant/asst-mascot.js +126 -7
- package/neural-interface/public/shared/assistant/asst-menu.js +15 -3
- package/neural-interface/public/shared/assistant/asst-panel.js +48 -14
- package/neural-interface/public/shared/assistant/asst-render.js +38 -7
- package/neural-interface/public/shared/assistant/asst-route.js +72 -14
- package/neural-interface/public/shared/assistant/asst-routes-editor.js +45 -6
- package/neural-interface/public/shared/assistant/asst-slash.js +1 -1
- package/neural-interface/public/shared/assistant/asst-state.js +1 -1
- package/neural-interface/public/shared/assistant/asst-styles.js +99 -17
- package/neural-interface/public/shared/cdx/cdx-commands.js +4 -1
- package/neural-interface/public/shared/cdx/cdx-features.js +22 -14
- package/neural-interface/public/shared/cdx/cdx-icons.js +2 -0
- package/neural-interface/public/shared/cdx/cdx-panel.js +48 -107
- package/neural-interface/public/shared/cdx/cdx-settings.js +231 -0
- package/neural-interface/public/shared/cdx/cdx-styles.js +128 -107
- package/neural-interface/public/shared/cdx/cdx-tabs.js +261 -664
- package/neural-interface/public/shared/cdx/cdx-ws.js +2 -0
- package/neural-interface/public/shared/claude-account-view.js +3 -0
- package/neural-interface/public/shared/cli-install-view.js +392 -0
- package/neural-interface/public/shared/cli-status.js +282 -22
- package/neural-interface/public/shared/cp/cp-events.js +2 -1
- package/neural-interface/public/shared/cp/cp-styles.js +46 -0
- package/neural-interface/public/shared/desktop-bridge.js +39 -0
- package/neural-interface/public/shared/desktop-titlebar-page.js +59 -0
- package/neural-interface/public/shared/desktop-titlebar-view.js +122 -0
- package/neural-interface/public/shared/desktop-titlebar.js +153 -0
- package/neural-interface/public/shared/desktop-update-view.js +462 -0
- package/neural-interface/public/shared/editor/editor-panel.js +1 -1
- package/neural-interface/public/shared/explorer/fx-main.js +1 -1
- package/neural-interface/public/shared/git-bash-view.js +145 -0
- package/neural-interface/public/shared/html-shell.js +1 -0
- package/neural-interface/public/shared/i18n.js +19 -1
- package/neural-interface/public/shared/install-details-view.js +86 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +32 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +17 -0
- package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +118 -0
- package/neural-interface/public/shared/pwa-install-page.js +3 -1
- package/neural-interface/public/shared/settings/settings-about-pane.js +271 -0
- package/neural-interface/public/shared/settings/settings-about.js +254 -0
- package/neural-interface/public/shared/settings/settings-ia.js +15 -0
- package/neural-interface/public/shared/showcase-privacy.js +489 -0
- package/neural-interface/public/shared/storage.js +30 -3
- package/neural-interface/public/shared/styles.css +278 -31
- package/neural-interface/public/shared/synabun-mascot.js +48 -2
- package/neural-interface/public/shared/ui-claude-panel.js +212 -213
- package/neural-interface/public/shared/ui-cli-banner.js +355 -0
- package/neural-interface/public/shared/ui-git-bash.js +124 -0
- package/neural-interface/public/shared/ui-judgments.js +10 -1
- package/neural-interface/public/shared/ui-loading.js +30 -6
- package/neural-interface/public/shared/ui-menubar.js +13 -3
- package/neural-interface/public/shared/ui-navbar.js +3 -1
- package/neural-interface/public/shared/ui-provider-auth.js +104 -0
- package/neural-interface/public/shared/ui-provider-terminal-auth.js +223 -0
- package/neural-interface/public/shared/ui-sessions.js +9 -3
- package/neural-interface/public/shared/ui-settings.js +55 -3
- package/neural-interface/public/shared/ui-sidepanel-sessions.js +3 -1
- package/neural-interface/public/shared/ui-sync.js +6 -0
- package/neural-interface/public/shared/ui-terminal.js +17 -0
- package/neural-interface/public/shared/ui-tool-updates.js +5 -0
- package/neural-interface/public/shared/ui-update.js +594 -5
- package/neural-interface/public/shared/ui-whatsapp.js +21 -6
- package/neural-interface/public/shared/whatsapp/wa-view.js +51 -8
- package/neural-interface/public/shared/worker-end.js +2 -0
- package/neural-interface/public/sw.js +1 -1
- package/neural-interface/public/variant/2d/main.js +10 -1
- package/neural-interface/public/variant/3d/main.js +10 -1
- package/neural-interface/server.js +1219 -608
- package/package.json +4 -1
- package/setup.js +9 -8
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════
|
|
2
|
+
// SETTINGS — About (what it says)
|
|
3
|
+
// ═══════════════════════════════════════════
|
|
4
|
+
//
|
|
5
|
+
// The About page reads GET /api/system/about (lib/system-about.js). A server from before that route answers 404
|
|
6
|
+
// until it restarts (the page's files are served live): the page then shows what /api/health and
|
|
7
|
+
// /api/system/version already say, with a note, and nothing fails. This module turns either answer into what the
|
|
8
|
+
// page draws: labels, the dependency lists a filter leaves, the plain-text block "Copy info" puts on the clipboard.
|
|
9
|
+
//
|
|
10
|
+
// No DOM and no imports: node --test loads it as it is (tests/settings-about.test.mjs). Strings come through the
|
|
11
|
+
// translate function the caller passes (`tx`, the kit's); the keys are written out in full so the i18n audit sees them.
|
|
12
|
+
|
|
13
|
+
export const ABOUT_URL = '/api/system/about';
|
|
14
|
+
/** The filter field shows once there are more dependencies than this. */
|
|
15
|
+
export const ABOUT_FILTER_MIN = 20;
|
|
16
|
+
|
|
17
|
+
const INSTALL_KEYS = {
|
|
18
|
+
desktop: 'settings.redesign.about.install.desktop',
|
|
19
|
+
app: 'settings.redesign.about.install.app',
|
|
20
|
+
npm: 'settings.redesign.about.install.npm',
|
|
21
|
+
git: 'settings.redesign.about.install.git',
|
|
22
|
+
};
|
|
23
|
+
const BUILD_KEYS = {
|
|
24
|
+
stable: 'settings.redesign.about.channel.stable',
|
|
25
|
+
prerelease: 'settings.redesign.about.channel.prerelease',
|
|
26
|
+
dev: 'settings.redesign.about.channel.dev',
|
|
27
|
+
};
|
|
28
|
+
export const LINK_KEYS = {
|
|
29
|
+
repository: 'settings.redesign.about.link.repository',
|
|
30
|
+
releases: 'settings.redesign.about.link.releases',
|
|
31
|
+
changelog: 'settings.redesign.about.link.changelog',
|
|
32
|
+
issues: 'settings.redesign.about.link.issues',
|
|
33
|
+
website: 'settings.redesign.about.link.website',
|
|
34
|
+
docs: 'settings.redesign.about.link.docs',
|
|
35
|
+
npm: 'settings.redesign.about.link.npm',
|
|
36
|
+
license: 'settings.redesign.about.link.license',
|
|
37
|
+
discord: 'settings.redesign.about.link.discord',
|
|
38
|
+
x: 'settings.redesign.about.link.x',
|
|
39
|
+
};
|
|
40
|
+
const PACKAGE_KEYS = {
|
|
41
|
+
'neural-interface': 'settings.redesign.about.package.neural_interface',
|
|
42
|
+
'mcp-server': 'settings.redesign.about.package.mcp_server',
|
|
43
|
+
desktop: 'settings.redesign.about.package.desktop',
|
|
44
|
+
'whatsapp-connector': 'settings.redesign.about.package.whatsapp_connector',
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const NPM_NAME = /^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/i;
|
|
48
|
+
const SEP = ' · ';
|
|
49
|
+
|
|
50
|
+
const str = (value) => (typeof value === 'string' && value.trim() ? value.trim() : null);
|
|
51
|
+
const list = (value) => (Array.isArray(value) ? value : []);
|
|
52
|
+
|
|
53
|
+
/** An address the page may link to: https only. */
|
|
54
|
+
export const isExternalUrl = (url) => typeof url === 'string' && /^https:\/\/[^\s"'<>]+$/.test(url);
|
|
55
|
+
|
|
56
|
+
/** A link's address without the scheme, for the quiet line beside its name. */
|
|
57
|
+
export const linkHost = (url) => String(url || '').replace(/^https:\/\//, '').replace(/\/+$/, '');
|
|
58
|
+
|
|
59
|
+
/** A package's page on npm, or null for a name npm would not have. */
|
|
60
|
+
export const npmUrl = (name) => (typeof name === 'string' && NPM_NAME.test(name) ? `https://www.npmjs.com/package/${name}` : null);
|
|
61
|
+
|
|
62
|
+
function readDependency(dep) {
|
|
63
|
+
if (!dep || typeof dep !== 'object' || !str(dep.name)) return null;
|
|
64
|
+
return {
|
|
65
|
+
name: dep.name,
|
|
66
|
+
declared: str(dep.declared) || '',
|
|
67
|
+
version: dep.installed ? str(dep.version) : null,
|
|
68
|
+
installed: !!dep.installed && !!str(dep.version),
|
|
69
|
+
license: str(dep.license),
|
|
70
|
+
optional: !!dep.optional,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function readDependencies(deps) {
|
|
75
|
+
if (!deps || typeof deps !== 'object') return null;
|
|
76
|
+
const packages = list(deps.packages).filter((p) => p && str(p.id)).map((p) => ({
|
|
77
|
+
id: p.id,
|
|
78
|
+
name: str(p.name) || p.id,
|
|
79
|
+
onDemand: !!p.onDemand,
|
|
80
|
+
runtime: list(p.runtime).map(readDependency).filter(Boolean),
|
|
81
|
+
dev: list(p.dev).map(readDependency).filter(Boolean),
|
|
82
|
+
}));
|
|
83
|
+
const vendored = list(deps.vendored).filter((b) => b && str(b.id)).map((b) => ({
|
|
84
|
+
id: b.id,
|
|
85
|
+
label: str(b.label) || b.id,
|
|
86
|
+
version: str(b.version),
|
|
87
|
+
packages: list(b.packages).filter((p) => p && str(p.name) && str(p.version))
|
|
88
|
+
.map((p) => ({ name: p.name, declared: '', version: p.version, installed: true, license: str(p.license), optional: false })),
|
|
89
|
+
}));
|
|
90
|
+
return { packages, vendored, counts: countDependencies({ packages, vendored }) };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** How many runtime, dev and vendored dependencies a set of lists holds. */
|
|
94
|
+
export function countDependencies({ packages = [], vendored = [] } = {}) {
|
|
95
|
+
const runtime = packages.reduce((n, p) => n + p.runtime.length, 0);
|
|
96
|
+
const dev = packages.reduce((n, p) => n + p.dev.length, 0);
|
|
97
|
+
const bundled = vendored.reduce((n, b) => n + b.packages.length, 0);
|
|
98
|
+
return { runtime, dev, vendored: bundled, total: runtime + dev + bundled };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* What the page shows, from the answers it got. `about` is the body of GET /api/system/about when it answered
|
|
103
|
+
* (anything else: null); `health` and `version` are the bodies of /api/health and /api/system/version, or null.
|
|
104
|
+
* `full` is false when the About route did not answer: the page then says that a restart brings the rest.
|
|
105
|
+
*/
|
|
106
|
+
export function readAboutAnswer({ about = null, health = null, version = null } = {}) {
|
|
107
|
+
const full = !!(about && typeof about === 'object' && about.app && typeof about.app === 'object');
|
|
108
|
+
if (full) {
|
|
109
|
+
const app = about.app;
|
|
110
|
+
const install = INSTALL_KEYS[app.install] ? app.install : null;
|
|
111
|
+
const channel = app.channel === 'prerelease' ? 'prerelease' : 'stable';
|
|
112
|
+
const git = app.git && typeof app.git === 'object' ? { branch: str(app.git.branch), commit: str(app.git.commit) } : null;
|
|
113
|
+
const rt = about.runtime && typeof about.runtime === 'object' ? about.runtime : {};
|
|
114
|
+
const os = rt.os && typeof rt.os === 'object' ? rt.os : null;
|
|
115
|
+
return {
|
|
116
|
+
full: true,
|
|
117
|
+
app: {
|
|
118
|
+
version: str(app.version),
|
|
119
|
+
channel,
|
|
120
|
+
build: install === 'git' ? 'dev' : channel,
|
|
121
|
+
install,
|
|
122
|
+
git: git && (git.branch || git.commit) ? git : null,
|
|
123
|
+
description: str(app.description),
|
|
124
|
+
license: str(app.license),
|
|
125
|
+
copyright: app.copyright && str(app.copyright.years) && str(app.copyright.holder) ? { years: app.copyright.years, holder: app.copyright.holder } : null,
|
|
126
|
+
},
|
|
127
|
+
runtime: {
|
|
128
|
+
node: str(rt.node),
|
|
129
|
+
sqlite: str(rt.sqlite),
|
|
130
|
+
os: os ? { name: str(os.name), version: str(os.version), arch: str(os.arch), kernel: str(os.kernel) } : null,
|
|
131
|
+
dataHome: str(rt.dataHome),
|
|
132
|
+
port: Number.isFinite(Number(rt.port)) && Number(rt.port) > 0 ? Number(rt.port) : null,
|
|
133
|
+
},
|
|
134
|
+
links: list(about.links).filter((l) => l && LINK_KEYS[l.id] && isExternalUrl(l.url)).map((l) => ({ id: l.id, url: l.url })),
|
|
135
|
+
dependencies: readDependencies(about.dependencies),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// An older server: what /api/health and /api/system/version say.
|
|
139
|
+
const h = health && typeof health === 'object' ? health : {};
|
|
140
|
+
const v = version && typeof version === 'object' ? version : {};
|
|
141
|
+
const install = v.desktopManaged ? 'desktop' : (INSTALL_KEYS[h.install] && h.install !== 'desktop' ? h.install : null);
|
|
142
|
+
const channel = v.installedChannel === 'prerelease' ? 'prerelease' : 'stable';
|
|
143
|
+
return {
|
|
144
|
+
full: false,
|
|
145
|
+
app: {
|
|
146
|
+
version: str(h.version) || str(v.current),
|
|
147
|
+
channel,
|
|
148
|
+
build: install === 'git' ? 'dev' : channel,
|
|
149
|
+
install,
|
|
150
|
+
git: null,
|
|
151
|
+
description: null,
|
|
152
|
+
license: null,
|
|
153
|
+
copyright: null,
|
|
154
|
+
},
|
|
155
|
+
runtime: { node: null, sqlite: null, os: null, dataHome: null, port: null },
|
|
156
|
+
links: [],
|
|
157
|
+
dependencies: null,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* What the page itself knows about where it runs: inside the desktop app, the Electron and Chromium versions
|
|
163
|
+
* its window reports in the user agent (the app never changes it), and the app's own platform and processor.
|
|
164
|
+
*/
|
|
165
|
+
export function readClientRuntime({ userAgent = '', desktop = null } = {}) {
|
|
166
|
+
const ua = String(userAgent || '');
|
|
167
|
+
const electron = /\bElectron\/(\d[\w.-]*)/.exec(ua)?.[1] || null;
|
|
168
|
+
const inApp = !!desktop || !!electron;
|
|
169
|
+
return {
|
|
170
|
+
desktop: inApp,
|
|
171
|
+
electron: inApp ? electron : null,
|
|
172
|
+
chromium: inApp ? (/\bChrome\/(\d[\w.-]*)/.exec(ua)?.[1] || null) : null,
|
|
173
|
+
platform: desktop && str(desktop.platform),
|
|
174
|
+
arch: desktop && str(desktop.arch),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** "Stable", "Pre-release" or "Development build". */
|
|
179
|
+
export const buildLabel = (app, tx) => tx(BUILD_KEYS[app?.build] || BUILD_KEYS.stable);
|
|
180
|
+
|
|
181
|
+
/** "Desktop app", "npm install", "Git clone" …, or null when the server did not say. */
|
|
182
|
+
export const installLabel = (app, tx) => (INSTALL_KEYS[app?.install] ? tx(INSTALL_KEYS[app.install]) : null);
|
|
183
|
+
|
|
184
|
+
/** The install line under the version: "Git clone · Dev · 295547c". */
|
|
185
|
+
export function installLine(app, tx) {
|
|
186
|
+
const parts = [installLabel(app, tx)];
|
|
187
|
+
if (app?.git) parts.push(app.git.branch, app.git.commit);
|
|
188
|
+
return parts.filter(Boolean).join(SEP);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** The version line: "Version 2.0.5 · Stable". */
|
|
192
|
+
export function versionLine(app, tx) {
|
|
193
|
+
if (!app?.version) return buildLabel(app, tx);
|
|
194
|
+
return `${tx('settings.redesign.about.version', { version: app.version })}${SEP}${buildLabel(app, tx)}`;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** "macOS 26.1 · arm64" from the server's answer; the desktop app's platform and processor when there is none. */
|
|
198
|
+
export function osLine(runtime, client = {}) {
|
|
199
|
+
const os = runtime?.os;
|
|
200
|
+
if (os && (os.name || os.version)) return [[os.name, os.version].filter(Boolean).join(' '), os.arch].filter(Boolean).join(SEP);
|
|
201
|
+
return [client.platform, client.arch].filter(Boolean).join(SEP) || null;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** A package of the product by its id, in the page's language; its npm name otherwise. */
|
|
205
|
+
export const packageLabel = (pkg, tx) => (PACKAGE_KEYS[pkg?.id] ? tx(PACKAGE_KEYS[pkg.id]) : (pkg?.name || ''));
|
|
206
|
+
|
|
207
|
+
/** A link's name in the page's language. */
|
|
208
|
+
export const linkLabel = (link, tx) => (LINK_KEYS[link?.id] ? tx(LINK_KEYS[link.id]) : linkHost(link?.url));
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* The lists a filter leaves: every dependency whose name holds the query (case-insensitive), and the counts of
|
|
212
|
+
* what is shown. An empty query leaves everything.
|
|
213
|
+
*/
|
|
214
|
+
export function filterDependencies(deps, query = '') {
|
|
215
|
+
const q = String(query || '').trim().toLowerCase();
|
|
216
|
+
const keep = (dep) => !q || dep.name.toLowerCase().includes(q);
|
|
217
|
+
const packages = list(deps?.packages).map((p) => ({ ...p, runtime: p.runtime.filter(keep), dev: p.dev.filter(keep) }));
|
|
218
|
+
const vendored = list(deps?.vendored).map((b) => ({ ...b, packages: b.packages.filter(keep) }));
|
|
219
|
+
return { query: q, packages, vendored, counts: countDependencies({ packages, vendored }) };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* The plain-text block "Copy info" copies: version and channel, install, runtime, system, and the version of every
|
|
224
|
+
* runtime dependency and bundled library. No path, no address, nothing from a setting.
|
|
225
|
+
*/
|
|
226
|
+
export function diagnosticsText(model, client = {}, { tx }) {
|
|
227
|
+
const lines = [];
|
|
228
|
+
const app = model?.app || {};
|
|
229
|
+
const rt = model?.runtime || {};
|
|
230
|
+
lines.push(`SynaBun ${app.version || '?'} (${buildLabel(app, tx)})`);
|
|
231
|
+
const install = installLine(app, tx);
|
|
232
|
+
if (install) lines.push(`${tx('settings.redesign.about.row.install')}: ${install}`);
|
|
233
|
+
if (rt.node) lines.push(`Node.js: ${rt.node}`);
|
|
234
|
+
if (rt.sqlite) lines.push(`SQLite: ${rt.sqlite}`);
|
|
235
|
+
if (client.electron) lines.push(`Electron: ${client.electron}`);
|
|
236
|
+
if (client.chromium) lines.push(`Chromium: ${client.chromium}`);
|
|
237
|
+
const os = osLine(rt, client);
|
|
238
|
+
if (os) lines.push(`${tx('settings.redesign.about.row.os')}: ${os}`);
|
|
239
|
+
const deps = model?.dependencies;
|
|
240
|
+
if (deps) {
|
|
241
|
+
for (const pkg of deps.packages) {
|
|
242
|
+
if (!pkg.runtime.length) continue;
|
|
243
|
+
lines.push('', `${packageLabel(pkg, tx)} (${pkg.name})`);
|
|
244
|
+
for (const dep of pkg.runtime) lines.push(` ${dep.name} ${dep.installed ? dep.version : `${dep.declared} (${tx('settings.redesign.about.deps.notInstalled')})`}`);
|
|
245
|
+
}
|
|
246
|
+
if (deps.vendored.length) {
|
|
247
|
+
lines.push('', tx('settings.redesign.about.deps.vendored'));
|
|
248
|
+
for (const bundle of deps.vendored) lines.push(` ${bundle.label} ${bundle.version || '?'}`);
|
|
249
|
+
}
|
|
250
|
+
} else if (model && !model.full) {
|
|
251
|
+
lines.push('', tx('settings.redesign.about.restartNote'));
|
|
252
|
+
}
|
|
253
|
+
return lines.join('\n');
|
|
254
|
+
}
|
|
@@ -29,6 +29,7 @@ export const SETTINGS_GROUPS = [
|
|
|
29
29
|
{ id: 'tools', labelKey: k('group.tools') },
|
|
30
30
|
{ id: 'automations', labelKey: k('group.automations') },
|
|
31
31
|
{ id: 'personalize', labelKey: k('group.personalize') },
|
|
32
|
+
{ id: 'app', labelKey: k('group.app') },
|
|
32
33
|
];
|
|
33
34
|
|
|
34
35
|
/** `key` is the i18n slug under settings.redesign.{nav,page,section}; `icon` names a TAB_ICONS entry. */
|
|
@@ -183,6 +184,17 @@ export const SETTINGS_PAGES = [
|
|
|
183
184
|
{ id: 'stg-sec-2d-graph', key: 'd2_graph', state: 'advanced', variant: 'graphics' },
|
|
184
185
|
],
|
|
185
186
|
},
|
|
187
|
+
{
|
|
188
|
+
// The last page: version, links, system and dependencies (settings-about-pane.js, GET /api/system/about).
|
|
189
|
+
// Its header (icon, version, Check for updates, Copy info) is not a section: it is always shown.
|
|
190
|
+
id: 'about', key: 'about', group: 'app', icon: 'about',
|
|
191
|
+
panes: [{ id: 'about' }],
|
|
192
|
+
sections: [
|
|
193
|
+
{ id: 'stg-sec-about-links', key: 'links', state: 'open' },
|
|
194
|
+
{ id: 'stg-sec-about-system', key: 'system', state: 'open' },
|
|
195
|
+
{ id: 'stg-sec-about-dependencies', key: 'dependencies', state: 'open' },
|
|
196
|
+
],
|
|
197
|
+
},
|
|
186
198
|
];
|
|
187
199
|
|
|
188
200
|
export const DEFAULT_SETTINGS_PAGE = 'ai-connections';
|
|
@@ -278,11 +290,13 @@ export const SETTINGS_CONTROLS = {
|
|
|
278
290
|
'stg-sec-visual-tuning': 'UI003 UI004 UI005 UI006 UI007 UI008 UI009 UI010',
|
|
279
291
|
'stg-sec-file-icons': 'ICO001 ICO003 ICO002 ICO004 ICO005',
|
|
280
292
|
'stg-sec-2d-graph': 'GFX001 GFX002 GFX003 GFX004 GFX005 GFX006 GFX007 GFX008',
|
|
293
|
+
'stg-sec-about-dependencies': 'ABT003',
|
|
281
294
|
};
|
|
282
295
|
/** Controls of a page that sit outside its sections (a pane's save bar, the tabs of a pane). */
|
|
283
296
|
export const SETTINGS_PAGE_CONTROLS = {
|
|
284
297
|
browser: 'BRW081 BRW082 BRW085',
|
|
285
298
|
'connected-tools': 'MCP001',
|
|
299
|
+
about: 'ABT001 ABT002',
|
|
286
300
|
};
|
|
287
301
|
/** The window's own controls (dim the background, close, the page list): not settings, so never search results. */
|
|
288
302
|
export const SETTINGS_SHELL_CONTROLS = 'SH002 SH003 SH005';
|
|
@@ -306,6 +320,7 @@ export const homeOfControl = (controlId) => CONTROL_HOME.get(controlId) || null;
|
|
|
306
320
|
// ── Deep-link aliases ──────────────────────────────────────────────────────
|
|
307
321
|
// Old tab id → the page that took it over, and the section a link to that tab
|
|
308
322
|
// should land on. Old callers keep working; new code uses the page ids.
|
|
323
|
+
// A page that never had an old tab needs no entry: `{ tab: 'about' }` names the About page itself.
|
|
309
324
|
|
|
310
325
|
export const SETTINGS_TAB_ALIASES = {
|
|
311
326
|
server: { page: 'memory-backups', section: 'stg-sec-database' },
|