@geminilight/mindos 0.6.13 → 0.6.15

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.
@@ -202,7 +202,14 @@ function DesktopUpdateTab() {
202
202
 
203
203
  {state === 'ready' && (
204
204
  <button
205
- onClick={() => bridge.installUpdate()}
205
+ onClick={async () => {
206
+ try {
207
+ await bridge.installUpdate();
208
+ } catch {
209
+ setState('error');
210
+ setErrorMsg(u?.error ?? 'Failed to install update. Please try again.');
211
+ }
212
+ }}
206
213
  className="flex items-center gap-1.5 px-3 py-1.5 text-xs rounded-lg font-medium text-[var(--amber-foreground)] bg-[var(--amber)] transition-colors"
207
214
  >
208
215
  <RefreshCw size={12} />
package/bin/cli.js CHANGED
@@ -771,16 +771,19 @@ ${dim('Shortcut: mindos start --daemon → install + start in one step')}
771
771
 
772
772
  // Stage 3: Rebuild
773
773
  writeUpdateStatus('rebuilding', vOpts);
774
- buildIfNeeded(updatedRoot);
774
+ let daemonBuildFailed = '';
775
+ try {
776
+ buildIfNeeded(updatedRoot);
777
+ } catch (err) {
778
+ daemonBuildFailed = err instanceof Error ? err.message : String(err);
779
+ console.error(yellow(`\n Pre-build failed: ${daemonBuildFailed}`));
780
+ console.error(yellow(' Daemon will attempt to rebuild on startup...\n'));
781
+ }
775
782
 
776
- // Stage 4: Restart
783
+ // Stage 4: Restart — always attempt, even if pre-build failed
784
+ // (daemon has auto-restart; `mindos start` retries the build)
777
785
  writeUpdateStatus('restarting', vOpts);
778
786
  await runGatewayCommand('install');
779
- // install() starts the service:
780
- // - systemd: daemon-reload + enable + start
781
- // - launchd: bootstrap (RunAtLoad=true auto-starts)
782
- // Do NOT call start() again — on macOS kickstart -k would kill the
783
- // just-started process, causing a port-conflict race with KeepAlive.
784
787
  const updateConfig = (() => {
785
788
  try { return JSON.parse(readFileSync(CONFIG_PATH, 'utf-8')); } catch { return {}; }
786
789
  })();
@@ -799,8 +802,11 @@ ${dim('Shortcut: mindos start --daemon → install + start in one step')}
799
802
  console.log(`${'─'.repeat(53)}\n`);
800
803
  writeUpdateStatus('done', vOpts);
801
804
  } else {
802
- writeUpdateFailed('restarting', 'Server did not come back up in time', vOpts);
803
- console.error(red('✘ MindOS did not come back up in time. Check logs: mindos logs\n'));
805
+ const failMsg = daemonBuildFailed
806
+ ? `Build failed (${daemonBuildFailed}), server did not come back up`
807
+ : 'Server did not come back up in time';
808
+ writeUpdateFailed('restarting', failMsg, vOpts);
809
+ console.error(red(`✘ ${failMsg}. Check logs: mindos logs\n`));
804
810
  process.exit(1);
805
811
  }
806
812
  } else {
@@ -828,9 +834,17 @@ ${dim('Shortcut: mindos start --daemon → install + start in one step')}
828
834
 
829
835
  // Stage 3: Rebuild
830
836
  writeUpdateStatus('rebuilding', vOpts);
831
- buildIfNeeded(updatedRoot);
837
+ let buildFailed = '';
838
+ try {
839
+ buildIfNeeded(updatedRoot);
840
+ } catch (err) {
841
+ buildFailed = err instanceof Error ? err.message : String(err);
842
+ console.error(yellow(`\n Pre-build failed: ${buildFailed}`));
843
+ console.error(yellow(' Starting server anyway (it will retry the build)...\n'));
844
+ }
832
845
 
833
- // Stage 4: Restart
846
+ // Stage 4: Restart — always attempt, even if pre-build failed
847
+ // (`mindos start` has its own build-on-startup logic)
834
848
  writeUpdateStatus('restarting', vOpts);
835
849
  const newCliPath = resolve(updatedRoot, 'bin', 'cli.js');
836
850
  const childEnv = { ...process.env };
@@ -858,13 +872,22 @@ ${dim('Shortcut: mindos start --daemon → install + start in one step')}
858
872
  console.log(`${'─'.repeat(53)}\n`);
859
873
  writeUpdateStatus('done', vOpts);
860
874
  } else {
861
- writeUpdateFailed('restarting', 'Server did not come back up in time', vOpts);
862
- console.error(red('✘ MindOS did not come back up in time. Check logs: mindos logs\n'));
875
+ const failMsg = buildFailed
876
+ ? `Build failed (${buildFailed}), server did not come back up`
877
+ : 'Server did not come back up in time';
878
+ writeUpdateFailed('restarting', failMsg, vOpts);
879
+ console.error(red(`✘ ${failMsg}. Check logs: mindos logs\n`));
863
880
  process.exit(1);
864
881
  }
865
882
  } else {
866
883
  // No running instance — just build and tell user to start manually
867
- buildIfNeeded(updatedRoot);
884
+ try {
885
+ buildIfNeeded(updatedRoot);
886
+ } catch (err) {
887
+ const msg = err instanceof Error ? err.message : String(err);
888
+ console.error(yellow(`\n Pre-build failed: ${msg}`));
889
+ console.error(dim(' The build will be retried when you run `mindos start`.'));
890
+ }
868
891
  console.log(`\n${green('✔')} ${bold(`Updated: ${currentVersion} → ${newVersion}`)}`);
869
892
  console.log(dim(' Run `mindos start` to start the updated version.'));
870
893
  console.log(` ${dim('View changelog:')} ${cyan('https://github.com/GeminiLight/MindOS/releases')}\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geminilight/mindos",
3
- "version": "0.6.13",
3
+ "version": "0.6.15",
4
4
  "description": "MindOS — Human-Agent Collaborative Mind System. Local-first knowledge base that syncs your mind to all AI Agents via MCP.",
5
5
  "keywords": [
6
6
  "mindos",
@@ -0,0 +1,100 @@
1
+ #!/bin/bash
2
+ # 阿里云 OSS 上传测试(纯 curl,和 CI workflow 用同样的签名方式)
3
+ # 用法:
4
+ # export OSS_ACCESS_KEY_ID=你的ID
5
+ # export OSS_ACCESS_KEY_SECRET=你的Secret
6
+ # export OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com # 不带 https://
7
+ # export OSS_BUCKET=mindos-cn-releases
8
+ # bash scripts/test-oss-upload.sh
9
+
10
+ set -e
11
+
12
+ : "${OSS_ACCESS_KEY_ID:?请设置 OSS_ACCESS_KEY_ID}"
13
+ : "${OSS_ACCESS_KEY_SECRET:?请设置 OSS_ACCESS_KEY_SECRET}"
14
+ : "${OSS_ENDPOINT:?请设置 OSS_ENDPOINT (不带 https://)}"
15
+ : "${OSS_BUCKET:?请设置 OSS_BUCKET}"
16
+
17
+ echo "=== OSS 上传测试 ==="
18
+ echo "Bucket: $OSS_BUCKET"
19
+ echo "Endpoint: $OSS_ENDPOINT"
20
+ echo "URL: https://${OSS_BUCKET}.${OSS_ENDPOINT}/"
21
+ echo ""
22
+
23
+ # 检查 endpoint 格式
24
+ if [[ "$OSS_ENDPOINT" == https://* ]]; then
25
+ echo "错误: OSS_ENDPOINT 不要带 https:// 前缀"
26
+ echo "当前值: $OSS_ENDPOINT"
27
+ echo "应该是: oss-cn-hangzhou.aliyuncs.com"
28
+ exit 1
29
+ fi
30
+
31
+ # 创建测试文件
32
+ OBJECT_KEY="test-upload-$(date +%s).txt"
33
+ CONTENT_TYPE="text/plain"
34
+ TMP_FILE="/tmp/oss-test-$$.txt"
35
+ echo "hello from MindOS CI test at $(date)" > "$TMP_FILE"
36
+
37
+ # 上传函数(和 CI workflow 完全一致)
38
+ oss_upload() {
39
+ local file="$1"
40
+ local object_key="$2"
41
+ local content_type="${3:-application/octet-stream}"
42
+ local date_header=$(date -u +"%a, %d %b %Y %H:%M:%S GMT")
43
+ local resource="/${OSS_BUCKET}/${object_key}"
44
+ local string_to_sign="PUT\n\n${content_type}\n${date_header}\n${resource}"
45
+ local signature=$(printf "$string_to_sign" | openssl dgst -sha1 -hmac "$OSS_ACCESS_KEY_SECRET" -binary | base64)
46
+ local url="https://${OSS_BUCKET}.${OSS_ENDPOINT}/${object_key}"
47
+
48
+ echo " URL: $url"
49
+ local http_code=$(curl -s -o /tmp/oss-response.txt -w "%{http_code}" \
50
+ -X PUT \
51
+ -H "Date: ${date_header}" \
52
+ -H "Content-Type: ${content_type}" \
53
+ -H "Authorization: OSS ${OSS_ACCESS_KEY_ID}:${signature}" \
54
+ -T "$file" \
55
+ "$url")
56
+
57
+ if [ "$http_code" = "200" ]; then
58
+ echo " 上传成功 (HTTP $http_code)"
59
+ return 0
60
+ else
61
+ echo " 上传失败 (HTTP $http_code)"
62
+ cat /tmp/oss-response.txt 2>/dev/null
63
+ echo ""
64
+ return 1
65
+ fi
66
+ }
67
+
68
+ # 1. 上传
69
+ echo "1. 上传测试文件: $OBJECT_KEY"
70
+ oss_upload "$TMP_FILE" "$OBJECT_KEY" "text/plain"
71
+
72
+ # 2. 公网访问
73
+ echo ""
74
+ echo "2. 公网访问测试:"
75
+ PUBLIC_URL="https://${OSS_BUCKET}.${OSS_ENDPOINT}/${OBJECT_KEY}"
76
+ HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$PUBLIC_URL")
77
+ if [ "$HTTP_CODE" = "200" ]; then
78
+ echo " 公网访问成功 (HTTP $HTTP_CODE)"
79
+ echo " 内容: $(curl -s "$PUBLIC_URL")"
80
+ else
81
+ echo " 公网访问失败 (HTTP $HTTP_CODE) — 请在 OSS 控制台开启公共读"
82
+ fi
83
+
84
+ # 3. 清理
85
+ echo ""
86
+ echo "3. 清理测试文件..."
87
+ DATE_HEADER=$(date -u +"%a, %d %b %Y %H:%M:%S GMT")
88
+ RESOURCE="/${OSS_BUCKET}/${OBJECT_KEY}"
89
+ STRING_TO_SIGN="DELETE\n\n\n${DATE_HEADER}\n${RESOURCE}"
90
+ SIGNATURE=$(printf "$STRING_TO_SIGN" | openssl dgst -sha1 -hmac "$OSS_ACCESS_KEY_SECRET" -binary | base64)
91
+ curl -s -o /dev/null \
92
+ -X DELETE \
93
+ -H "Date: ${DATE_HEADER}" \
94
+ -H "Authorization: OSS ${OSS_ACCESS_KEY_ID}:${SIGNATURE}" \
95
+ "https://${OSS_BUCKET}.${OSS_ENDPOINT}/${OBJECT_KEY}"
96
+ echo " 已清理"
97
+
98
+ rm -f "$TMP_FILE" /tmp/oss-response.txt
99
+ echo ""
100
+ echo "=== 测试完成 ==="