soulsync 1.0.9 → 1.0.11
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/package.json +1 -1
- package/src/main.py +162 -150
package/package.json
CHANGED
package/src/main.py
CHANGED
|
@@ -67,16 +67,6 @@ class SoulSyncPlugin:
|
|
|
67
67
|
self.config['cloud_url'] = 'https://soulsync.work'
|
|
68
68
|
print("[SoulSync] Cloud URL not set, using default: https://soulsync.work")
|
|
69
69
|
|
|
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)
|
|
79
|
-
|
|
80
70
|
workspace = self.config.get('workspace', './workspace')
|
|
81
71
|
if workspace.startswith('./'):
|
|
82
72
|
workspace = workspace[2:]
|
|
@@ -116,151 +106,166 @@ class SoulSyncPlugin:
|
|
|
116
106
|
print("[SoulSync] Auth info saved to config.json")
|
|
117
107
|
|
|
118
108
|
def run_setup(self):
|
|
119
|
-
"""
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
109
|
+
"""交互式设置:注册或登录(带循环)"""
|
|
110
|
+
while True:
|
|
111
|
+
print("\n[SoulSync] ========================================")
|
|
112
|
+
print("[SoulSync] Welcome to SoulSync! / 欢迎使用 SoulSync!")
|
|
113
|
+
print("[SoulSync] ========================================")
|
|
114
|
+
print("[SoulSync] 1. Register / 注册")
|
|
115
|
+
print("[SoulSync] 2. Login / 登录")
|
|
116
|
+
print("[SoulSync] 0. Exit / 退出")
|
|
117
|
+
print("[SoulSync] ========================================")
|
|
118
|
+
|
|
119
|
+
try:
|
|
120
|
+
choice = input("[SoulSync] Choose / 选择 (0/1/2): ").strip()
|
|
121
|
+
except KeyboardInterrupt:
|
|
122
|
+
print("\n[SoulSync] Cancelled by user. Goodbye! / 已取消,再见!")
|
|
123
|
+
sys.exit(0)
|
|
124
|
+
|
|
125
|
+
if choice == '1':
|
|
126
|
+
result = self._interactive_register()
|
|
127
|
+
if result:
|
|
128
|
+
return result
|
|
129
|
+
elif choice == '2':
|
|
130
|
+
result = self._interactive_login()
|
|
131
|
+
if result:
|
|
132
|
+
return result
|
|
133
|
+
elif choice == '0':
|
|
134
|
+
print("[SoulSync] Goodbye! / 再见!")
|
|
135
|
+
sys.exit(0)
|
|
136
|
+
else:
|
|
137
|
+
print("[SoulSync] Invalid choice / 无效选择")
|
|
136
138
|
|
|
137
139
|
def _interactive_login(self):
|
|
138
|
-
"""
|
|
140
|
+
"""交互式登录(失败返回 None,由主循环处理)"""
|
|
139
141
|
from client import OpenClawClient
|
|
140
142
|
|
|
141
|
-
|
|
142
|
-
retry_count = 0
|
|
143
|
+
print("\n--- Login / 登录 ---")
|
|
143
144
|
|
|
144
|
-
|
|
145
|
-
print("\n--- Login / 登录 ---")
|
|
145
|
+
try:
|
|
146
146
|
email = input("[SoulSync] Email / 邮箱: ").strip()
|
|
147
147
|
if not email:
|
|
148
148
|
print("[SoulSync] Email cannot be empty / 邮箱不能为空")
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
return None
|
|
150
|
+
except KeyboardInterrupt:
|
|
151
|
+
print("\n[SoulSync] Cancelled. Returning to menu... / 已取消,返回菜单...")
|
|
152
|
+
return None
|
|
153
|
+
|
|
154
|
+
try:
|
|
151
155
|
password = getpass.getpass("[SoulSync] Password / 密码: ")
|
|
152
156
|
if not password:
|
|
153
157
|
print("[SoulSync] Password cannot be empty / 密码不能为空")
|
|
154
|
-
|
|
158
|
+
return None
|
|
159
|
+
except KeyboardInterrupt:
|
|
160
|
+
print("\n[SoulSync] Cancelled. Returning to menu... / 已取消,返回菜单...")
|
|
161
|
+
return None
|
|
162
|
+
|
|
163
|
+
try:
|
|
164
|
+
temp_client = OpenClawClient(self.config)
|
|
165
|
+
result = temp_client.authenticate(email, password)
|
|
166
|
+
if result:
|
|
167
|
+
print("\n[SoulSync] ✓ Login successful! / 登录成功!")
|
|
168
|
+
self._save_auth_to_config(result)
|
|
169
|
+
return True
|
|
170
|
+
except Exception as e:
|
|
171
|
+
error_msg = str(e)
|
|
155
172
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
remaining = max_retries - retry_count
|
|
166
|
-
error_msg = str(e)
|
|
167
|
-
|
|
168
|
-
if "429" in error_msg or "too many" in error_msg.lower():
|
|
169
|
-
print(f"\n[SoulSync] ❌ {e}")
|
|
170
|
-
print("\n[SoulSync] Too many failed attempts / 登录失败次数过多")
|
|
171
|
-
print("[SoulSync] Exiting... / 退出...")
|
|
172
|
-
sys.exit(0)
|
|
173
|
-
|
|
174
|
-
if remaining > 0:
|
|
175
|
-
print(f"\n[SoulSync] ❌ Login failed: {e} / 登录失败: {e}")
|
|
176
|
-
print(f"[SoulSync] Remaining attempts / 剩余尝试次数: {remaining}")
|
|
177
|
-
else:
|
|
178
|
-
print(f"\n[SoulSync] ❌ Login failed: {e} / 登录失败: {e}")
|
|
173
|
+
if "429" in error_msg or "too many" in error_msg.lower():
|
|
174
|
+
print(f"\n[SoulSync] ❌ {e}")
|
|
175
|
+
print("\n[SoulSync] Too many failed attempts. Please try again later / 登录失败次数过多,请稍后再试")
|
|
176
|
+
print("[SoulSync] Exiting... / 退出...")
|
|
177
|
+
sys.exit(0)
|
|
178
|
+
|
|
179
|
+
print(f"\n[SoulSync] ❌ Login failed: {e} / 登录失败: {e}")
|
|
180
|
+
print("[SoulSync] Returning to menu... / 返回菜单...")
|
|
181
|
+
return None
|
|
179
182
|
|
|
180
|
-
print("
|
|
181
|
-
print("[SoulSync]
|
|
182
|
-
|
|
183
|
+
print("[SoulSync] ❌ Login failed / 登录失败")
|
|
184
|
+
print("[SoulSync] Returning to menu... / 返回菜单...")
|
|
185
|
+
return None
|
|
183
186
|
|
|
184
187
|
def _interactive_register(self):
|
|
185
|
-
"""
|
|
188
|
+
"""交互式注册(失败返回 None)"""
|
|
186
189
|
from client import OpenClawClient
|
|
187
190
|
|
|
188
|
-
|
|
189
|
-
retry_count = 0
|
|
191
|
+
print("\n--- Register / 注册 ---")
|
|
190
192
|
|
|
191
|
-
|
|
192
|
-
print("\n--- Register / 注册 ---")
|
|
193
|
+
try:
|
|
193
194
|
email = input("[SoulSync] Email / 邮箱: ").strip()
|
|
194
195
|
if not email or '@' not in email:
|
|
195
196
|
print("[SoulSync] Invalid email / 无效邮箱")
|
|
196
|
-
|
|
197
|
+
return None
|
|
198
|
+
except KeyboardInterrupt:
|
|
199
|
+
print("\n[SoulSync] Cancelled. Returning to menu... / 已取消,返回菜单...")
|
|
200
|
+
return None
|
|
201
|
+
|
|
202
|
+
password = None
|
|
203
|
+
while password is None:
|
|
204
|
+
try:
|
|
205
|
+
password = getpass.getpass("[SoulSync] Password / 密码: ")
|
|
206
|
+
if len(password) < 6:
|
|
207
|
+
print("[SoulSync] Password must be at least 6 characters / 密码至少6位")
|
|
208
|
+
password = None
|
|
209
|
+
continue
|
|
210
|
+
except KeyboardInterrupt:
|
|
211
|
+
print("\n[SoulSync] Cancelled. Returning to menu... / 已取消,返回菜单...")
|
|
212
|
+
return None
|
|
197
213
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
214
|
+
try:
|
|
215
|
+
password2 = getpass.getpass("[SoulSync] Confirm password / 确认密码: ")
|
|
216
|
+
except KeyboardInterrupt:
|
|
217
|
+
print("\n[SoulSync] Cancelled. Returning to menu... / 已取消,返回菜单...")
|
|
218
|
+
return None
|
|
202
219
|
|
|
203
|
-
password2 = getpass.getpass("[SoulSync] Confirm password / 确认密码: ")
|
|
204
220
|
if password != password2:
|
|
205
221
|
print("[SoulSync] Passwords do not match / 两次密码不一致")
|
|
222
|
+
password = None
|
|
223
|
+
|
|
224
|
+
print(f"\n[SoulSync] Sending verification code to {email}...")
|
|
225
|
+
try:
|
|
226
|
+
temp_client = OpenClawClient(self.config)
|
|
227
|
+
temp_client.send_verification_code(email)
|
|
228
|
+
print("[SoulSync] ✓ Verification code sent! / 验证码已发送!")
|
|
229
|
+
except Exception as e:
|
|
230
|
+
print(f"[SoulSync] ❌ Failed to send code: {e}")
|
|
231
|
+
print("[SoulSync] Returning to menu... / 返回菜单...")
|
|
232
|
+
return None
|
|
233
|
+
|
|
234
|
+
code_success = False
|
|
235
|
+
code_retry = 0
|
|
236
|
+
max_code_retries = 3
|
|
237
|
+
|
|
238
|
+
while code_retry < max_code_retries and not code_success:
|
|
239
|
+
try:
|
|
240
|
+
code = input(f"[SoulSync] Enter code / 输入验证码 ({max_code_retries - code_retry} left): ").strip()
|
|
241
|
+
except KeyboardInterrupt:
|
|
242
|
+
print("\n[SoulSync] Cancelled. Returning to menu... / 已取消,返回菜单...")
|
|
243
|
+
return None
|
|
244
|
+
|
|
245
|
+
if len(code) != 6 or not code.isdigit():
|
|
246
|
+
code_retry += 1
|
|
247
|
+
print("[SoulSync] Invalid code format / 验证码格式错误")
|
|
206
248
|
continue
|
|
207
249
|
|
|
208
|
-
print(f"\n[SoulSync] Sending verification code to {email}...")
|
|
209
250
|
try:
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
251
|
+
result = temp_client.register(email, password, code)
|
|
252
|
+
print("\n[SoulSync] ✓ Registration successful! / 注册成功!")
|
|
253
|
+
self._save_auth_to_config(result)
|
|
254
|
+
return True
|
|
213
255
|
except Exception as e:
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
code = input(f"[SoulSync] Enter code / 输入验证码 ({max_retries - code_retry} attempts left): ").strip()
|
|
220
|
-
if len(code) != 6 or not code.isdigit():
|
|
221
|
-
code_retry += 1
|
|
222
|
-
print("[SoulSync] Invalid code format / 验证码格式错误")
|
|
223
|
-
continue
|
|
224
|
-
|
|
225
|
-
try:
|
|
226
|
-
result = temp_client.register(email, password, code)
|
|
227
|
-
print("\n[SoulSync] ✓ Registration successful! / 注册成功!")
|
|
228
|
-
self._save_auth_to_config(result)
|
|
229
|
-
return True
|
|
230
|
-
except Exception as e:
|
|
231
|
-
code_retry += 1
|
|
232
|
-
remaining_code = max_retries - code_retry
|
|
233
|
-
if "invalid" in str(e).lower() or "expired" in str(e).lower():
|
|
234
|
-
if remaining_code > 0:
|
|
235
|
-
print(f"[SoulSync] ❌ Invalid or expired code: {e}")
|
|
236
|
-
print(f"[SoulSync] Remaining attempts / 剩余尝试: {remaining_code}")
|
|
237
|
-
else:
|
|
238
|
-
print("[SoulSync] ❌ Too many code attempts / 验证码错误次数过多")
|
|
239
|
-
break
|
|
256
|
+
code_retry += 1
|
|
257
|
+
if "invalid" in str(e).lower() or "expired" in str(e).lower():
|
|
258
|
+
if code_retry < max_code_retries:
|
|
259
|
+
print(f"[SoulSync] ❌ Invalid or expired code: {e}")
|
|
260
|
+
print(f"[SoulSync] Remaining attempts / 剩余尝试: {max_code_retries - code_retry}")
|
|
240
261
|
else:
|
|
241
|
-
print(
|
|
242
|
-
break
|
|
243
|
-
|
|
244
|
-
if code_retry >= max_retries:
|
|
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 / 退出")
|
|
249
|
-
|
|
250
|
-
sub_choice = input("[SoulSync] Choose / 选择 (1/2/3): ").strip()
|
|
251
|
-
if sub_choice == '1':
|
|
252
|
-
retry_count = 0
|
|
253
|
-
continue
|
|
254
|
-
elif sub_choice == '2':
|
|
255
|
-
retry_count = 0
|
|
256
|
-
break
|
|
262
|
+
print("[SoulSync] ❌ Too many code attempts / 验证码错误次数过多")
|
|
257
263
|
else:
|
|
258
|
-
print("[SoulSync]
|
|
259
|
-
sys.exit(0)
|
|
264
|
+
print(f"[SoulSync] ❌ Registration failed: {e}")
|
|
260
265
|
|
|
261
|
-
print("\n[SoulSync]
|
|
262
|
-
print("[SoulSync]
|
|
263
|
-
|
|
266
|
+
print("\n[SoulSync] Too many code verification failures.")
|
|
267
|
+
print("[SoulSync] Returning to menu... / 返回菜单...")
|
|
268
|
+
return None
|
|
264
269
|
|
|
265
270
|
def initialize(self):
|
|
266
271
|
"""初始化组件"""
|
|
@@ -446,34 +451,41 @@ class SoulSyncPlugin:
|
|
|
446
451
|
print("Plugin shutdown complete")
|
|
447
452
|
def main():
|
|
448
453
|
"""主函数"""
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
454
|
+
try:
|
|
455
|
+
parser = argparse.ArgumentParser(description='SoulSync Plugin')
|
|
456
|
+
parser.add_argument('--setup', action='store_true', help='Run interactive setup (register/login)')
|
|
457
|
+
parser.add_argument('--start', action='store_true', help='Start sync service (auto-login from config)')
|
|
458
|
+
|
|
459
|
+
args = parser.parse_args()
|
|
460
|
+
|
|
461
|
+
plugin = SoulSyncPlugin()
|
|
462
|
+
|
|
463
|
+
if args.setup:
|
|
464
|
+
try:
|
|
465
|
+
plugin.load_config()
|
|
466
|
+
plugin.run_setup()
|
|
467
|
+
print("\n[SoulSync] ✓ Setup complete! Run 'openclaw soulsync:start' to begin syncing.")
|
|
468
|
+
print("[SoulSync] 设置完成!运行 'openclaw soulsync:start' 开始同步。")
|
|
469
|
+
except KeyboardInterrupt:
|
|
470
|
+
print("\n[SoulSync] Cancelled by user. Goodbye! / 已取消,再见!")
|
|
471
|
+
sys.exit(0)
|
|
472
|
+
|
|
458
473
|
plugin.load_config()
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
print("[SoulSync]
|
|
474
|
+
|
|
475
|
+
email = plugin.config.get('email', '').strip()
|
|
476
|
+
password = plugin.config.get('password', '').strip()
|
|
477
|
+
|
|
478
|
+
if not email or not password:
|
|
479
|
+
print("\n[SoulSync] ========================================")
|
|
480
|
+
print("[SoulSync] Not configured. Run 'openclaw soulsync:setup' first.")
|
|
481
|
+
print("[SoulSync] 尚未配置,请先运行 'openclaw soulsync:setup'")
|
|
482
|
+
print("[SoulSync] ========================================\n")
|
|
483
|
+
sys.exit(0)
|
|
484
|
+
|
|
485
|
+
plugin.initialize()
|
|
486
|
+
plugin.run()
|
|
487
|
+
except KeyboardInterrupt:
|
|
488
|
+
print("\n[SoulSync] Cancelled by user. Goodbye! / 已取消,再见!")
|
|
474
489
|
sys.exit(0)
|
|
475
|
-
|
|
476
|
-
plugin.initialize()
|
|
477
|
-
plugin.run()
|
|
478
490
|
if __name__ == '__main__':
|
|
479
491
|
main()
|