soulsync 1.0.6 → 1.0.8

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "cloud_url": "https://soulsync.work",
3
- "email": "your-email@example.com",
4
- "password": "your-password",
3
+ "email": "",
4
+ "password": "",
5
5
  "workspace": "./workspace",
6
6
  "memory_file": "MEMORY.md",
7
7
  "watch_files": [
@@ -13,5 +13,6 @@
13
13
  "skills.json",
14
14
  "memory/",
15
15
  "MEMORY.md"
16
- ]
16
+ ],
17
+ "_comment": "Register at https://soulsync.work or use curl to call /api/auth/register endpoint"
17
18
  }
package/index.js CHANGED
@@ -1,59 +1,106 @@
1
1
  const { spawn } = require('child_process');
2
2
  const path = require('path');
3
+ const fs = require('fs');
3
4
 
4
5
  let pythonProcess = null;
5
6
 
6
- // 函数形式导出(推荐)
7
+ function getPluginDir() {
8
+ return path.dirname(__filename);
9
+ }
10
+
11
+ function checkConfigExists(pluginDir) {
12
+ const configPath = path.join(pluginDir, 'config.json');
13
+ if (!fs.existsSync(configPath)) {
14
+ const examplePath = path.join(pluginDir, 'config.json.example');
15
+ if (fs.existsSync(examplePath)) {
16
+ fs.copyFileSync(examplePath, configPath);
17
+ console.log('[SoulSync] Created config.json from template');
18
+ }
19
+ return false;
20
+ }
21
+
22
+ try {
23
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
24
+ const email = (config.email || '').trim();
25
+ const password = (config.password || '').trim();
26
+ return email && password && email !== 'your-email@example.com' && password !== 'your-password';
27
+ } catch (e) {
28
+ return false;
29
+ }
30
+ }
31
+
32
+ function startPythonService(mode = '--start') {
33
+ const pluginDir = getPluginDir();
34
+ const pythonScript = path.join(pluginDir, 'src', 'main.py');
35
+ const pythonPath = process.env.PYTHON_PATH || 'python3';
36
+
37
+ console.log(`[SoulSync] Starting Python service (${mode})...`);
38
+
39
+ pythonProcess = spawn(pythonPath, [pythonScript, mode], {
40
+ cwd: pluginDir,
41
+ env: {
42
+ ...process.env,
43
+ OPENCLAW_PLUGIN: 'true',
44
+ PLUGIN_DIR: pluginDir
45
+ },
46
+ stdio: 'inherit'
47
+ });
48
+
49
+ pythonProcess.on('close', (code) => {
50
+ console.log(`[SoulSync] Python process exited with code ${code}`);
51
+ pythonProcess = null;
52
+ });
53
+
54
+ pythonProcess.on('error', (err) => {
55
+ console.error(`[SoulSync] Failed to start Python process: ${err}`);
56
+ pythonProcess = null;
57
+ });
58
+
59
+ return pythonProcess;
60
+ }
61
+
7
62
  module.exports = function register(api) {
8
63
  console.log('[SoulSync] Registering plugin...');
9
64
 
10
- // 自动启动 Python 服务
11
- function startPythonService() {
12
- const pluginDir = path.dirname(__filename);
13
- const pythonScript = path.join(pluginDir, 'src', 'main.py');
14
- const pythonPath = process.env.PYTHON_PATH || 'python3';
15
-
16
- console.log('[SoulSync] Auto-starting Python service...');
17
-
18
- pythonProcess = spawn(pythonPath, [pythonScript], {
19
- cwd: pluginDir,
20
- env: {
21
- ...process.env,
22
- OPENCLAW_PLUGIN: 'true',
23
- PLUGIN_DIR: pluginDir
24
- },
25
- stdio: 'inherit'
26
- });
27
-
28
- pythonProcess.on('close', (code) => {
29
- console.log(`[SoulSync] Python process exited with code ${code}`);
30
- pythonProcess = null;
31
- });
32
-
33
- pythonProcess.on('error', (err) => {
34
- console.error(`[SoulSync] Failed to start Python process: ${err}`);
35
- pythonProcess = null;
36
- });
37
- }
65
+ api.registerCli(
66
+ ({ program }) => {
67
+ program
68
+ .command('soulsync:setup')
69
+ .description('首次配置:注册或登录 SoulSync 账号')
70
+ .action(() => {
71
+ console.log('[SoulSync] Starting setup...');
72
+ startPythonService('--setup');
73
+ });
74
+ },
75
+ { commands: ['soulsync:setup'] }
76
+ );
38
77
 
39
- // 注册CLI命令:启动 SoulSync
40
78
  api.registerCli(
41
79
  ({ program }) => {
42
80
  program
43
81
  .command('soulsync:start')
44
82
  .description('启动 SoulSync 同步服务')
45
83
  .action(() => {
84
+ const pluginDir = getPluginDir();
85
+ const configPath = path.join(pluginDir, 'config.json');
86
+
87
+ if (!checkConfigExists(pluginDir)) {
88
+ console.log('[SoulSync] Not configured. Starting setup...');
89
+ startPythonService('--setup');
90
+ return;
91
+ }
92
+
46
93
  if (pythonProcess) {
47
94
  console.log('[SoulSync] Service already running');
48
95
  return;
49
96
  }
50
- startPythonService();
97
+
98
+ startPythonService('--start');
51
99
  });
52
100
  },
53
101
  { commands: ['soulsync:start'] }
54
102
  );
55
103
 
56
- // 注册CLI命令:停止 SoulSync
57
104
  api.registerCli(
58
105
  ({ program }) => {
59
106
  program
@@ -72,8 +119,6 @@ module.exports = function register(api) {
72
119
  { commands: ['soulsync:stop'] }
73
120
  );
74
121
 
75
- // 自动启动服务
76
- startPythonService();
77
-
122
+ console.log('[SoulSync] Plugin loaded. Run "openclaw soulsync:start" to begin.');
78
123
  console.log('[SoulSync] Plugin registered successfully');
79
124
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "soulsync",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "SoulSync plugin for OpenClaw - cross-bot memory synchronization",
5
5
  "main": "index.js",
6
6
  "repository": {
package/src/main.py CHANGED
@@ -8,6 +8,7 @@ import os
8
8
  import sys
9
9
  import time
10
10
  import getpass
11
+ import argparse
11
12
 
12
13
  # 获取插件根目录
13
14
  PLUGIN_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -22,8 +23,6 @@ from watcher import OpenClawMultiWatcher
22
23
  from version_manager import VersionManager
23
24
  from profiles import ProfilesClient
24
25
  from sync import ProfileSync
25
- from register import Register, Login
26
- from interactive_auth import prompt_for_missing_config, interactive_setup, check_existing_config
27
26
 
28
27
 
29
28
  class SoulSyncPlugin:
@@ -43,14 +42,14 @@ class SoulSyncPlugin:
43
42
  config_path = os.path.normpath(os.path.join(PLUGIN_DIR, 'config.json'))
44
43
  config_example_path = os.path.normpath(os.path.join(PLUGIN_DIR, 'config.json.example'))
45
44
 
46
- print(f"Looking for config at: {config_path}")
45
+ print(f"[SoulSync] Looking for config at: {config_path}")
47
46
 
48
47
  if not os.path.exists(config_path):
49
48
  if os.path.exists(config_example_path):
50
- print("Config file not found, copying from config.json.example...")
49
+ print("[SoulSync] Config file not found, copying from config.json.example...")
51
50
  import shutil
52
51
  shutil.copy(config_example_path, config_path)
53
- print(f"Created config.json from template")
52
+ print("[SoulSync] Created config.json from template")
54
53
  else:
55
54
  raise FileNotFoundError(f"Config file not found: {config_path}")
56
55
 
@@ -60,25 +59,24 @@ class SoulSyncPlugin:
60
59
  except json.JSONDecodeError as e:
61
60
  raise ValueError(f"Invalid JSON in config.json: {e}")
62
61
 
63
- # 检查必要配置
64
62
  cloud_url = self.config.get('cloud_url', '').strip()
65
63
  email = self.config.get('email', '').strip()
66
64
  password = self.config.get('password', '').strip()
67
65
 
68
- # 如果 cloud_url 为空,设置为默认值
69
66
  if not cloud_url:
70
67
  self.config['cloud_url'] = 'https://soulsync.work'
71
- print("Cloud URL not set, using default: https://soulsync.work")
68
+ print("[SoulSync] Cloud URL not set, using default: https://soulsync.work")
72
69
 
73
- # 如果 email password 为空,需要交互式认证
74
- if not email or not password:
75
- print("\nEmail or password not configured, initiating interactive setup...")
76
- self._interactive_setup()
77
- # 重新加载配置
78
- with open(config_path, 'r', encoding='utf-8') as f:
79
- self.config = json.load(f)
70
+ if not email or not password or email == 'your-email@example.com' or password == 'your-password':
71
+ print("\n[SoulSync] ========================================")
72
+ print("[SoulSync] Please configure your account first / 请先配置账号")
73
+ print("[SoulSync] ========================================")
74
+ print("[SoulSync] Edit config file / 编辑配置文件:")
75
+ print(f" {config_path}")
76
+ print("[SoulSync] Set your email and password, then restart / 填写邮箱和密码后重启")
77
+ print("[SoulSync] ========================================\n")
78
+ sys.exit(0)
80
79
 
81
- # 处理 workspace 路径
82
80
  workspace = self.config.get('workspace', './workspace')
83
81
  if workspace.startswith('./'):
84
82
  workspace = workspace[2:]
@@ -89,62 +87,77 @@ class SoulSyncPlugin:
89
87
  self.config['workspace'] = workspace
90
88
  self.config['watch_files'] = watch_files
91
89
 
92
- print(f"Config loaded:")
93
- print(f" Cloud URL: {self.config.get('cloud_url')}")
94
- print(f" Workspace: {workspace}")
95
- print(f" Watch files: {watch_files}")
96
-
97
- def _interactive_setup(self):
98
- """交互式设置:引导用户登录或注册"""
99
- from register import Register, Login
100
- from interactive_auth import interactive_setup
90
+ print(f"[SoulSync] Config loaded:")
91
+ print(f" Cloud URL: {self.config.get('cloud_url')}")
92
+ print(f" Workspace: {workspace}")
93
+ print(f" Watch files: {watch_files}")
94
+
95
+ def _save_auth_to_config(self, auth_result):
96
+ """保存认证结果到 config.json"""
97
+ config_path = os.path.normpath(os.path.join(PLUGIN_DIR, 'config.json'))
101
98
 
102
- while True:
103
- print("\n" + "=" * 50)
104
- print("Welcome / 欢迎使用 SoulSync")
105
- print("=" * 50)
106
- print("1. Login / 登录(已有账号)")
107
- print("2. Register / 注册(新用户)")
108
- print("3. Exit / 退出")
109
-
110
- choice = input("Choose / 选择 (1/2/3): ").strip()
111
-
112
- if choice == '1':
113
- success = self._interactive_login()
114
- if success:
115
- return True
116
- elif choice == '2':
117
- success = self._interactive_register()
118
- if success:
119
- return True
120
- elif choice == '3':
121
- print("Exiting... / 退出...")
122
- sys.exit(0)
123
- else:
124
- print("Invalid choice / 无效选择")
99
+ try:
100
+ with open(config_path, 'r', encoding='utf-8') as f:
101
+ config = json.load(f)
102
+ except:
103
+ config = {}
104
+
105
+ # 保存 email 和 password(如果 auth_result 包含)
106
+ if 'user' in auth_result:
107
+ config['email'] = auth_result['user'].get('email', '')
108
+
109
+ # 保存 token
110
+ if 'token' in auth_result:
111
+ config['token'] = auth_result['token']
112
+
113
+ with open(config_path, 'w', encoding='utf-8') as f:
114
+ json.dump(config, f, indent=2, ensure_ascii=False)
115
+
116
+ print("[SoulSync] Auth info saved to config.json")
117
+
118
+ def run_setup(self):
119
+ """交互式设置:注册或登录"""
120
+ print("\n[SoulSync] ========================================")
121
+ print("[SoulSync] Welcome to SoulSync! / 欢迎使用 SoulSync!")
122
+ print("[SoulSync] ========================================")
123
+ print("[SoulSync] 1. Register / 注册")
124
+ print("[SoulSync] 2. Login / 登录")
125
+ print("[SoulSync] ========================================")
126
+
127
+ choice = input("[SoulSync] Choose / 选择 (1/2): ").strip()
128
+
129
+ if choice == '1':
130
+ return self._interactive_register()
131
+ elif choice == '2':
132
+ return self._interactive_login()
133
+ else:
134
+ print("[SoulSync] Invalid choice / 无效选择")
135
+ sys.exit(0)
125
136
 
126
137
  def _interactive_login(self):
127
138
  """交互式登录(带重试)"""
139
+ from client import OpenClawClient
140
+
128
141
  max_retries = 5
129
142
  retry_count = 0
130
143
 
131
144
  while retry_count < max_retries:
132
145
  print("\n--- Login / 登录 ---")
133
- email = input("Email / 邮箱: ").strip()
146
+ email = input("[SoulSync] Email / 邮箱: ").strip()
134
147
  if not email:
135
- print("Email cannot be empty / 邮箱不能为空")
148
+ print("[SoulSync] Email cannot be empty / 邮箱不能为空")
136
149
  continue
137
150
 
138
- password = getpass.getpass("Password / 密码: ")
151
+ password = getpass.getpass("[SoulSync] Password / 密码: ")
139
152
  if not password:
140
- print("Password cannot be empty / 密码不能为空")
153
+ print("[SoulSync] Password cannot be empty / 密码不能为空")
141
154
  continue
142
155
 
143
156
  try:
144
157
  temp_client = OpenClawClient(self.config)
145
158
  result = temp_client.authenticate(email, password)
146
159
  if result:
147
- print("\n Login successful! / 登录成功!")
160
+ print("\n[SoulSync] Login successful! / 登录成功!")
148
161
  self._save_auth_to_config(result)
149
162
  return True
150
163
  except Exception as e:
@@ -153,67 +166,65 @@ class SoulSyncPlugin:
153
166
  error_msg = str(e)
154
167
 
155
168
  if "429" in error_msg or "too many" in error_msg.lower():
156
- print(f"\n❌ {e}")
157
- print("\nToo many failed attempts / 登录失败次数过多")
158
- print("Exiting... / 退出...")
169
+ print(f"\n[SoulSync] ❌ {e}")
170
+ print("\n[SoulSync] Too many failed attempts / 登录失败次数过多")
171
+ print("[SoulSync] Exiting... / 退出...")
159
172
  sys.exit(0)
160
173
 
161
174
  if remaining > 0:
162
- print(f"\n❌ Login failed: {e} / 登录失败: {e}")
163
- print(f"Remaining attempts / 剩余尝试次数: {remaining}")
175
+ print(f"\n[SoulSync] ❌ Login failed: {e} / 登录失败: {e}")
176
+ print(f"[SoulSync] Remaining attempts / 剩余尝试次数: {remaining}")
164
177
  else:
165
- print(f"\n❌ Login failed: {e} / 登录失败: {e}")
178
+ print(f"\n[SoulSync] ❌ Login failed: {e} / 登录失败: {e}")
166
179
 
167
- print("\n❌ Too many failed attempts. Please try again in 15 minutes. / 登录失败次数过多,请15分钟后再试")
168
- print("Exiting... / 退出...")
180
+ print("\n[SoulSync] ❌ Too many failed attempts. Please try again in 15 minutes. / 登录失败次数过多,请15分钟后再试")
181
+ print("[SoulSync] Exiting... / 退出...")
169
182
  sys.exit(0)
170
183
 
171
184
  def _interactive_register(self):
172
185
  """交互式注册(带重试)"""
173
- from register import Register
186
+ from client import OpenClawClient
174
187
 
175
188
  max_retries = 5
176
189
  retry_count = 0
177
190
 
178
191
  while retry_count < max_retries:
179
192
  print("\n--- Register / 注册 ---")
180
- email = input("Email / 邮箱: ").strip()
193
+ email = input("[SoulSync] Email / 邮箱: ").strip()
181
194
  if not email or '@' not in email:
182
- print("Invalid email / 无效邮箱")
195
+ print("[SoulSync] Invalid email / 无效邮箱")
183
196
  continue
184
197
 
185
- password = getpass.getpass("Password / 密码: ")
198
+ password = getpass.getpass("[SoulSync] Password / 密码: ")
186
199
  if len(password) < 6:
187
- print("Password must be at least 6 characters / 密码至少6位")
200
+ print("[SoulSync] Password must be at least 6 characters / 密码至少6位")
188
201
  continue
189
202
 
190
- password2 = getpass.getpass("Confirm password / 确认密码: ")
203
+ password2 = getpass.getpass("[SoulSync] Confirm password / 确认密码: ")
191
204
  if password != password2:
192
- print("Passwords do not match / 两次密码不一致")
205
+ print("[SoulSync] Passwords do not match / 两次密码不一致")
193
206
  continue
194
207
 
195
- # 发送验证码
196
- print(f"\nSending verification code to {email}...")
208
+ print(f"\n[SoulSync] Sending verification code to {email}...")
197
209
  try:
198
210
  temp_client = OpenClawClient(self.config)
199
211
  temp_client.send_verification_code(email)
200
- print(" Verification code sent! / 验证码已发送!")
212
+ print("[SoulSync] Verification code sent! / 验证码已发送!")
201
213
  except Exception as e:
202
- print(f"❌ Failed to send code: {e}")
214
+ print(f"[SoulSync] ❌ Failed to send code: {e}")
203
215
  continue
204
216
 
205
- # 验证码输入(带重试)
206
217
  code_retry = 0
207
218
  while code_retry < max_retries:
208
- code = input(f"Enter verification code / 请输入验证码 ({max_retries - code_retry} attempts left): ").strip()
219
+ code = input(f"[SoulSync] Enter code / 输入验证码 ({max_retries - code_retry} attempts left): ").strip()
209
220
  if len(code) != 6 or not code.isdigit():
210
221
  code_retry += 1
211
- print("Invalid code format / 验证码格式错误")
222
+ print("[SoulSync] Invalid code format / 验证码格式错误")
212
223
  continue
213
224
 
214
225
  try:
215
226
  result = temp_client.register(email, password, code)
216
- print("\n Registration successful! / 注册成功!")
227
+ print("\n[SoulSync] Registration successful! / 注册成功!")
217
228
  self._save_auth_to_config(result)
218
229
  return True
219
230
  except Exception as e:
@@ -221,62 +232,41 @@ class SoulSyncPlugin:
221
232
  remaining_code = max_retries - code_retry
222
233
  if "invalid" in str(e).lower() or "expired" in str(e).lower():
223
234
  if remaining_code > 0:
224
- print(f"❌ Invalid or expired code: {e}")
225
- print(f"Remaining attempts / 剩余尝试: {remaining_code}")
235
+ print(f"[SoulSync] ❌ Invalid or expired code: {e}")
236
+ print(f"[SoulSync] Remaining attempts / 剩余尝试: {remaining_code}")
226
237
  else:
227
- print("❌ Too many code attempts / 验证码错误次数过多")
238
+ print("[SoulSync] ❌ Too many code attempts / 验证码错误次数过多")
228
239
  break
229
240
  else:
230
- print(f"❌ Registration failed: {e}")
241
+ print(f"[SoulSync] ❌ Registration failed: {e}")
231
242
  break
232
243
 
233
244
  if code_retry >= max_retries:
234
- print("\nToo many code verification failures. Would you like to:")
235
- print("1. Resend code / 重新发送验证码")
236
- print("2. Start over / 重新开始")
237
- print("3. Exit / 退出")
245
+ print("\n[SoulSync] Too many code verification failures.")
246
+ print("[SoulSync] 1. Resend code / 重新发送验证码")
247
+ print("[SoulSync] 2. Start over / 重新开始")
248
+ print("[SoulSync] 3. Exit / 退出")
238
249
 
239
- sub_choice = input("Choose / 选择 (1/2/3): ").strip()
250
+ sub_choice = input("[SoulSync] Choose / 选择 (1/2/3): ").strip()
240
251
  if sub_choice == '1':
241
- retry_count = 0 # 重置主重试计数
252
+ retry_count = 0
242
253
  continue
243
254
  elif sub_choice == '2':
244
255
  retry_count = 0
245
- break # 跳出内层循环,继续外层循环
256
+ break
246
257
  else:
247
- print("Exiting... / 退出...")
258
+ print("[SoulSync] Exiting... / 退出...")
248
259
  sys.exit(0)
249
260
 
250
- print("\n❌ Too many registration attempts / 注册尝试次数过多")
251
- print("Exiting... / 退出...")
252
- sys.exit(0)
261
+ print("\n[SoulSync] ❌ Too many registration attempts / 注册尝试次数过多")
262
+ print("[SoulSync] Exiting... / 退出...")
263
+ sys.exit(0)
253
264
 
254
- def _save_auth_to_config(self, auth_result):
255
- """保存认证结果到 config.json"""
256
- config_path = os.path.normpath(os.path.join(PLUGIN_DIR, 'config.json'))
257
-
258
- try:
259
- with open(config_path, 'r', encoding='utf-8') as f:
260
- config = json.load(f)
261
- except:
262
- config = {}
263
-
264
- # 保存 email 和 password(如果 auth_result 包含)
265
- if 'user' in auth_result:
266
- config['email'] = auth_result['user'].get('email', '')
267
-
268
- # 保存 token
269
- if 'token' in auth_result:
270
- config['token'] = auth_result['token']
271
-
272
- with open(config_path, 'w', encoding='utf-8') as f:
273
- json.dump(config, f, indent=2, ensure_ascii=False)
274
-
275
- print("Auth info saved to config.json")
276
-
277
265
  def initialize(self):
278
266
  """初始化组件"""
279
- print("\n=== Initializing SoulSync Plugin ===\n")
267
+ print("\n[SoulSync] ========================================")
268
+ print("[SoulSync] Initializing SoulSync Plugin")
269
+ print("[SoulSync] ========================================\n")
280
270
 
281
271
  self.client = OpenClawClient(self.config)
282
272
 
@@ -284,38 +274,49 @@ class SoulSyncPlugin:
284
274
  if token:
285
275
  try:
286
276
  profile = self.client.get_profile()
287
- print(f"Using existing token, user: {profile.get('email', 'unknown')}")
277
+ print(f"[SoulSync] Using existing token, user: {profile.get('email', 'unknown')}")
288
278
  except Exception as e:
289
- print(f"Token invalid / 令牌无效, re-authenticating: {e}")
279
+ print(f"[SoulSync] Token invalid, re-authenticating: {e}")
290
280
  token = None
291
281
 
292
282
  if not token:
293
- print("\n=== Token invalid - Please login or register / 令牌无效,请先登录或注册 ===\n")
294
- print("1. Login / 登录(已有账号)")
295
- print("2. Register / 注册(新用户)")
296
-
297
- choice = input("Choose (1/2): ").strip()
298
-
299
- if choice == '1':
300
- login = Login(self.client)
301
- result = login.run()
302
- elif choice == '2':
303
- register = Register(self.client)
304
- result = register.run()
305
- else:
306
- print("Invalid choice / 无效选择")
307
- sys.exit(1)
283
+ email = self.config.get('email', '').strip()
284
+ password = self.config.get('password', '').strip()
285
+
286
+ print("[SoulSync] No valid token, attempting auto-login...")
287
+ try:
288
+ result = self.client.authenticate(email, password)
289
+ if result:
290
+ print("[SoulSync] Login successful! / 登录成功!")
291
+ self._save_auth_to_config(result)
292
+ token = self.client.token
293
+ except Exception as e:
294
+ error_msg = str(e)
295
+ print(f"[SoulSync] Login failed: {e}")
296
+
297
+ if "429" in error_msg or "too many" in error_msg.lower():
298
+ print("\n[SoulSync] ========================================")
299
+ print("[SoulSync] Too many failed attempts. Please try again later / 登录失败次数过多,请稍后再试")
300
+ print("[SoulSync] ========================================\n")
301
+ else:
302
+ print("\n[SoulSync] ========================================")
303
+ print("[SoulSync] Login failed: invalid email or password / 登录失败:邮箱或密码错误")
304
+ print("[SoulSync] Please check your config file / 请检查配置文件:")
305
+ print(f" {os.path.normpath(os.path.join(PLUGIN_DIR, 'config.json'))}")
306
+ print("[SoulSync] ========================================\n")
307
+
308
+ sys.exit(0)
308
309
 
309
310
  email = self.config.get('email')
310
311
  password = self.config.get('password')
311
312
 
312
313
  try:
313
314
  profile = self.client.get_profile()
314
- print(f"\nLogged in as: {profile.get('email')}")
315
+ print(f"\n[SoulSync] Logged in as: {profile.get('email')}")
315
316
  subscription = profile.get('subscription', {})
316
- print(f"Subscription: {subscription.get('status')} (days remaining: {subscription.get('daysRemaining', 0)})\n")
317
+ print(f"[SoulSync] Subscription: {subscription.get('status')} (days remaining: {subscription.get('daysRemaining', 0)})\n")
317
318
  except Exception as e:
318
- print(f"Warning: Could not get profile: {e}")
319
+ print(f"[SoulSync] Warning: Could not get profile: {e}")
319
320
 
320
321
  # 版本管理器
321
322
  versions_file = os.path.normpath(os.path.join(PLUGIN_DIR, 'versions.json'))
@@ -445,7 +446,34 @@ class SoulSyncPlugin:
445
446
  print("Plugin shutdown complete")
446
447
  def main():
447
448
  """主函数"""
449
+ parser = argparse.ArgumentParser(description='SoulSync Plugin')
450
+ parser.add_argument('--setup', action='store_true', help='Run interactive setup (register/login)')
451
+ parser.add_argument('--start', action='store_true', help='Start sync service (auto-login from config)')
452
+
453
+ args = parser.parse_args()
454
+
448
455
  plugin = SoulSyncPlugin()
456
+
457
+ if args.setup:
458
+ plugin.load_config()
459
+ plugin.run_setup()
460
+ print("\n[SoulSync] ✓ Setup complete! Run 'openclaw soulsync:start' to begin syncing.")
461
+ print("[SoulSync] 设置完成!运行 'openclaw soulsync:start' 开始同步。")
462
+ sys.exit(0)
463
+
464
+ plugin.load_config()
465
+
466
+ email = plugin.config.get('email', '').strip()
467
+ password = plugin.config.get('password', '').strip()
468
+
469
+ if not email or not password:
470
+ print("\n[SoulSync] ========================================")
471
+ print("[SoulSync] Not configured. Run 'openclaw soulsync:setup' first.")
472
+ print("[SoulSync] 尚未配置,请先运行 'openclaw soulsync:setup'")
473
+ print("[SoulSync] ========================================\n")
474
+ sys.exit(0)
475
+
476
+ plugin.initialize()
449
477
  plugin.run()
450
478
  if __name__ == '__main__':
451
479
  main()