codedthemes-cli 0.1.15__tar.gz → 0.1.16__tar.gz

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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codedthemes-cli
3
- Version: 0.1.15
3
+ Version: 0.1.16
4
4
  Summary: CLI tool for Code Theme and Integration
5
5
  Author: codedthemes
6
6
  Requires-Python: >=3.10
@@ -240,10 +240,29 @@ def handle_init():
240
240
  sys.exit(1)
241
241
 
242
242
 
243
+ def clean_remote_path(p: str) -> str:
244
+ """
245
+ Strips the deeply nested remote container path if present.
246
+ e.g., 'home/runner/work/<owner>/<repo>/src/...' -> 'src/...'
247
+ """
248
+ if not p: return p
249
+ p = p.replace('\\', '/')
250
+ if p.startswith('/'): p = p[1:]
251
+ if p.startswith('home/runner/work/'):
252
+ parts = p.split('/')
253
+ if len(parts) > 4: # e.g. ['home', 'runner', 'work', 'owner', 'repo', 'src', ...]
254
+ return '/'.join(parts[5:])
255
+ return p
256
+
243
257
  def handle_apply(query: str):
244
258
  """
245
259
  Plans and executes changes based on a natural language query.
246
260
  """
261
+ if not query or not query.strip():
262
+ print("✖ Error: Query cannot be empty.")
263
+ print("💡 Example: codedthemes apply \"Update the primary color to deep purple\"")
264
+ return
265
+
247
266
  try:
248
267
  repo_root = detect_repo_root()
249
268
  repo_abs_path = os.path.abspath(repo_root)
@@ -335,10 +354,10 @@ def handle_apply(query: str):
335
354
  print(f"✖ Planning failed: {plan.get('message', 'Unknown error')}")
336
355
  return
337
356
 
338
- target_files = plan.get("files_to_modify", [])
357
+ target_files = [clean_remote_path(f) for f in plan.get("files_to_modify", [])]
339
358
  instructions = plan.get("plan_instructions", [])
340
- files_to_create = plan.get("files_to_create", [])
341
- files_to_delete = plan.get("files_to_delete", [])
359
+ files_to_create = [clean_remote_path(f) for f in plan.get("files_to_create", [])]
360
+ files_to_delete = [clean_remote_path(f) for f in plan.get("files_to_delete", [])]
342
361
 
343
362
  if not any([target_files, files_to_create, files_to_delete, instructions]):
344
363
  print("Information: No changes planned.")
@@ -396,41 +415,52 @@ def handle_apply(query: str):
396
415
  updates = res_data.get("updates_for_local", [])
397
416
  deletes = res_data.get("deleted_files", [])
398
417
 
399
- if updates or deletes:
400
- for item in updates:
401
- rel_path, code = item.get("path"), item.get("code")
402
- if not rel_path or code is None: continue
403
- abs_path = os.path.abspath(os.path.join(repo_abs_path, rel_path.replace('/', os.sep)))
418
+ # 1. Apply local updates
419
+ for item in updates:
420
+ rel_path = clean_remote_path(item.get("path"))
421
+ code = item.get("code")
422
+ if not rel_path or code is None: continue
423
+ abs_path = os.path.abspath(os.path.join(repo_abs_path, rel_path.replace('/', os.sep)))
424
+
425
+ try:
426
+ os.makedirs(os.path.dirname(abs_path), exist_ok=True)
427
+ with open(abs_path, 'w', encoding='utf-8') as f:
428
+ f.write(code)
429
+ print(f"✔ Updated: {rel_path}")
430
+ except Exception as e:
431
+ print(f"✖ Error writing {rel_path}: {e}")
404
432
 
433
+ # 2. Apply local deletions
434
+ for rel_path_raw in (deletes or []):
435
+ rel_path = clean_remote_path(rel_path_raw)
436
+ abs_path = os.path.normpath(os.path.join(repo_abs_path, rel_path.replace('/', os.sep)))
437
+ if os.path.exists(abs_path) and abs_path.startswith(os.path.abspath(repo_abs_path)):
405
438
  try:
406
- os.makedirs(os.path.dirname(abs_path), exist_ok=True)
407
- with open(abs_path, 'w', encoding='utf-8') as f:
408
- f.write(code)
409
- print(f"✔ Updated: {rel_path}")
410
- except Exception as e:
411
- print(f"✖ Error writing {rel_path}: {e}")
412
-
413
- for rel_path in (deletes or []):
414
- abs_path = os.path.normpath(os.path.join(repo_abs_path, rel_path.replace('/', os.sep)))
415
- if os.path.exists(abs_path) and abs_path.startswith(os.path.abspath(repo_abs_path)):
416
- try:
417
- if os.path.isfile(abs_path): os.remove(abs_path)
418
- elif os.path.isdir(abs_path): shutil.rmtree(abs_path)
419
- print(f"✔ Deleted: {rel_path}")
420
- except: pass
421
-
439
+ if os.path.isfile(abs_path): os.remove(abs_path)
440
+ elif os.path.isdir(abs_path): shutil.rmtree(abs_path)
441
+ print(f"✔ Deleted: {rel_path}")
442
+ except: pass
443
+
444
+ # 3. Synchronize state
445
+ if updates or deletes:
422
446
  sync_manager.update_sync_state(repo_abs_path, workspace_id, user_email)
423
447
  print("✔ Local sync state updated.")
424
448
 
425
- _details_raw = res_data.get("details", [])
426
- details_list = _details_raw.get("report", []) if isinstance(_details_raw, dict) else (_details_raw if isinstance(_details_raw, list) else [])
427
- if details_list:
428
- print("\n📊 Integration Report:")
429
- for item in details_list:
430
- status_icon = "✔" if item.get("success") else "✖"
431
- print(f" [{status_icon}] {item.get('file_path')}: {item.get('message', '')}")
432
- else:
433
- print(f"✔ {res_data.get('message', 'Changes applied successfully.')}")
449
+ # 4. Show Integration Report (Always show errors or details)
450
+ _details_raw = res_data.get("details", [])
451
+ details_list = _details_raw.get("report", []) if isinstance(_details_raw, dict) else (_details_raw if isinstance(_details_raw, list) else [])
452
+ if details_list:
453
+ print("\n📊 Integration Report:")
454
+ for item in details_list:
455
+ status_icon = "✔" if item.get("success") else "✖"
456
+ print(f" [{status_icon}] {item.get('file_path')}: {item.get('message', '')}")
457
+
458
+ # 5. Output Final Message if no updates were applied
459
+ if not updates and not deletes:
460
+ msg = res_data.get('message', 'Changes applied successfully.')
461
+ if isinstance(msg, str) and "AI MUST now sync" in msg:
462
+ msg = msg.split("AI MUST now sync")[0].strip()
463
+ print(f"✔ {msg}")
434
464
 
435
465
  except Exception as e:
436
466
  print(f"✖ Error: {e}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codedthemes-cli
3
- Version: 0.1.15
3
+ Version: 0.1.16
4
4
  Summary: CLI tool for Code Theme and Integration
5
5
  Author: codedthemes
6
6
  Requires-Python: >=3.10
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "codedthemes-cli"
7
- version = "0.1.15"
7
+ version = "0.1.16"
8
8
  description = "CLI tool for Code Theme and Integration"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"