chore: align local paths and add colima dev flow
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
TKMIND_API_TARGET=https://127.0.0.1:18006
|
||||
TKMIND_API_TARGETS=https://127.0.0.1:18006
|
||||
GOOSED_MCP_NODE_PATH=/usr/local/bin/node
|
||||
GOOSED_MCP_SERVER_PATH=/opt/portal/mindspace-sandbox-mcp.mjs
|
||||
+7
-2
@@ -7,6 +7,11 @@
|
||||
# 后端代理(server.mjs / vite dev proxy 共用)
|
||||
TKMIND_API_TARGET=https://127.0.0.1:18006
|
||||
TKMIND_SERVER__SECRET_KEY=local-dev-secret
|
||||
NODE_BIN=/opt/homebrew/opt/node@24/bin/node
|
||||
AIDER_BIN=/Users/john/Project/aider/aider.sh
|
||||
GOOSE_AIDER_BIN=/Users/john/Project/aider/aider.sh
|
||||
OPENHANDS_BIN=/Users/john/.openhands/bin/studio-openhands
|
||||
GOOSE_OPENHANDS_BIN=/Users/john/.openhands/bin/studio-openhands
|
||||
H5_PORT=8081
|
||||
H5_PUBLIC_BASE_URL=http://127.0.0.1:5173
|
||||
|
||||
@@ -31,7 +36,7 @@ ADMIN_PUBLIC_HOST=gadm.tkmind.cn
|
||||
# 多用户系统(MySQL 配置后启用;未配置时回退到 H5_ACCESS_PASSWORD)
|
||||
DATABASE_URL=mysql://boot:password@localhost:3306/tkmind
|
||||
# 或分别设置 MYSQL_HOST / MYSQL_PORT / MYSQL_USER / MYSQL_PASSWORD / MYSQL_DATABASE
|
||||
H5_USERS_ROOT=/root/tkmind_go/users
|
||||
H5_USERS_ROOT=/Users/john/Project/Memind/users
|
||||
# 新用户赠送余额(人民币分,500 = ¥5.00;勿与美元 cents 混淆)
|
||||
H5_SIGNUP_BALANCE_CENTS=500
|
||||
H5_ADMIN_USERNAME=admin
|
||||
@@ -122,7 +127,7 @@ H5_ACCESS_PASSWORD=change-me
|
||||
|
||||
# 前端构建时注入(Vite,需 VITE_ 前缀)
|
||||
# 工作目录:新建会话时使用,必填
|
||||
VITE_TKMIND_WORKING_DIR=/Users/john/PycharmProjects/tkmind
|
||||
VITE_TKMIND_WORKING_DIR=/Users/john/Project/Memind
|
||||
|
||||
# 可选:覆盖默认 provider / model(未设置则从服务端 config 读取)
|
||||
# VITE_TKMIND_PROVIDER=openai
|
||||
|
||||
@@ -72,7 +72,7 @@ pnpm open:plaza # 浏览器打开 https://plaza.tkmind.cn/plaza
|
||||
## 发布规则入口
|
||||
|
||||
```bash
|
||||
cd /Users/john/PycharmProjects/test/test-memind
|
||||
cd /Users/john/Project/Memind
|
||||
bash scripts/release-portal-runtime-prod.sh --dry-run
|
||||
bash scripts/release-portal-runtime-prod.sh
|
||||
```
|
||||
|
||||
+12
-5
@@ -29,7 +29,10 @@ test('resolveSandboxMcpServerPath honors container-path override without host fs
|
||||
});
|
||||
|
||||
test('resolveSandboxMcpNodeExecPath honors container-path override without host fs checks', () => {
|
||||
assert.equal(resolveSandboxMcpNodeExecPath('/usr/local/bin/node'), '/usr/local/bin/node');
|
||||
assert.equal(
|
||||
resolveSandboxMcpNodeExecPath('/opt/homebrew/opt/node@24/bin/node'),
|
||||
'/opt/homebrew/opt/node@24/bin/node',
|
||||
);
|
||||
assert.equal(resolveSandboxMcpNodeExecPath(''), process.execPath);
|
||||
});
|
||||
|
||||
@@ -229,13 +232,17 @@ test('private_data_space alone exposes private data tools through sandbox MCP',
|
||||
|
||||
test('static_publish with sandboxMcp uses stdio sandbox-fs extension instead of developer', () => {
|
||||
const caps = { ...DEFAULT_USER_CAPABILITIES, static_publish: true };
|
||||
const sandboxMcp = { serverPath: '/opt/h5/mindspace-sandbox-mcp.mjs', sandboxRoot: '/opt/h5/MindSpace/abc123' };
|
||||
const sandboxMcp = {
|
||||
serverPath: '/opt/h5/mindspace-sandbox-mcp.mjs',
|
||||
sandboxRoot: '/opt/h5/MindSpace/abc123',
|
||||
nodeExecPath: '/opt/homebrew/opt/node@24/bin/node',
|
||||
};
|
||||
const policy = buildAgentExtensionPolicy(caps, { sandboxMcp });
|
||||
|
||||
const sandboxExt = policy.extensionOverrides.find((ext) => ext.name === 'sandbox-fs');
|
||||
assert.ok(sandboxExt, 'sandbox-fs extension should be present');
|
||||
assert.equal(sandboxExt.type, 'stdio');
|
||||
assert.equal(sandboxExt.cmd, process.execPath);
|
||||
assert.equal(sandboxExt.cmd, '/opt/homebrew/opt/node@24/bin/node');
|
||||
assert.equal(sandboxExt.envs.SANDBOX_ROOT, '/opt/h5/MindSpace/abc123');
|
||||
assert.equal(sandboxExt.args[1], '/opt/h5/MindSpace/abc123'); // also passed as argv[2]
|
||||
assert.ok(sandboxExt.available_tools.includes('write_file'));
|
||||
@@ -258,10 +265,10 @@ test('sandboxMcp honors container node executable override', () => {
|
||||
sandboxMcp: {
|
||||
serverPath: '/opt/h5/mindspace-sandbox-mcp.mjs',
|
||||
sandboxRoot: '/opt/h5/MindSpace/abc123',
|
||||
nodeExecPath: '/usr/local/bin/node',
|
||||
nodeExecPath: '/opt/homebrew/opt/node@24/bin/node',
|
||||
},
|
||||
});
|
||||
|
||||
const sandboxExt = policy.extensionOverrides.find((ext) => ext.name === 'sandbox-fs');
|
||||
assert.equal(sandboxExt?.cmd, '/usr/local/bin/node');
|
||||
assert.equal(sandboxExt?.cmd, '/opt/homebrew/opt/node@24/bin/node');
|
||||
});
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
# Colima Dev Flow
|
||||
|
||||
## 1. 原生开发
|
||||
|
||||
先在宿主机改代码并确认:
|
||||
|
||||
- `NODE_BIN=/opt/homebrew/opt/node@24/bin/node`
|
||||
- `AIDER_BIN=/Users/john/Project/aider/aider.sh`
|
||||
- `OPENHANDS_BIN=/Users/john/.openhands/bin/studio-openhands`
|
||||
|
||||
建议先过:
|
||||
|
||||
```bash
|
||||
cd /Users/john/Project/Memind
|
||||
curl -sS http://127.0.0.1:8081/api/status
|
||||
```
|
||||
|
||||
## 2. 启动本机 Colima goosed
|
||||
|
||||
```bash
|
||||
cd /Users/john/Project/tkmind_go
|
||||
cp .env.colima.example .env.colima
|
||||
bash scripts/colima-up.sh
|
||||
curl -sk https://127.0.0.1:18006/status
|
||||
```
|
||||
|
||||
必须看到:
|
||||
|
||||
- `ok`
|
||||
|
||||
## 3. 用 Colima goosed 启动本机 H5
|
||||
|
||||
```bash
|
||||
cd /Users/john/Project/Memind
|
||||
cp .env.colima.example .env.colima
|
||||
bash scripts/dev-colima.sh
|
||||
```
|
||||
|
||||
检查:
|
||||
|
||||
```bash
|
||||
curl -sS http://127.0.0.1:8081/api/status
|
||||
```
|
||||
|
||||
## 4. 用 Colima goosed 启动本机管理端
|
||||
|
||||
```bash
|
||||
cd /Users/john/Project/memind_adm
|
||||
cp .env.colima.example .env.colima
|
||||
bash scripts/local_restart_colima.sh
|
||||
```
|
||||
|
||||
检查:
|
||||
|
||||
```bash
|
||||
curl -sS http://127.0.0.1:8085/health
|
||||
```
|
||||
|
||||
## 5. 发布前 smoke
|
||||
|
||||
至少确认:
|
||||
|
||||
1. `https://127.0.0.1:18006/status` 返回 `ok`
|
||||
2. `http://127.0.0.1:8081/api/status` 返回 `ok`
|
||||
3. `http://127.0.0.1:8085/health` 返回 `{"ok":true,...}`
|
||||
4. `GOOSED_MCP_NODE_PATH` 是容器内路径
|
||||
5. `GOOSED_MCP_SERVER_PATH` 是容器内路径
|
||||
6. `AIDER_BIN`、`GOOSE_AIDER_BIN` 都是 `/Users/john/Project/aider/aider.sh`
|
||||
7. `OPENHANDS_BIN`、`GOOSE_OPENHANDS_BIN` 都是 `/Users/john/.openhands/bin/studio-openhands`
|
||||
|
||||
## 6. 停止 Colima goosed
|
||||
|
||||
```bash
|
||||
cd /Users/john/Project/tkmind_go
|
||||
bash scripts/colima-down.sh
|
||||
```
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
|
||||
> 这是本机本地开发文档,只处理当前工作区里的源码联调,不做任何生产同步。
|
||||
> `pnpm dev` 不再启动 Plaza;如果需要联动 Plaza,请显式运行 `pnpm dev:all`,或者单独运行 `pnpm dev:plaza` / `pnpm start:plaza`。
|
||||
> Plaza 专用脚本的源码默认指向同级仓库 `../test-memindplaza/app/plaza`;如你的目录不同,请用 `PLAZA_APP_DIR` 覆盖。
|
||||
> Plaza 专用脚本的源码默认指向 `/Users/john/Project/memind_plaza`;如你的目录不同,请用 `PLAZA_APP_DIR` 覆盖。
|
||||
> 生产 / 测试 / 预览隔离仍单独看 [生产 / 测试 / 预览隔离规程](./service-isolation-runbook.md)。
|
||||
|
||||
`pnpm dev` 启动后,用 **127.0.0.1 + 端口** 访问本仓库自己的服务:
|
||||
@@ -38,7 +38,7 @@ pnpm dev:all
|
||||
| `OPS_PORT` | 3002 | Ops SPA |
|
||||
| `ADMIN_PORT` | 8082 | memind_adm |
|
||||
| `H5_PUBLIC_BASE_URL` | http://127.0.0.1:5173 | 公开链接基址 |
|
||||
| `PLAZA_APP_DIR` | ../test-memindplaza/app/plaza | Plaza 专用脚本的源码路径(`pnpm dev:plaza` / `pnpm start:plaza` / `pnpm dev:all`) |
|
||||
| `PLAZA_APP_DIR` | /Users/john/Project/memind_plaza | Plaza 专用脚本的源码路径(`pnpm dev:plaza` / `pnpm start:plaza` / `pnpm dev:all`) |
|
||||
|
||||
Plaza 本地开发说明见 [plaza-local.md](./plaza-local.md)。生产发布、同步与回滚不要在这里处理,统一看 [生产更新发布指南](./release-deploy.md)。
|
||||
|
||||
|
||||
+14
-13
@@ -153,19 +153,25 @@ ssh john@58.38.22.103 'cd /Users/john/Project/Memind && test -d node_modules/htt
|
||||
Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'http-proxy-middleware'
|
||||
```
|
||||
|
||||
### 4.4 Portal 下发给 goosed 的 MCP 路径必须是容器内路径
|
||||
### 4.4 宿主机 Node 与 goosed MCP Node 必须分层配置,且都走显式 env
|
||||
|
||||
推荐并默认使用:
|
||||
103 宿主机脚本不要再依赖 PATH 找 `node`。宿主机统一显式设置:
|
||||
|
||||
```bash
|
||||
GOOSED_MCP_NODE_PATH=/usr/local/bin/node
|
||||
NODE_BIN=/opt/homebrew/opt/node@24/bin/node
|
||||
```
|
||||
|
||||
Portal 下发给 goosed 的 MCP 路径也不要猜,必须在 `.env` 里显式设置容器内路径。当前推荐:
|
||||
|
||||
```bash
|
||||
GOOSED_MCP_NODE_PATH=/opt/homebrew/opt/node@24/bin/node
|
||||
GOOSED_MCP_SERVER_PATH=/opt/portal/mindspace-sandbox-mcp.mjs
|
||||
```
|
||||
|
||||
不要让新会话继续依赖宿主机路径:
|
||||
不要让新会话继续依赖宿主机源码路径或 PATH 猜测:
|
||||
|
||||
```text
|
||||
/opt/homebrew/Cellar/node@24/24.16.0/bin/node
|
||||
/usr/local/bin/node
|
||||
/Users/john/Project/Memind/mindspace-sandbox-mcp.mjs
|
||||
```
|
||||
|
||||
@@ -207,13 +213,10 @@ Provider 'custom_deepseek' is not configured
|
||||
tkmind/goosed:prod-20260627-2125-mcp
|
||||
```
|
||||
|
||||
这个镜像必须保证以下路径在容器内存在:
|
||||
这个镜像至少必须保证 `.env` 指向的容器内路径存在。按当前推荐配置,最少要有:
|
||||
|
||||
```text
|
||||
/usr/local/bin/node
|
||||
/opt/homebrew/bin/node
|
||||
/opt/homebrew/opt/node@24/bin/node
|
||||
/opt/homebrew/Cellar/node@24/24.16.0/bin/node
|
||||
/opt/portal/mindspace-sandbox-mcp.mjs
|
||||
```
|
||||
|
||||
@@ -231,10 +234,8 @@ ssh john@58.38.22.103 '
|
||||
for c in goosed-prod-1 goosed-prod-2 goosed-prod-3 goosed-prod-4; do
|
||||
echo "--- $c"
|
||||
/opt/homebrew/bin/docker exec "$c" sh -lc "
|
||||
ls -l /usr/local/bin/node \
|
||||
/opt/homebrew/bin/node \
|
||||
ls -l \
|
||||
/opt/homebrew/opt/node@24/bin/node \
|
||||
/opt/homebrew/Cellar/node@24/24.16.0/bin/node \
|
||||
/opt/portal/mindspace-sandbox-mcp.mjs
|
||||
"
|
||||
done
|
||||
@@ -255,7 +256,7 @@ ssh john@58.38.22.103 '
|
||||
3. 103 Portal 进程是否拿到了 `DATABASE_URL`?
|
||||
4. `~/Library/Logs/memind-portal.log` 是否有 `User auth bootstrap failed`?
|
||||
5. 18006-18009 是否全 200?
|
||||
6. goosed 容器内 `/usr/local/bin/node` 和 `/opt/portal/mindspace-sandbox-mcp.mjs` 是否存在?
|
||||
6. goosed 容器内 `${GOOSED_MCP_NODE_PATH}` 和 `${GOOSED_MCP_SERVER_PATH}` 对应路径是否存在?
|
||||
7. provider 是否同步到四个 target?
|
||||
8. 如果是微信服务号或专属 Agent 报错,必须测真实业务路径,不要只看健康接口。
|
||||
|
||||
|
||||
+15
-2
@@ -436,6 +436,19 @@ function normalizeLaunchMode(mode) {
|
||||
return normalized === 'serve' ? 'serve' : 'headless';
|
||||
}
|
||||
|
||||
function resolveExecutorCommand(executor) {
|
||||
if (executor === 'openhands') {
|
||||
const explicit =
|
||||
String(process.env.GOOSE_OPENHANDS_BIN ?? process.env.OPENHANDS_BIN ?? '').trim();
|
||||
if (explicit) return explicit;
|
||||
}
|
||||
if (executor === 'aider') {
|
||||
const explicit = String(process.env.GOOSE_AIDER_BIN ?? process.env.AIDER_BIN ?? '').trim();
|
||||
if (explicit) return explicit;
|
||||
}
|
||||
return executor;
|
||||
}
|
||||
|
||||
function commandExists(command) {
|
||||
const probe = spawnSync('sh', ['-lc', `command -v ${JSON.stringify(command).slice(1, -1)}`], {
|
||||
stdio: 'ignore',
|
||||
@@ -545,7 +558,7 @@ export function buildExecutorLaunchPlan(runtime, options = {}) {
|
||||
ok: true,
|
||||
executor: 'aider',
|
||||
cwd,
|
||||
command: 'aider',
|
||||
command: resolveExecutorCommand('aider'),
|
||||
args: [
|
||||
'--model',
|
||||
runtime.model,
|
||||
@@ -576,7 +589,7 @@ export function buildExecutorLaunchPlan(runtime, options = {}) {
|
||||
ok: true,
|
||||
executor: 'openhands',
|
||||
cwd,
|
||||
command: 'openhands',
|
||||
command: resolveExecutorCommand('openhands'),
|
||||
args,
|
||||
env,
|
||||
notes: [
|
||||
|
||||
@@ -203,12 +203,13 @@ async function writeMetadata() {
|
||||
'export TKMIND_API_TARGETS="${TKMIND_API_TARGETS:-https://127.0.0.1:18006,https://127.0.0.1:18007,https://127.0.0.1:18008,https://127.0.0.1:18009}"',
|
||||
'export TKMIND_API_TARGET="${TKMIND_API_TARGET:-https://127.0.0.1:18006}"',
|
||||
'export TKMIND_API_TARGET_1="${TKMIND_API_TARGET_1:-https://127.0.0.1:18007}"',
|
||||
'export GOOSED_MCP_NODE_PATH="${GOOSED_MCP_NODE_PATH:-/usr/local/bin/node}"',
|
||||
'export GOOSED_MCP_NODE_PATH="${GOOSED_MCP_NODE_PATH:-/opt/homebrew/opt/node@24/bin/node}"',
|
||||
'export GOOSED_MCP_SERVER_PATH="${GOOSED_MCP_SERVER_PATH:-/opt/portal/mindspace-sandbox-mcp.mjs}"',
|
||||
'',
|
||||
'NODE_BIN="${NODE_BIN:-/opt/homebrew/opt/node@24/bin/node}"',
|
||||
'if [[ ! -x "${NODE_BIN}" ]]; then',
|
||||
' NODE_BIN="$(command -v node)"',
|
||||
' echo "NODE_BIN is not executable: ${NODE_BIN}" >&2',
|
||||
' exit 1',
|
||||
'fi',
|
||||
'',
|
||||
'exec "${NODE_BIN}" "${ROOT}/server.mjs"',
|
||||
|
||||
@@ -12,12 +12,12 @@ ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
EXCLUDE_FILE="${ROOT_DIR}/scripts/.rsync-exclude-test-host"
|
||||
|
||||
MEMIND_SRC="${MEMIND_SRC:-${ROOT_DIR}}"
|
||||
ADM_SRC="${ADM_SRC:-${ROOT_DIR}/../memind_adm}"
|
||||
PLAZA_SRC="${PLAZA_SRC:-${ROOT_DIR}/../tkmind_go/ui/plaza}"
|
||||
ADM_SRC="${ADM_SRC:-/Users/john/Project/memind_adm}"
|
||||
PLAZA_SRC="${PLAZA_SRC:-/Users/john/Project/memind_plaza}"
|
||||
|
||||
MEMIND_DST="${MEMIND_DST:-/Users/john/PycharmProjects/test/test-memind}"
|
||||
ADM_DST="${ADM_DST:-/Users/john/PycharmProjects/test/test-memindadm}"
|
||||
PLAZA_DST="${PLAZA_DST:-/Users/john/PycharmProjects/test/test-memindplaza}"
|
||||
MEMIND_DST="${MEMIND_DST:-/Users/john/Project/Memind}"
|
||||
ADM_DST="${ADM_DST:-/Users/john/Project/memind_adm}"
|
||||
PLAZA_DST="${PLAZA_DST:-/Users/john/Project/memind_plaza}"
|
||||
|
||||
RSYNC_OPTS=(
|
||||
-az
|
||||
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
|
||||
cd "${ROOT}"
|
||||
|
||||
set -a
|
||||
source "${ROOT}/.env"
|
||||
if [[ -f "${ROOT}/.env.colima" ]]; then
|
||||
source "${ROOT}/.env.colima"
|
||||
fi
|
||||
set +a
|
||||
|
||||
exec "${NODE_BIN:-/opt/homebrew/opt/node@24/bin/node}" "${ROOT}/scripts/dev-core.mjs"
|
||||
@@ -12,8 +12,8 @@ import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const defaultPlazaDir = fs.existsSync(path.join(root, '../test-memindplaza/app/plaza/package.json'))
|
||||
? path.join(root, '../test-memindplaza/app/plaza')
|
||||
const defaultPlazaDir = fs.existsSync(path.join('/Users/john/Project/memind_plaza', 'package.json'))
|
||||
? '/Users/john/Project/memind_plaza'
|
||||
: path.join(root, '../tkmind_go/ui/plaza');
|
||||
const plazaDir = process.env.PLAZA_APP_DIR ?? defaultPlazaDir;
|
||||
const portalPort = Number(process.env.H5_PORT ?? 8081);
|
||||
@@ -119,7 +119,7 @@ process.on('SIGINT', () => shutdown(0));
|
||||
process.on('SIGTERM', () => shutdown(0));
|
||||
|
||||
if (!fs.existsSync(path.join(plazaDir, 'package.json'))) {
|
||||
console.error(`未找到 Plaza Next.js:${plazaDir}。请设置 PLAZA_APP_DIR 指向本地 Plaza 源码,例如 ../test-memindplaza/app/plaza`);
|
||||
console.error(`未找到 Plaza Next.js:${plazaDir}。请设置 PLAZA_APP_DIR 指向本地 Plaza 源码,例如 /Users/john/Project/memind_plaza`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -7,8 +7,8 @@ import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const defaultPlazaDir = fs.existsSync(path.join(root, '../test-memindplaza/app/plaza/package.json'))
|
||||
? path.join(root, '../test-memindplaza/app/plaza')
|
||||
const defaultPlazaDir = fs.existsSync(path.join('/Users/john/Project/memind_plaza', 'package.json'))
|
||||
? '/Users/john/Project/memind_plaza'
|
||||
: path.join(root, '../tkmind_go/ui/plaza');
|
||||
const plazaDir = process.env.PLAZA_APP_DIR ?? defaultPlazaDir;
|
||||
const opsDir = path.join(root, 'ops');
|
||||
@@ -125,7 +125,7 @@ const opsEnv = {
|
||||
|
||||
function ensurePlazaApp() {
|
||||
if (!fs.existsSync(path.join(plazaDir, 'package.json'))) {
|
||||
throw new Error(`未找到 Plaza Next.js:${plazaDir}。请设置 PLAZA_APP_DIR 指向本地 Plaza 源码,例如 ../test-memindplaza/app/plaza`);
|
||||
throw new Error(`未找到 Plaza Next.js:${plazaDir}。请设置 PLAZA_APP_DIR 指向本地 Plaza 源码,例如 /Users/john/Project/memind_plaza`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -162,6 +162,16 @@ missing=0
|
||||
|
||||
docker_bin="/opt/homebrew/bin/docker"
|
||||
if [[ -x "${docker_bin}" ]] && "${docker_bin}" ps --format '{{.Names}}' 2>/dev/null | grep -q '^goosed-prod-1$'; then
|
||||
portal_mcp_node=""
|
||||
portal_mcp_server=""
|
||||
if [[ -f /Users/john/Project/Memind/.env ]]; then
|
||||
portal_mcp_node="$(grep -E '^GOOSED_MCP_NODE_PATH=' /Users/john/Project/Memind/.env | tail -1 | cut -d= -f2- || true)"
|
||||
portal_mcp_server="$(grep -E '^GOOSED_MCP_SERVER_PATH=' /Users/john/Project/Memind/.env | tail -1 | cut -d= -f2- || true)"
|
||||
fi
|
||||
if [[ -z "${portal_mcp_node}" || -z "${portal_mcp_server}" ]]; then
|
||||
echo "goosed dependency check failed: Portal .env must set GOOSED_MCP_NODE_PATH and GOOSED_MCP_SERVER_PATH for Docker goosed" >&2
|
||||
missing=1
|
||||
fi
|
||||
for index in 1 2 3 4; do
|
||||
container="goosed-prod-${index}"
|
||||
host_port=$((18005 + index))
|
||||
@@ -169,27 +179,11 @@ if [[ -x "${docker_bin}" ]] && "${docker_bin}" ps --format '{{.Names}}' 2>/dev/n
|
||||
echo "goosed dependency check failed: ${container} is not healthy on host port ${host_port}" >&2
|
||||
missing=1
|
||||
fi
|
||||
if ! "${docker_bin}" exec "${container}" sh -lc 'test -x /usr/local/bin/node && test -f /opt/portal/mindspace-sandbox-mcp.mjs' >/dev/null 2>&1; then
|
||||
echo "goosed dependency check failed: ${container} missing /usr/local/bin/node or /opt/portal/mindspace-sandbox-mcp.mjs" >&2
|
||||
if [[ -n "${portal_mcp_node}" && -n "${portal_mcp_server}" ]] && ! "${docker_bin}" exec "${container}" sh -lc "test -x '${portal_mcp_node}' && test -f '${portal_mcp_server}'" >/dev/null 2>&1; then
|
||||
echo "goosed dependency check failed: ${container} cannot resolve Portal .env MCP paths '${portal_mcp_node}' and '${portal_mcp_server}'" >&2
|
||||
missing=1
|
||||
fi
|
||||
done
|
||||
if [[ -f /Users/john/Project/Memind/.env ]]; then
|
||||
portal_mcp_node="$(grep -E '^GOOSED_MCP_NODE_PATH=' /Users/john/Project/Memind/.env | tail -1 | cut -d= -f2- || true)"
|
||||
portal_mcp_server="$(grep -E '^GOOSED_MCP_SERVER_PATH=' /Users/john/Project/Memind/.env | tail -1 | cut -d= -f2- || true)"
|
||||
if [[ -z "${portal_mcp_node}" || -z "${portal_mcp_server}" ]]; then
|
||||
echo "goosed dependency check failed: Portal .env must set GOOSED_MCP_NODE_PATH and GOOSED_MCP_SERVER_PATH for Docker goosed" >&2
|
||||
missing=1
|
||||
else
|
||||
for index in 1 2 3 4; do
|
||||
container="goosed-prod-${index}"
|
||||
if ! "${docker_bin}" exec "${container}" sh -lc "test -x '${portal_mcp_node}' && test -f '${portal_mcp_server}'" >/dev/null 2>&1; then
|
||||
echo "goosed dependency check failed: ${container} cannot resolve Portal .env MCP paths '${portal_mcp_node}' and '${portal_mcp_server}'" >&2
|
||||
missing=1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
else
|
||||
for port in 18006 18007; do
|
||||
line="$(lsof -nP -iTCP:${port} -sTCP:LISTEN 2>/dev/null | awk 'NR==2 {print $1, $2, $9}')"
|
||||
|
||||
@@ -237,13 +237,15 @@ done
|
||||
|
||||
say "安装依赖"
|
||||
cd "${RELEASE_DIR}"
|
||||
export PATH="/opt/homebrew/bin:/opt/homebrew/opt/node@24/bin:/usr/local/bin:/usr/bin:/bin:${PATH}"
|
||||
if command -v npm >/dev/null 2>&1; then
|
||||
NPM_BIN="$(command -v npm)"
|
||||
elif [[ -x /opt/homebrew/opt/node@24/bin/npm ]]; then
|
||||
NPM_BIN="/opt/homebrew/opt/node@24/bin/npm"
|
||||
else
|
||||
echo "npm not found on remote" >&2
|
||||
NODE_BIN="${NODE_BIN:-/opt/homebrew/opt/node@24/bin/node}"
|
||||
if [[ ! -x "${NODE_BIN}" ]]; then
|
||||
echo "node not found or not executable: ${NODE_BIN}" >&2
|
||||
exit 1
|
||||
fi
|
||||
NODE_DIR="$(cd "$(dirname "${NODE_BIN}")" && pwd)"
|
||||
NPM_BIN="${NPM_BIN:-${NODE_DIR}/npm}"
|
||||
if [[ ! -x "${NPM_BIN}" ]]; then
|
||||
echo "npm not found or not executable: ${NPM_BIN}" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -f package-lock.json ]]; then
|
||||
|
||||
@@ -21,7 +21,8 @@ export TKMIND_API_TARGET_1="${TKMIND_API_TARGET_1_OVERRIDE:-https://127.0.0.1:18
|
||||
|
||||
NODE_BIN="${NODE_BIN:-/opt/homebrew/opt/node@24/bin/node}"
|
||||
if [[ ! -x "${NODE_BIN}" ]]; then
|
||||
NODE_BIN="$(command -v node)"
|
||||
echo "NODE_BIN is not executable: ${NODE_BIN}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec "${NODE_BIN}" server.mjs
|
||||
|
||||
@@ -19,7 +19,8 @@ PLAZA_PORT="${PLAZA_PORT:-3001}"
|
||||
|
||||
NODE_BIN="${NODE_BIN:-/opt/homebrew/opt/node@24/bin/node}"
|
||||
if [[ ! -x "${NODE_BIN}" ]]; then
|
||||
NODE_BIN="$(command -v node)"
|
||||
echo "NODE_BIN is not executable: ${NODE_BIN}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> 等待 Portal :${PORTAL_PORT}…"
|
||||
|
||||
@@ -12,8 +12,8 @@ import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const defaultPlazaDir = fs.existsSync(path.join(root, '../test-memindplaza/app/plaza/package.json'))
|
||||
? path.join(root, '../test-memindplaza/app/plaza')
|
||||
const defaultPlazaDir = fs.existsSync(path.join('/Users/john/Project/memind_plaza', 'package.json'))
|
||||
? '/Users/john/Project/memind_plaza'
|
||||
: path.join(root, '../tkmind_go/ui/plaza');
|
||||
const plazaDir = process.env.PLAZA_APP_DIR ?? defaultPlazaDir;
|
||||
const portalPort = Number(process.env.H5_PORT ?? 8081);
|
||||
@@ -102,7 +102,7 @@ process.on('SIGINT', () => shutdown(0));
|
||||
process.on('SIGTERM', () => shutdown(0));
|
||||
|
||||
if (!fs.existsSync(path.join(plazaDir, 'package.json'))) {
|
||||
console.error(`未找到 Plaza Next.js:${plazaDir}。请设置 PLAZA_APP_DIR 指向本地 Plaza 源码,例如 ../test-memindplaza/app/plaza`);
|
||||
console.error(`未找到 Plaza Next.js:${plazaDir}。请设置 PLAZA_APP_DIR 指向本地 Plaza 源码,例如 /Users/john/Project/memind_plaza`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -990,7 +990,7 @@ test('wechat mp service reconciles existing dedicated session before reply', asy
|
||||
const extensionConfig = {
|
||||
type: 'stdio',
|
||||
name: 'sandbox-fs',
|
||||
cmd: '/usr/local/bin/node',
|
||||
cmd: '/opt/homebrew/opt/node@24/bin/node',
|
||||
args: ['/Users/john/Project/Memind/mindspace-sandbox-mcp.mjs', workingDir],
|
||||
envs: { SANDBOX_ROOT: workingDir },
|
||||
available_tools: ['list_dir'],
|
||||
@@ -1852,7 +1852,7 @@ test('wechat mp service persists image and routes image url into agent prompt',
|
||||
await result.task;
|
||||
} finally {
|
||||
crypto.randomUUID = originalRandomUuid;
|
||||
fs.rmSync(`/Users/john/PycharmProjects/test/test-memind/MindSpace/${testUserId}`, {
|
||||
fs.rmSync(`/Users/john/Project/Memind/MindSpace/${testUserId}`, {
|
||||
recursive: true,
|
||||
force: true,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user