@geminilight/mindos 0.6.40 → 0.6.41
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/_standalone/.mindos-build-version +1 -1
- package/_standalone/.next/BUILD_ID +1 -1
- package/_standalone/.next/app-path-routes-manifest.json +18 -18
- package/_standalone/.next/build-manifest.json +3 -3
- package/_standalone/.next/cache/.previewinfo +1 -1
- package/_standalone/.next/cache/.rscinfo +1 -1
- package/_standalone/.next/cache/config.json +3 -3
- package/_standalone/.next/prerender-manifest.json +3 -3
- package/_standalone/.next/react-loadable-manifest.json +5 -1
- package/_standalone/.next/server/app/.well-known/agent-card.json/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/_global-error.html +2 -2
- package/_standalone/.next/server/app/_global-error.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/_standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/_standalone/.next/server/app/_not-found/page.js +1 -1
- package/_standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/agents/[agentKey]/page.js +1 -1
- package/_standalone/.next/server/app/agents/[agentKey]/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/agents/[agentKey]/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/agents/page.js +2 -2
- package/_standalone/.next/server/app/agents/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/agents/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/agents/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/delegations/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/discover/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/a2a/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/config/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/detect/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/install/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/registry/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/acp/session/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/agent-activity/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/ask/route.js +1 -1
- package/_standalone/.next/server/app/api/ask/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/ask/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/ask-sessions/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/auth/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/backlinks/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/backlinks/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/bootstrap/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/bootstrap/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/changes/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/changes/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/export/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/export/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/extract-pdf/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/file/import/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/file/import/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/file/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/file/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/graph/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/graph/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/inbox/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/inbox/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/init/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/init/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/agents/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/mcp/agents/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/install/route.js +1 -1
- package/_standalone/.next/server/app/api/mcp/install/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/install-skill/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/mcp/install-skill/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/restart/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/mcp/status/route.js +1 -1
- package/_standalone/.next/server/app/api/mcp/status/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/monitoring/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/monitoring/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/recent-files/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/recent-files/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/restart/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/search/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/settings/list-models/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/settings/reset-token/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/settings/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/settings/test-key/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/check-path/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/check-port/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/generate-token/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/ls/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/setup/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/sync/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/tree-version/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/tree-version/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/uninstall/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/update-check/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/update-status/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/api/workflows/route.js.nft.json +1 -1
- package/_standalone/.next/server/app/api/workflows/route_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/changes/page.js +1 -1
- package/_standalone/.next/server/app/changes/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/changes/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/echo/[segment]/page.js +1 -1
- package/_standalone/.next/server/app/echo/[segment]/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/echo/[segment]/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/echo/page.js +1 -1
- package/_standalone/.next/server/app/echo/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/echo/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/explore/page.js +1 -1
- package/_standalone/.next/server/app/explore/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/explore/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/help/page.js +2 -2
- package/_standalone/.next/server/app/help/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/help/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/login/page.js +1 -1
- package/_standalone/.next/server/app/login/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/page.js +2 -2
- package/_standalone/.next/server/app/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/setup/page.js +2 -2
- package/_standalone/.next/server/app/setup/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/trash/page.js +3 -3
- package/_standalone/.next/server/app/trash/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/trash/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app/view/[...path]/page.js +3 -3
- package/_standalone/.next/server/app/view/[...path]/page.js.nft.json +1 -1
- package/_standalone/.next/server/app/view/[...path]/page_client-reference-manifest.js +1 -1
- package/_standalone/.next/server/app-paths-manifest.json +18 -18
- package/_standalone/.next/server/chunks/1550.js +1 -1
- package/_standalone/.next/server/chunks/2190.js +11 -0
- package/_standalone/.next/server/chunks/{6365.js → 2536.js} +2 -2
- package/_standalone/.next/server/chunks/5648.js +2 -0
- package/_standalone/.next/server/chunks/8388.js +1 -1
- package/_standalone/.next/server/chunks/953.js +1 -1
- package/_standalone/.next/server/chunks/9539.js +219 -0
- package/_standalone/.next/server/middleware-build-manifest.js +1 -1
- package/_standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/_standalone/.next/server/next-font-manifest.js +1 -1
- package/_standalone/.next/server/next-font-manifest.json +1 -1
- package/_standalone/.next/server/pages/500.html +2 -2
- package/_standalone/.next/server/server-reference-manifest.js +1 -1
- package/_standalone/.next/server/server-reference-manifest.json +1 -1
- package/_standalone/.next/static/chunks/1053-b70535785cc5aaee.js +29 -0
- package/_standalone/.next/static/chunks/{8663-de911d2d395622be.js → 1880-c2a9e76201841c86.js} +1 -1
- package/_standalone/.next/static/chunks/3637.0541ac2d0ea7de1f.js +1 -0
- package/_standalone/.next/static/chunks/4563-b2a2ce80aff845af.js +6 -0
- package/_standalone/.next/static/chunks/6981-3d7dcac2d12a5670.js +1 -0
- package/_standalone/.next/static/chunks/7144-5febf62f1a79fe64.js +1 -0
- package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-773071a99c4daac2.js +1 -0
- package/_standalone/.next/static/chunks/app/agents/page-6102a884b2cb3cfe.js +5 -0
- package/_standalone/.next/static/chunks/app/help/page-2325d25b6846ca07.js +1 -0
- package/_standalone/.next/static/chunks/app/{layout-9378c1c8d3e5761b.js → layout-42cdbce19f404567.js} +34 -34
- package/_standalone/.next/static/chunks/app/{page-9bae420fbbdc5fff.js → page-8c9643b649e01735.js} +1 -1
- package/_standalone/.next/static/chunks/app/setup/page-d158b8cb533feb1e.js +1 -0
- package/_standalone/.next/static/chunks/app/trash/{page-b61ef2d5cd4f8d73.js → page-e9ab74ffeb96af41.js} +1 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/page-764a69a1c8bd4eef.js +12 -0
- package/_standalone/.next/static/chunks/{webpack-c28c55d0a6021a6b.js → webpack-7b276daaa930d480.js} +1 -1
- package/_standalone/.next/static/css/bc9179074eaf65ae.css +1 -0
- package/_standalone/.next/trace +63 -63
- package/_standalone/__tests__/api/mcp-install.test.ts +23 -0
- package/_standalone/__tests__/cli/agent-routing.test.ts +232 -0
- package/_standalone/__tests__/cli/file-subcommands.test.ts +379 -0
- package/_standalone/__tests__/core/tools.test.ts +3 -6
- package/_standalone/components/FileTree.tsx +3 -2
- package/_standalone/components/MarkdownView.tsx +30 -15
- package/_standalone/components/RightAskPanel.tsx +36 -6
- package/_standalone/components/Sidebar.tsx +3 -3
- package/_standalone/components/agents/AgentsMcpSection.tsx +3 -0
- package/_standalone/components/settings/McpAgentInstall.tsx +94 -27
- package/_standalone/components/settings/McpSkillsSection.tsx +1 -1
- package/_standalone/components/settings/McpTab.tsx +484 -340
- package/_standalone/components/settings/SettingsContent.tsx +12 -6
- package/_standalone/components/settings/types.ts +3 -0
- package/_standalone/components/setup/StepAgents.tsx +113 -47
- package/_standalone/components/setup/StepReview.tsx +14 -27
- package/_standalone/components/setup/types.ts +6 -0
- package/_standalone/data/skills/mindos/SKILL.md +92 -92
- package/_standalone/data/skills/mindos/references/write-supplement.md +119 -0
- package/_standalone/data/skills/mindos-zh/SKILL.md +100 -104
- package/_standalone/data/skills/mindos-zh/references/write-supplement.md +119 -0
- package/_standalone/lib/i18n/modules/features.ts +4 -4
- package/_standalone/lib/i18n/modules/knowledge.ts +4 -0
- package/_standalone/lib/i18n/modules/onboarding.ts +40 -30
- package/_standalone/lib/i18n/modules/settings.ts +78 -6
- package/_standalone/lib/mcp-snippets.ts +5 -1
- package/_standalone/tsconfig.tsbuildinfo +1 -1
- package/app/app/api/ask/route.ts +3 -2
- package/app/app/api/mcp/install/route.ts +2 -1
- package/app/app/api/mcp/status/route.ts +14 -6
- package/app/app/view/[...path]/ViewPageClient.tsx +12 -27
- package/app/components/FileTree.tsx +3 -2
- package/app/components/MarkdownView.tsx +30 -15
- package/app/components/RightAskPanel.tsx +36 -6
- package/app/components/Sidebar.tsx +3 -3
- package/app/components/agents/AgentsMcpSection.tsx +3 -0
- package/app/components/help/HelpContent.tsx +1 -0
- package/app/components/settings/McpAgentInstall.tsx +94 -27
- package/app/components/settings/McpSkillsSection.tsx +1 -1
- package/app/components/settings/McpTab.tsx +484 -340
- package/app/components/settings/SettingsContent.tsx +12 -6
- package/app/components/settings/types.ts +3 -0
- package/app/components/setup/StepAgents.tsx +113 -47
- package/app/components/setup/StepReview.tsx +14 -27
- package/app/components/setup/index.tsx +12 -11
- package/app/components/setup/types.ts +6 -0
- package/app/data/skills/mindos/SKILL.md +92 -92
- package/app/data/skills/mindos/references/write-supplement.md +119 -0
- package/app/data/skills/mindos-zh/SKILL.md +100 -104
- package/app/data/skills/mindos-zh/references/write-supplement.md +119 -0
- package/app/lib/fs.ts +0 -6
- package/app/lib/i18n/modules/features.ts +4 -4
- package/app/lib/i18n/modules/knowledge.ts +4 -0
- package/app/lib/i18n/modules/onboarding.ts +40 -30
- package/app/lib/i18n/modules/settings.ts +78 -6
- package/app/lib/mcp-agents.ts +1 -2
- package/app/lib/mcp-snippets.ts +5 -1
- package/app/lib/renderers/index.ts +2 -1
- package/bin/cli.js +168 -1404
- package/bin/commands/agent.js +156 -20
- package/bin/commands/api.js +14 -11
- package/bin/commands/ask.js +79 -68
- package/bin/commands/build.js +26 -0
- package/bin/commands/config.js +170 -0
- package/bin/commands/dev.js +58 -0
- package/bin/commands/doctor.js +205 -0
- package/bin/commands/file.js +551 -36
- package/bin/commands/gateway.js +42 -0
- package/bin/commands/init-skills.js +56 -0
- package/bin/commands/logs.js +32 -0
- package/bin/commands/mcp-cmd.js +57 -0
- package/bin/commands/onboard.js +25 -0
- package/bin/commands/open.js +41 -0
- package/bin/commands/restart.js +48 -0
- package/bin/commands/search.js +16 -14
- package/bin/commands/space.js +96 -25
- package/bin/commands/start.js +262 -0
- package/bin/commands/status.js +2 -2
- package/bin/commands/stop.js +14 -0
- package/bin/commands/sync-cmd.js +134 -0
- package/bin/commands/token.js +98 -0
- package/bin/commands/uninstall.js +154 -0
- package/bin/commands/update.js +286 -0
- package/bin/lib/build.js +1 -1
- package/bin/lib/colors.js +8 -7
- package/bin/lib/command.js +37 -96
- package/bin/lib/config.js +5 -0
- package/bin/lib/csv.js +19 -0
- package/bin/lib/jsonc.js +12 -0
- package/bin/lib/markdown.js +69 -0
- package/bin/lib/mcp-agents.js +1 -6
- package/bin/lib/mcp-build.js +1 -1
- package/bin/lib/mcp-install.js +2 -1
- package/bin/lib/one-shot.js +88 -0
- package/bin/lib/path-expand.js +9 -0
- package/bin/lib/remote.js +65 -0
- package/bin/lib/repl.js +167 -0
- package/bin/lib/{utils.js → shell.js} +10 -26
- package/bin/lib/skill-check.js +1 -1
- package/bin/lib/sse-stream.js +167 -0
- package/package.json +2 -2
- package/scripts/setup.js +182 -120
- package/skills/mindos/SKILL.md +92 -92
- package/skills/mindos-zh/SKILL.md +100 -104
- package/_standalone/.next/server/chunks/1955.js +0 -11
- package/_standalone/.next/server/chunks/3680.js +0 -1
- package/_standalone/.next/server/chunks/4497.js +0 -219
- package/_standalone/.next/server/chunks/5560.js +0 -2
- package/_standalone/.next/static/chunks/1053-0adaccc98a752a58.js +0 -29
- package/_standalone/.next/static/chunks/3637.f9a42cca59fd5bb5.js +0 -1
- package/_standalone/.next/static/chunks/4563-c2afaeacb241d1d0.js +0 -6
- package/_standalone/.next/static/chunks/6090-c98268ca726a68d3.js +0 -1
- package/_standalone/.next/static/chunks/9371-575600301da5d6bb.js +0 -1
- package/_standalone/.next/static/chunks/app/agents/[agentKey]/page-3e08abb495ecd5fd.js +0 -1
- package/_standalone/.next/static/chunks/app/agents/page-e7e0f87ad3d765ac.js +0 -5
- package/_standalone/.next/static/chunks/app/help/page-3d0e1ceaa4abc243.js +0 -1
- package/_standalone/.next/static/chunks/app/setup/page-99ed3d1bb6b8f4ef.js +0 -1
- package/_standalone/.next/static/chunks/app/view/[...path]/page-44fa78cbea613a78.js +0 -12
- package/_standalone/.next/static/css/d300701f384db50d.css +0 -1
- package/_standalone/components/renderers/agent-inspector/manifest.ts +0 -16
- /package/_standalone/.next/static/{rZLs1krFuduixvcVNe6q3 → Ij3PFh-a0zi5K_ANoSAW0}/_buildManifest.js +0 -0
- /package/_standalone/.next/static/{rZLs1krFuduixvcVNe6q3 → Ij3PFh-a0zi5K_ANoSAW0}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mindos update — npm install latest, sync skills, rebuild, restart daemon or foreground instance.
|
|
3
|
+
*
|
|
4
|
+
* Heavy dependencies are loaded on demand to keep CLI cold start fast.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { execSync, spawn as nodeSpawn } from 'node:child_process';
|
|
8
|
+
import { existsSync, readFileSync, writeFileSync, rmSync } from 'node:fs';
|
|
9
|
+
import { dirname, resolve } from 'node:path';
|
|
10
|
+
|
|
11
|
+
import { ROOT, BUILD_STAMP, CONFIG_PATH, LOG_PATH } from '../lib/constants.js';
|
|
12
|
+
import { bold, dim, cyan, green, red, yellow } from '../lib/colors.js';
|
|
13
|
+
import { execInherited } from '../lib/shell.js';
|
|
14
|
+
import { EXIT } from '../lib/command.js';
|
|
15
|
+
import { stopMindos } from '../lib/stop.js';
|
|
16
|
+
import { getLocalIP } from '../lib/startup.js';
|
|
17
|
+
import { isPortInUse } from '../lib/port.js';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Dynamically resolve the new ROOT after `npm install -g`.
|
|
21
|
+
* This is needed because constants are evaluated at module load time.
|
|
22
|
+
*/
|
|
23
|
+
function getUpdatedRoot() {
|
|
24
|
+
try {
|
|
25
|
+
const mindosBin = execSync('which mindos', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
|
|
26
|
+
if (mindosBin) {
|
|
27
|
+
// mindos bin is usually at <root>/bin/cli.js or a symlink to it
|
|
28
|
+
let cliPath;
|
|
29
|
+
try {
|
|
30
|
+
cliPath = execSync(`readlink -f "${mindosBin}"`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
|
|
31
|
+
} catch {
|
|
32
|
+
try {
|
|
33
|
+
cliPath = execSync(`realpath "${mindosBin}"`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
|
|
34
|
+
} catch {
|
|
35
|
+
cliPath = mindosBin;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (cliPath) {
|
|
39
|
+
// cliPath is like /path/to/node_modules/@geminilight/mindos/bin/cli.js
|
|
40
|
+
// ROOT is /path/to/node_modules/@geminilight/mindos
|
|
41
|
+
return resolve(dirname(cliPath), '..');
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
} catch {}
|
|
45
|
+
// Fallback to static ROOT
|
|
46
|
+
return ROOT;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Build the app in the given root if the build stamp doesn't match the package version.
|
|
51
|
+
* Used by `mindos update` to pre-build before restarting the daemon.
|
|
52
|
+
* @param {string} newRoot
|
|
53
|
+
*/
|
|
54
|
+
function buildIfNeeded(newRoot) {
|
|
55
|
+
// Check for prebuilt standalone first (npm package ships with it)
|
|
56
|
+
const standaloneServer = resolve(newRoot, '_standalone', 'server.js');
|
|
57
|
+
const standaloneStamp = resolve(newRoot, '_standalone', '.mindos-build-version');
|
|
58
|
+
if (existsSync(standaloneServer)) {
|
|
59
|
+
try {
|
|
60
|
+
const builtVersion = readFileSync(standaloneStamp, 'utf-8').trim();
|
|
61
|
+
const pkgVersion = JSON.parse(readFileSync(resolve(newRoot, 'package.json'), 'utf-8')).version;
|
|
62
|
+
if (builtVersion === pkgVersion) return; // prebuilt standalone matches, no build needed
|
|
63
|
+
} catch { /* fall through to legacy build */ }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const newBuildStamp = resolve(newRoot, 'app', '.next', '.mindos-build-version');
|
|
67
|
+
const newNextBin = resolve(newRoot, 'app', 'node_modules', '.bin', 'next');
|
|
68
|
+
|
|
69
|
+
let needBuild = true;
|
|
70
|
+
try {
|
|
71
|
+
const builtVersion = readFileSync(newBuildStamp, 'utf-8').trim();
|
|
72
|
+
const pkgVersion = JSON.parse(readFileSync(resolve(newRoot, 'package.json'), 'utf-8')).version;
|
|
73
|
+
needBuild = builtVersion !== pkgVersion;
|
|
74
|
+
} catch {
|
|
75
|
+
needBuild = true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!needBuild) return;
|
|
79
|
+
|
|
80
|
+
console.log(yellow('\n Building MindOS (version change detected)...\n'));
|
|
81
|
+
const appPkg = resolve(newRoot, 'app', 'package.json');
|
|
82
|
+
if (existsSync(appPkg)) {
|
|
83
|
+
execInherited('npm install', resolve(newRoot, 'app'));
|
|
84
|
+
}
|
|
85
|
+
const nextDir = resolve(newRoot, 'app', '.next');
|
|
86
|
+
if (existsSync(nextDir)) {
|
|
87
|
+
execInherited(`rm -rf "${nextDir}"`, newRoot);
|
|
88
|
+
}
|
|
89
|
+
execInherited('node scripts/gen-renderer-index.js', newRoot);
|
|
90
|
+
execInherited(`${newNextBin} build`, resolve(newRoot, 'app'));
|
|
91
|
+
const version = JSON.parse(readFileSync(resolve(newRoot, 'package.json'), 'utf-8')).version;
|
|
92
|
+
writeFileSync(newBuildStamp, version, 'utf-8');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const meta = {
|
|
96
|
+
name: 'update',
|
|
97
|
+
group: 'Config',
|
|
98
|
+
summary: 'Update to latest version',
|
|
99
|
+
usage: 'mindos update',
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export const run = async () => {
|
|
103
|
+
const { writeUpdateStatus, writeUpdateFailed } = await import('../lib/update-status.js');
|
|
104
|
+
const currentVersion = (() => {
|
|
105
|
+
try { return JSON.parse(readFileSync(resolve(ROOT, 'package.json'), 'utf-8')).version; } catch { return '?'; }
|
|
106
|
+
})();
|
|
107
|
+
console.log(`\n${bold('⬆ Updating MindOS...')} ${dim(`(current: ${currentVersion})`)}\n`);
|
|
108
|
+
|
|
109
|
+
// Stage 1: Download
|
|
110
|
+
writeUpdateStatus('downloading', { fromVersion: currentVersion });
|
|
111
|
+
try {
|
|
112
|
+
execSync('npm install -g @geminilight/mindos@latest', { stdio: 'inherit' });
|
|
113
|
+
} catch {
|
|
114
|
+
writeUpdateFailed('downloading', 'npm install failed', { fromVersion: currentVersion });
|
|
115
|
+
console.error(red('Update failed. Try: npm install -g @geminilight/mindos@latest'));
|
|
116
|
+
process.exit(EXIT.ERROR);
|
|
117
|
+
}
|
|
118
|
+
if (existsSync(BUILD_STAMP)) rmSync(BUILD_STAMP);
|
|
119
|
+
|
|
120
|
+
// Resolve the new installation path (after npm install -g, ROOT is stale)
|
|
121
|
+
const updatedRoot = getUpdatedRoot();
|
|
122
|
+
const newVersion = (() => {
|
|
123
|
+
try { return JSON.parse(readFileSync(resolve(updatedRoot, 'package.json'), 'utf-8')).version; } catch { return '?'; }
|
|
124
|
+
})();
|
|
125
|
+
const vOpts = { fromVersion: currentVersion, toVersion: newVersion };
|
|
126
|
+
|
|
127
|
+
// Stage 2: Skills
|
|
128
|
+
writeUpdateStatus('skills', vOpts);
|
|
129
|
+
try {
|
|
130
|
+
const { checkSkillVersions, updateSkill } = await import('../lib/skill-check.js');
|
|
131
|
+
const mismatches = checkSkillVersions(updatedRoot);
|
|
132
|
+
for (const m of mismatches) {
|
|
133
|
+
updateSkill(m.bundledPath, m.installPath);
|
|
134
|
+
console.log(` ${green('✓')} ${dim(`Skill ${m.name}: v${m.installed} → v${m.bundled}`)}`);
|
|
135
|
+
}
|
|
136
|
+
} catch { /* best-effort */ }
|
|
137
|
+
|
|
138
|
+
if (newVersion !== currentVersion) {
|
|
139
|
+
console.log(`\n${green(`✔ Updated ${currentVersion} → ${newVersion}`)}`);
|
|
140
|
+
} else {
|
|
141
|
+
console.log(`\n${green('✔ Already on the latest version')} ${dim(`(${currentVersion})`)}\n`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const gateway = await import('../lib/gateway.js');
|
|
146
|
+
const updatePlatform = await gateway.getPlatform();
|
|
147
|
+
let daemonRunning = false;
|
|
148
|
+
if (updatePlatform === 'systemd') {
|
|
149
|
+
try { execSync('systemctl --user is-active mindos', { stdio: 'pipe' }); daemonRunning = true; } catch {}
|
|
150
|
+
} else if (updatePlatform === 'launchd') {
|
|
151
|
+
try {
|
|
152
|
+
const uid = execSync('id -u').toString().trim();
|
|
153
|
+
execSync(`launchctl print gui/${uid}/com.mindos.app`, { stdio: 'pipe' });
|
|
154
|
+
daemonRunning = true;
|
|
155
|
+
} catch {}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (daemonRunning) {
|
|
159
|
+
console.log(cyan('\n Daemon is running — stopping to apply the new version...'));
|
|
160
|
+
await gateway.runGatewayCommand('stop');
|
|
161
|
+
|
|
162
|
+
// Stage 3: Rebuild
|
|
163
|
+
writeUpdateStatus('rebuilding', vOpts);
|
|
164
|
+
let daemonBuildFailed = '';
|
|
165
|
+
try {
|
|
166
|
+
buildIfNeeded(updatedRoot);
|
|
167
|
+
} catch (err) {
|
|
168
|
+
daemonBuildFailed = err instanceof Error ? err.message : String(err);
|
|
169
|
+
console.error(yellow(`\n Pre-build failed: ${daemonBuildFailed}`));
|
|
170
|
+
console.error(yellow(' Daemon will attempt to rebuild on startup...\n'));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Stage 4: Restart — always attempt, even if pre-build failed
|
|
174
|
+
// (daemon has auto-restart; `mindos start` retries the build)
|
|
175
|
+
writeUpdateStatus('restarting', vOpts);
|
|
176
|
+
await gateway.runGatewayCommand('install');
|
|
177
|
+
const updateConfig = (() => {
|
|
178
|
+
try { return JSON.parse(readFileSync(CONFIG_PATH, 'utf-8')); } catch { return {}; }
|
|
179
|
+
})();
|
|
180
|
+
const webPort = updateConfig.port ?? 3456;
|
|
181
|
+
const mcpPort = updateConfig.mcpPort ?? 8781;
|
|
182
|
+
console.log(dim(' (Waiting for Web UI to come back up — first run after update includes a rebuild...)'));
|
|
183
|
+
const ready = await gateway.waitForHttp(Number(webPort), { retries: 450, intervalMs: 2000, label: 'Web UI', logFile: LOG_PATH });
|
|
184
|
+
if (ready) {
|
|
185
|
+
const localIP = getLocalIP();
|
|
186
|
+
console.log(`\n${'─'.repeat(53)}`);
|
|
187
|
+
console.log(`${green('✔')} ${bold(`MindOS updated: ${currentVersion} → ${newVersion}`)}\n`);
|
|
188
|
+
console.log(` ${green('●')} Web UI ${cyan(`http://localhost:${webPort}`)}`);
|
|
189
|
+
if (localIP) console.log(` ${cyan(`http://${localIP}:${webPort}`)}`);
|
|
190
|
+
console.log(` ${green('●')} MCP ${cyan(`http://localhost:${mcpPort}/mcp`)}`);
|
|
191
|
+
console.log(`\n ${dim('View changelog:')} ${cyan('https://github.com/GeminiLight/MindOS/releases')}`);
|
|
192
|
+
console.log(`${'─'.repeat(53)}\n`);
|
|
193
|
+
writeUpdateStatus('done', vOpts);
|
|
194
|
+
} else {
|
|
195
|
+
const failMsg = daemonBuildFailed
|
|
196
|
+
? `Build failed (${daemonBuildFailed}), server did not come back up`
|
|
197
|
+
: 'Server did not come back up in time';
|
|
198
|
+
writeUpdateFailed('restarting', failMsg, vOpts);
|
|
199
|
+
console.error(red(`✘ ${failMsg}. Check logs: mindos logs\n`));
|
|
200
|
+
process.exit(EXIT.ERROR);
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
// Non-daemon mode: check if a MindOS instance is currently running
|
|
204
|
+
// (e.g. user started via `mindos start`, or GUI triggered this update).
|
|
205
|
+
// If so, stop it and restart from the NEW installation path.
|
|
206
|
+
const updateConfig = (() => {
|
|
207
|
+
try { return JSON.parse(readFileSync(CONFIG_PATH, 'utf-8')); } catch { return {}; }
|
|
208
|
+
})();
|
|
209
|
+
const webPort = Number(updateConfig.port ?? 3456);
|
|
210
|
+
const mcpPort = Number(updateConfig.mcpPort ?? 8781);
|
|
211
|
+
|
|
212
|
+
const wasRunning = await isPortInUse(webPort) || await isPortInUse(mcpPort);
|
|
213
|
+
|
|
214
|
+
if (wasRunning) {
|
|
215
|
+
console.log(cyan('\n MindOS is running — restarting to apply the new version...'));
|
|
216
|
+
stopMindos();
|
|
217
|
+
// Wait for ports to free (up to 15s)
|
|
218
|
+
const deadline = Date.now() + 15_000;
|
|
219
|
+
while (Date.now() < deadline) {
|
|
220
|
+
const busy = await isPortInUse(webPort) || await isPortInUse(mcpPort);
|
|
221
|
+
if (!busy) break;
|
|
222
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Stage 3: Rebuild
|
|
226
|
+
writeUpdateStatus('rebuilding', vOpts);
|
|
227
|
+
let buildFailed = '';
|
|
228
|
+
try {
|
|
229
|
+
buildIfNeeded(updatedRoot);
|
|
230
|
+
} catch (err) {
|
|
231
|
+
buildFailed = err instanceof Error ? err.message : String(err);
|
|
232
|
+
console.error(yellow(`\n Pre-build failed: ${buildFailed}`));
|
|
233
|
+
console.error(yellow(' Starting server anyway (it will retry the build)...\n'));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Stage 4: Restart — always attempt, even if pre-build failed
|
|
237
|
+
// (`mindos start` has its own build-on-startup logic)
|
|
238
|
+
writeUpdateStatus('restarting', vOpts);
|
|
239
|
+
const newCliPath = resolve(updatedRoot, 'bin', 'cli.js');
|
|
240
|
+
const childEnv = { ...process.env };
|
|
241
|
+
delete childEnv.MINDOS_WEB_PORT;
|
|
242
|
+
delete childEnv.MINDOS_MCP_PORT;
|
|
243
|
+
delete childEnv.MIND_ROOT;
|
|
244
|
+
delete childEnv.AUTH_TOKEN;
|
|
245
|
+
delete childEnv.WEB_PASSWORD;
|
|
246
|
+
const child = nodeSpawn(
|
|
247
|
+
process.execPath, [newCliPath, 'start'],
|
|
248
|
+
{ detached: true, stdio: 'ignore', env: childEnv },
|
|
249
|
+
);
|
|
250
|
+
child.unref();
|
|
251
|
+
|
|
252
|
+
console.log(dim(' (Waiting for Web UI to come back up...)'));
|
|
253
|
+
const ready = await gateway.waitForHttp(webPort, { retries: 180, intervalMs: 2000, label: 'Web UI', logFile: LOG_PATH });
|
|
254
|
+
if (ready) {
|
|
255
|
+
const localIP = getLocalIP();
|
|
256
|
+
console.log(`\n${'─'.repeat(53)}`);
|
|
257
|
+
console.log(`${green('✔')} ${bold(`MindOS updated: ${currentVersion} → ${newVersion}`)}\n`);
|
|
258
|
+
console.log(` ${green('●')} Web UI ${cyan(`http://localhost:${webPort}`)}`);
|
|
259
|
+
if (localIP) console.log(` ${cyan(`http://${localIP}:${webPort}`)}`);
|
|
260
|
+
console.log(` ${green('●')} MCP ${cyan(`http://localhost:${mcpPort}/mcp`)}`);
|
|
261
|
+
console.log(`\n ${dim('View changelog:')} ${cyan('https://github.com/GeminiLight/MindOS/releases')}`);
|
|
262
|
+
console.log(`${'─'.repeat(53)}\n`);
|
|
263
|
+
writeUpdateStatus('done', vOpts);
|
|
264
|
+
} else {
|
|
265
|
+
const failMsg = buildFailed
|
|
266
|
+
? `Build failed (${buildFailed}), server did not come back up`
|
|
267
|
+
: 'Server did not come back up in time';
|
|
268
|
+
writeUpdateFailed('restarting', failMsg, vOpts);
|
|
269
|
+
console.error(red(`✘ ${failMsg}. Check logs: mindos logs\n`));
|
|
270
|
+
process.exit(EXIT.ERROR);
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
// No running instance — just build and tell user to start manually
|
|
274
|
+
try {
|
|
275
|
+
buildIfNeeded(updatedRoot);
|
|
276
|
+
} catch (err) {
|
|
277
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
278
|
+
console.error(yellow(`\n Pre-build failed: ${msg}`));
|
|
279
|
+
console.error(dim(' The build will be retried when you run `mindos start`.'));
|
|
280
|
+
}
|
|
281
|
+
console.log(`\n${green('✔')} ${bold(`Updated: ${currentVersion} → ${newVersion}`)}`);
|
|
282
|
+
console.log(dim(' Run `mindos start` to start the updated version.'));
|
|
283
|
+
console.log(` ${dim('View changelog:')} ${cyan('https://github.com/GeminiLight/MindOS/releases')}\n`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
};
|
package/bin/lib/build.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createHash } from 'node:crypto';
|
|
|
4
4
|
import { resolve } from 'node:path';
|
|
5
5
|
import { ROOT, BUILD_STAMP, DEPS_STAMP, STANDALONE_SERVER, STANDALONE_STAMP } from './constants.js';
|
|
6
6
|
import { red, dim, yellow } from './colors.js';
|
|
7
|
-
import { run, npmInstall } from './
|
|
7
|
+
import { execInherited as run, npmInstall } from './shell.js';
|
|
8
8
|
|
|
9
9
|
export function needsBuild() {
|
|
10
10
|
// Prefer prebuilt standalone shipped with the npm package.
|
package/bin/lib/colors.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
const noColor = 'NO_COLOR' in process.env;
|
|
2
2
|
const forceColor = process.env.FORCE_COLOR !== undefined && process.env.FORCE_COLOR !== '0';
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
export const
|
|
6
|
-
export const
|
|
7
|
-
export const
|
|
8
|
-
export const
|
|
9
|
-
export const
|
|
3
|
+
const _tty = noColor ? false : (forceColor || process.stdout.isTTY);
|
|
4
|
+
export function isTTY() { return _tty; }
|
|
5
|
+
export const bold = (s) => _tty ? `\x1b[1m${s}\x1b[0m` : s;
|
|
6
|
+
export const dim = (s) => _tty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
7
|
+
export const cyan = (s) => _tty ? `\x1b[36m${s}\x1b[0m` : s;
|
|
8
|
+
export const green = (s) => _tty ? `\x1b[32m${s}\x1b[0m` : s;
|
|
9
|
+
export const red = (s) => _tty ? `\x1b[31m${s}\x1b[0m` : s;
|
|
10
|
+
export const yellow = (s) => _tty ? `\x1b[33m${s}\x1b[0m` : s;
|
package/bin/lib/command.js
CHANGED
|
@@ -1,59 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lightweight
|
|
2
|
+
* Lightweight CLI utilities — zero dependencies beyond lib/.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* meta.flags — { flag: description } (optional)
|
|
11
|
-
* run(args, flags) — async handler
|
|
4
|
+
* Exports used by cli.js and bin/commands/*.js:
|
|
5
|
+
* parseArgs(argv) — parse process.argv into { command, args, flags }
|
|
6
|
+
* printCommandHelp(cmd) — auto-generate --help output from cmd.meta
|
|
7
|
+
* output(data, flags) — print human-readable or JSON
|
|
8
|
+
* isJsonMode(flags) — check --json flag
|
|
9
|
+
* EXIT — standardized exit codes
|
|
12
10
|
*/
|
|
13
11
|
|
|
14
|
-
import { bold, dim, cyan
|
|
15
|
-
import { ROOT } from './constants.js';
|
|
16
|
-
import { readFileSync } from 'node:fs';
|
|
17
|
-
import { resolve } from 'node:path';
|
|
12
|
+
import { bold, dim, cyan } from './colors.js';
|
|
18
13
|
|
|
19
14
|
// ── Exit codes ────────────────────────────────────────────────────────────────
|
|
20
|
-
// Standardized exit codes for CLI commands. Use these instead of raw numbers.
|
|
21
15
|
export const EXIT = {
|
|
22
|
-
OK: 0,
|
|
23
|
-
ERROR: 1,
|
|
24
|
-
ARGS: 2,
|
|
25
|
-
CONNECT: 3,
|
|
26
|
-
NOT_FOUND: 4,
|
|
16
|
+
OK: 0,
|
|
17
|
+
ERROR: 1,
|
|
18
|
+
ARGS: 2,
|
|
19
|
+
CONNECT: 3,
|
|
20
|
+
NOT_FOUND: 4,
|
|
27
21
|
};
|
|
28
22
|
|
|
29
|
-
|
|
30
|
-
const registry = new Map();
|
|
23
|
+
// ── Arg parsing ───────────────────────────────────────────────────────────────
|
|
31
24
|
|
|
32
|
-
/**
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
registry.set(meta.name, { meta, run });
|
|
38
|
-
if (meta.aliases) {
|
|
39
|
-
for (const alias of meta.aliases) {
|
|
40
|
-
aliases.set(alias, meta.name);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function resolve_command(name) {
|
|
46
|
-
if (registry.has(name)) return registry.get(name);
|
|
47
|
-
const primary = aliases.get(name);
|
|
48
|
-
if (primary) return registry.get(primary);
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function getAllCommands() {
|
|
53
|
-
return [...registry.values()];
|
|
25
|
+
/** Parse process.argv into { command, args, flags } */
|
|
26
|
+
function looksLikeFlag(s) {
|
|
27
|
+
if (!s || s.length < 2) return false;
|
|
28
|
+
if (s.startsWith('--')) return true;
|
|
29
|
+
return s.length === 2 && s[0] === '-' && /[a-zA-Z]/.test(s[1]);
|
|
54
30
|
}
|
|
55
31
|
|
|
56
|
-
/** Parse process.argv into { command, args, flags } */
|
|
57
32
|
export function parseArgs(argv = process.argv.slice(2)) {
|
|
58
33
|
const flags = {};
|
|
59
34
|
const args = [];
|
|
@@ -63,17 +38,22 @@ export function parseArgs(argv = process.argv.slice(2)) {
|
|
|
63
38
|
const arg = argv[i];
|
|
64
39
|
if (arg.startsWith('--')) {
|
|
65
40
|
const key = arg.slice(2);
|
|
66
|
-
|
|
67
|
-
|
|
41
|
+
if (i + 1 < argv.length && !looksLikeFlag(argv[i + 1])) {
|
|
42
|
+
flags[key] = argv[i + 1];
|
|
43
|
+
i += 2;
|
|
44
|
+
} else {
|
|
45
|
+
flags[key] = true;
|
|
46
|
+
i++;
|
|
47
|
+
}
|
|
48
|
+
} else if (arg.startsWith('-') && arg.length === 2 && /[a-zA-Z]/.test(arg[1])) {
|
|
49
|
+
const key = arg.slice(1);
|
|
50
|
+
if (i + 1 < argv.length && !looksLikeFlag(argv[i + 1])) {
|
|
68
51
|
flags[key] = argv[i + 1];
|
|
69
52
|
i += 2;
|
|
70
53
|
} else {
|
|
71
54
|
flags[key] = true;
|
|
72
55
|
i++;
|
|
73
56
|
}
|
|
74
|
-
} else if (arg.startsWith('-') && arg.length === 2) {
|
|
75
|
-
flags[arg.slice(1)] = true;
|
|
76
|
-
i++;
|
|
77
57
|
} else {
|
|
78
58
|
args.push(arg);
|
|
79
59
|
i++;
|
|
@@ -83,12 +63,12 @@ export function parseArgs(argv = process.argv.slice(2)) {
|
|
|
83
63
|
return { command: args[0] || null, args: args.slice(1), flags };
|
|
84
64
|
}
|
|
85
65
|
|
|
86
|
-
|
|
66
|
+
// ── Output helpers ────────────────────────────────────────────────────────────
|
|
67
|
+
|
|
87
68
|
export function isJsonMode(flags) {
|
|
88
69
|
return flags.json === true;
|
|
89
70
|
}
|
|
90
71
|
|
|
91
|
-
/** Output helper: human-readable or JSON */
|
|
92
72
|
export function output(data, flags) {
|
|
93
73
|
if (isJsonMode(flags)) {
|
|
94
74
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -99,56 +79,17 @@ export function output(data, flags) {
|
|
|
99
79
|
}
|
|
100
80
|
}
|
|
101
81
|
|
|
102
|
-
|
|
103
|
-
export function printHelp() {
|
|
104
|
-
const pkgVersion = (() => {
|
|
105
|
-
try {
|
|
106
|
-
return JSON.parse(readFileSync(resolve(ROOT, 'package.json'), 'utf-8')).version;
|
|
107
|
-
} catch { return '?'; }
|
|
108
|
-
})();
|
|
109
|
-
|
|
110
|
-
const row = (c, d) => ` ${cyan(c.padEnd(38))}${dim(d)}`;
|
|
111
|
-
|
|
112
|
-
const groups = {};
|
|
113
|
-
for (const { meta } of registry.values()) {
|
|
114
|
-
const group = meta.group || 'Other';
|
|
115
|
-
if (!groups[group]) groups[group] = [];
|
|
116
|
-
const usage = meta.usage || `mindos ${meta.name}`;
|
|
117
|
-
groups[group].push(row(usage, meta.summary));
|
|
118
|
-
}
|
|
82
|
+
// ── Command-specific help (auto-generated from meta) ──────────────────────────
|
|
119
83
|
|
|
120
|
-
const sections = [];
|
|
121
|
-
const groupOrder = ['Core', 'Knowledge', 'MCP', 'Sync', 'Gateway', 'Config'];
|
|
122
|
-
for (const g of groupOrder) {
|
|
123
|
-
if (groups[g]) {
|
|
124
|
-
sections.push(`${bold(`${g}:`)}\n${groups[g].join('\n')}`);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
// Any remaining groups
|
|
128
|
-
for (const [g, items] of Object.entries(groups)) {
|
|
129
|
-
if (!groupOrder.includes(g)) {
|
|
130
|
-
sections.push(`${bold(`${g}:`)}\n${items.join('\n')}`);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
console.log(`
|
|
135
|
-
${bold('MindOS CLI')} ${dim(`v${pkgVersion}`)}
|
|
136
|
-
|
|
137
|
-
${sections.join('\n\n')}
|
|
138
|
-
|
|
139
|
-
${bold('Global Flags:')}
|
|
140
|
-
${cyan('--json'.padEnd(38))}${dim('Output in JSON format (for agents)')}
|
|
141
|
-
${cyan('--help, -h'.padEnd(38))}${dim('Show help')}
|
|
142
|
-
${cyan('--version, -v'.padEnd(38))}${dim('Show version')}
|
|
143
|
-
`);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/** Print command-specific help */
|
|
147
84
|
export function printCommandHelp(cmd) {
|
|
148
85
|
const { meta } = cmd;
|
|
149
86
|
const usage = meta.usage || `mindos ${meta.name}`;
|
|
150
|
-
console.log(`\n${bold(
|
|
87
|
+
console.log(`\n${bold('USAGE')}`);
|
|
88
|
+
console.log(` ${cyan(usage)}\n`);
|
|
151
89
|
console.log(` ${meta.summary}\n`);
|
|
90
|
+
if (meta.aliases && meta.aliases.length > 0) {
|
|
91
|
+
console.log(`${bold('Aliases:')} ${meta.aliases.join(', ')}\n`);
|
|
92
|
+
}
|
|
152
93
|
if (meta.flags) {
|
|
153
94
|
console.log(`${bold('Flags:')}`);
|
|
154
95
|
for (const [flag, desc] of Object.entries(meta.flags)) {
|
package/bin/lib/config.js
CHANGED
|
@@ -23,8 +23,13 @@ export function loadConfig() {
|
|
|
23
23
|
set('MINDOS_WEB_PORT', config.port);
|
|
24
24
|
set('MINDOS_MCP_PORT', config.mcpPort);
|
|
25
25
|
set('AUTH_TOKEN', config.authToken);
|
|
26
|
+
set('MINDOS_AUTH_TOKEN', config.authToken);
|
|
26
27
|
set('WEB_PASSWORD', config.webPassword);
|
|
27
28
|
set('AI_PROVIDER', config.ai?.provider);
|
|
29
|
+
// Remote URL: allows CLI to operate against a remote MindOS instance
|
|
30
|
+
if (config.url && !process.env.MINDOS_URL) {
|
|
31
|
+
process.env.MINDOS_URL = String(config.url);
|
|
32
|
+
}
|
|
28
33
|
|
|
29
34
|
const providers = config.ai?.providers;
|
|
30
35
|
if (providers) {
|
package/bin/lib/csv.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSV utility functions for CLI.
|
|
3
|
+
* Port of app/lib/core/csv.ts logic (RFC 4180 escaping).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Escape and join values into a single CSV row string.
|
|
8
|
+
* Follows RFC 4180: quote fields containing comma, double-quote, or newline.
|
|
9
|
+
* @param {string[]} row
|
|
10
|
+
* @returns {string} escaped CSV line (without trailing newline)
|
|
11
|
+
*/
|
|
12
|
+
export function escapeCsvRow(row) {
|
|
13
|
+
return row.map(cell => {
|
|
14
|
+
if (cell.includes(',') || cell.includes('"') || cell.includes('\n')) {
|
|
15
|
+
return `"${cell.replace(/"/g, '""')}"`;
|
|
16
|
+
}
|
|
17
|
+
return cell;
|
|
18
|
+
}).join(',');
|
|
19
|
+
}
|
package/bin/lib/jsonc.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSONC parser — strips comments before JSON.parse.
|
|
3
|
+
*
|
|
4
|
+
* VS Code-based editors (Cursor, Windsurf, Cline) use JSONC for config files.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const parseJsonc = (text) => {
|
|
8
|
+
let stripped = text.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*$)/gm, (m, g) => g ? '' : m);
|
|
9
|
+
stripped = stripped.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
10
|
+
if (!stripped.trim()) return {};
|
|
11
|
+
return JSON.parse(stripped);
|
|
12
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure Markdown section manipulation functions.
|
|
3
|
+
* Port of app/lib/core/lines.ts logic for CLI use (no server needed).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Finds the line index of a heading in a lines array.
|
|
8
|
+
* Matches both exact ("## Foo") and bare ("Foo" matching "## Foo").
|
|
9
|
+
* @returns -1 if not found
|
|
10
|
+
*/
|
|
11
|
+
export function findHeadingIndex(lines, heading) {
|
|
12
|
+
const bare = heading.replace(/^#+\s*/, '');
|
|
13
|
+
return lines.findIndex(l => {
|
|
14
|
+
const trimmed = l.trim();
|
|
15
|
+
return trimmed === heading || trimmed.replace(/^#+\s*/, '') === bare;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Replace the body of a markdown section (heading → next same/higher-level heading).
|
|
21
|
+
* @returns new full content, or null if heading not found
|
|
22
|
+
*/
|
|
23
|
+
export function replaceSection(content, heading, newBody) {
|
|
24
|
+
const lines = content.split('\n');
|
|
25
|
+
const idx = findHeadingIndex(lines, heading);
|
|
26
|
+
if (idx === -1) return null;
|
|
27
|
+
|
|
28
|
+
const headingLevel = (lines[idx].match(/^#+/) ?? [''])[0].length;
|
|
29
|
+
let sectionEnd = lines.length - 1;
|
|
30
|
+
for (let i = idx + 1; i < lines.length; i++) {
|
|
31
|
+
const m = lines[i].match(/^(#+)\s/);
|
|
32
|
+
if (m && m[1].length <= headingLevel) {
|
|
33
|
+
sectionEnd = i - 1;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
while (sectionEnd > idx && lines[sectionEnd].trim() === '') sectionEnd--;
|
|
38
|
+
|
|
39
|
+
const before = lines.slice(0, idx + 1);
|
|
40
|
+
const after = lines.slice(sectionEnd + 1);
|
|
41
|
+
return [...before, '', newBody, ...after].join('\n');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Insert content after a markdown heading (before existing body).
|
|
46
|
+
* @returns new full content, or null if heading not found
|
|
47
|
+
*/
|
|
48
|
+
export function insertAfterHeading(content, heading, insertion) {
|
|
49
|
+
const lines = content.split('\n');
|
|
50
|
+
const idx = findHeadingIndex(lines, heading);
|
|
51
|
+
if (idx === -1) return null;
|
|
52
|
+
|
|
53
|
+
let insertAt = idx + 1;
|
|
54
|
+
while (insertAt < lines.length && lines[insertAt].trim() === '') insertAt++;
|
|
55
|
+
|
|
56
|
+
const before = lines.slice(0, insertAt);
|
|
57
|
+
const after = lines.slice(insertAt);
|
|
58
|
+
return [...before, '', insertion, ...after].join('\n');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Extract all headings from markdown content.
|
|
63
|
+
* @returns array of heading lines (e.g., ["## A", "### B"])
|
|
64
|
+
*/
|
|
65
|
+
export function listHeadings(content) {
|
|
66
|
+
return content.split('\n')
|
|
67
|
+
.filter(l => /^#{1,6}\s/.test(l))
|
|
68
|
+
.map(l => l.trim());
|
|
69
|
+
}
|
package/bin/lib/mcp-agents.js
CHANGED
|
@@ -8,13 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { existsSync } from 'node:fs';
|
|
11
|
-
import { resolve } from 'node:path';
|
|
12
|
-
import { homedir } from 'node:os';
|
|
13
11
|
import { execSync } from 'node:child_process';
|
|
14
|
-
|
|
15
|
-
function expandHome(p) {
|
|
16
|
-
return p.startsWith('~/') ? resolve(homedir(), p.slice(2)) : p;
|
|
17
|
-
}
|
|
12
|
+
import { expandHome } from './path-expand.js';
|
|
18
13
|
|
|
19
14
|
export const MCP_AGENTS = {
|
|
20
15
|
'claude-code': {
|
package/bin/lib/mcp-build.js
CHANGED
|
@@ -2,7 +2,7 @@ import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { ROOT } from './constants.js';
|
|
4
4
|
import { yellow } from './colors.js';
|
|
5
|
-
import { run, npmInstall } from './
|
|
5
|
+
import { execInherited as run, npmInstall } from './shell.js';
|
|
6
6
|
|
|
7
7
|
export const MCP_DIR = resolve(ROOT, 'mcp');
|
|
8
8
|
export const MCP_SRC_DIR = resolve(MCP_DIR, 'src');
|
package/bin/lib/mcp-install.js
CHANGED
|
@@ -2,7 +2,8 @@ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import { CONFIG_PATH } from './constants.js';
|
|
4
4
|
import { bold, dim, cyan, green, red, yellow } from './colors.js';
|
|
5
|
-
import { expandHome
|
|
5
|
+
import { expandHome } from './path-expand.js';
|
|
6
|
+
import { parseJsonc } from './jsonc.js';
|
|
6
7
|
import { MCP_AGENTS, detectAgentPresence } from './mcp-agents.js';
|
|
7
8
|
|
|
8
9
|
export { MCP_AGENTS };
|