@tencent-ai/agent-sdk 0.3.206-dev.0c715ff.202607102010 → 0.3.206

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.
Files changed (33) hide show
  1. package/cli/dist/codebuddy-headless.js +178 -226
  2. package/cli/dist/web-ui/assets/{index-D0Z5-Zvd.js → index-BZjhFKbY.js} +2 -2
  3. package/cli/dist/web-ui/index.html +1 -1
  4. package/cli/dist/web-ui/sw.js +1 -1
  5. package/cli/package.json +2 -3
  6. package/cli/product.cloudhosted.json +2 -2
  7. package/cli/product.internal.json +2 -2
  8. package/cli/product.ioa.json +2 -2
  9. package/cli/product.json +2 -2
  10. package/cli/product.selfhosted.json +2 -2
  11. package/cli/vendor/shim/genie-safe-delete.cjs +781 -4
  12. package/cli/vendor/shim/safe-bin/safe-delete-bash-env.sh +1 -1
  13. package/cli/vendor/shim/safe-bin/safe-delete-common.sh +34 -95
  14. package/cli/vendor/shim/sitecustomize.py +22 -551
  15. package/package.json +2 -3
  16. package/cli/vendor/native-builds.json +0 -18
  17. package/cli/vendor/shim/broker-ipc-client.cjs +0 -158
  18. package/cli/vendor/shim/brokered-bin/codebuddy-toybox-dispatch +0 -381
  19. package/cli/vendor/shim/brokered-sandbox-bash-env.sh +0 -10
  20. package/cli/vendor/shim/native/binding.gyp +0 -13
  21. package/cli/vendor/shim/native/brokered_sandbox_native.c +0 -293
  22. package/cli/vendor/shim/native/darwin-arm64/brokered-sandbox-native.node +0 -0
  23. package/cli/vendor/shim/native/darwin-x64/brokered-sandbox-native.node +0 -0
  24. package/cli/vendor/shim/node-brokered-fs-shim.cjs +0 -932
  25. package/cli/vendor/shim/node-language-shim.cjs +0 -35
  26. package/cli/vendor/shim/node-safe-delete-shim.cjs +0 -810
  27. package/cli/vendor/shim/safe-delete-broker-delete.cjs +0 -166
  28. package/cli/vendor/shim/shell-runtime-bash-env.sh +0 -8
  29. package/cli/vendor/toybox-macos/LICENSE +0 -12
  30. package/cli/vendor/toybox-macos/toybox +0 -0
  31. package/cli/vendor/toybox-macos/toybox.sb +0 -19
  32. package/cli/vendor/zsh-macos/LICENSE +0 -37
  33. package/cli/vendor/zsh-macos/bin/zsh +0 -0
@@ -13,11 +13,8 @@ genie-safe-delete — Python 运行时安全删除 shim
13
13
  """
14
14
 
15
15
  import errno
16
- import builtins
17
- import io
18
16
  import json
19
17
  import os
20
- import socket
21
18
  import stat
22
19
  import sys
23
20
  import tempfile
@@ -32,11 +29,6 @@ _SESSION_ID = (
32
29
  or os.environ.get("CLAUDE_SESSION_ID")
33
30
  )
34
31
  _IN_SANDBOX = os.environ.get("CODEBUDDY_SAFE_DELETE_SANDBOX") == "1"
35
- _SAFE_DELETE_ENABLED = os.environ.get("CODEBUDDY_SAFE_DELETE_ENABLED") != "0"
36
- _BROKERED_FS_HOOK_ENABLED = (
37
- os.environ.get("CODEBUDDY_BROKERED_FS_HOOK_ENABLED") == "1"
38
- or _IN_SANDBOX
39
- )
40
32
 
41
33
  if _SESSION_ID:
42
34
  # __file__ 在 sitecustomize 加载时指向本文件路径,dirname 即 vendor/shim/
@@ -276,484 +268,14 @@ if _SESSION_ID:
276
268
  import pathlib
277
269
  import platform
278
270
 
279
- _orig_builtin_open = builtins.open
280
- _orig_io_open = io.open
281
- _orig_os_open = os.open
282
271
  _orig_remove = os.remove
283
272
  _orig_unlink = os.unlink
284
273
  _orig_rmdir = os.rmdir
285
- _orig_mkdir = os.mkdir
286
- _orig_makedirs = os.makedirs
287
- _orig_rename = os.rename
288
- _orig_replace = os.replace
289
- _orig_chmod = os.chmod
290
- _orig_link = os.link
291
- _orig_symlink = os.symlink
292
274
  _orig_shutil_rmtree = shutil.rmtree
293
- _orig_shutil_copyfile = shutil.copyfile
294
- _orig_shutil_copy2 = shutil.copy2
295
- _orig_shutil_copytree = shutil.copytree
296
275
  _orig_path_unlink = pathlib.Path.unlink
297
276
  _orig_path_rmdir = pathlib.Path.rmdir
298
- _orig_path_mkdir = pathlib.Path.mkdir
299
- _orig_path_touch = pathlib.Path.touch
300
277
  _report_path = os.environ.get("CODEBUDDY_SAFE_DELETE_REPORT_PATH")
301
278
 
302
- # -----------------------------------------------------------------------
303
- # Brokered sandbox file-token support.
304
- #
305
- # Mirrors the shell/toybox broker model, but the interception point is
306
- # Python's runtime file APIs. The host still owns policy and token issuing.
307
- # -----------------------------------------------------------------------
308
-
309
- _broker_socket_path = os.environ.get("CODEBUDDY_SANDBOX_BROKER_IPC_ADDRESS")
310
- _broker_session_id = os.environ.get("CODEBUDDY_SANDBOX_BROKER_SESSION_ID") or _SESSION_ID
311
- _broker_tool_call_id = (
312
- os.environ.get("CODEBUDDY_SANDBOX_BROKER_TOOL_CALL_ID")
313
- or os.environ.get("CODEBUDDY_TOOL_CALL_ID")
314
- )
315
- _broker_trace_id = os.environ.get("CODEBUDDY_SANDBOX_BROKER_TRACE_ID")
316
- _broker_file_token_command = (
317
- os.environ.get("CODEBUDDY_SANDBOX_FILE_TOKEN_OPERATION_COMMAND")
318
- or "FileTokenRequest"
319
- )
320
- _broker_host_operation_command = os.environ.get(
321
- "CODEBUDDY_SANDBOX_HOST_FILE_OPERATION_COMMAND"
322
- )
323
- _broker_request_seq = 0
324
- _broker_host_operation_depth = 0
325
- _COPYTREE_DEFAULT = object()
326
-
327
- def _broker_enabled():
328
- return bool(sys.platform == "darwin" and _BROKERED_FS_HOOK_ENABLED and _broker_socket_path and _broker_session_id and _broker_file_token_command)
329
-
330
- def _broker_write_completed_enabled():
331
- return bool(sys.platform == "darwin" and _BROKERED_FS_HOOK_ENABLED and _broker_socket_path and _broker_session_id)
332
-
333
- def _broker_host_ops_enabled():
334
- return bool(
335
- sys.platform == "darwin"
336
- and _BROKERED_FS_HOOK_ENABLED
337
- and _broker_socket_path
338
- and _broker_session_id
339
- and _broker_host_operation_command
340
- and _broker_host_operation_depth == 0
341
- )
342
-
343
- def _broker_abs_path(file_path, dir_fd=None):
344
- if isinstance(file_path, int):
345
- return None
346
- try:
347
- raw_path = os.fspath(file_path)
348
- except TypeError:
349
- return None
350
- if isinstance(raw_path, bytes):
351
- try:
352
- raw_path = os.fsdecode(raw_path)
353
- except UnicodeError:
354
- return None
355
- if not raw_path:
356
- return None
357
- if dir_fd is not None and not os.path.isabs(raw_path):
358
- return None
359
- return os.path.abspath(raw_path)
360
-
361
- def _broker_readline(sock):
362
- chunks = []
363
- while True:
364
- chunk = sock.recv(1)
365
- if not chunk:
366
- break
367
- if chunk == b"\n":
368
- break
369
- chunks.append(chunk)
370
- return b"".join(chunks).decode("utf-8", errors="replace")
371
-
372
- def _broker_consume_token(token):
373
- if sys.platform != "darwin":
374
- return
375
- import ctypes
376
-
377
- lib = ctypes.CDLL(None, use_errno=True)
378
- fn = lib.sandbox_extension_consume
379
- fn.argtypes = [ctypes.c_char_p]
380
- fn.restype = ctypes.c_int64
381
- handle = fn(token.encode("utf-8"))
382
- if handle <= 0:
383
- err = ctypes.get_errno() or errno.EINVAL
384
- raise OSError(err, os.strerror(err))
385
-
386
- def _broker_send_request(request):
387
- try:
388
- with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
389
- sock.settimeout(5)
390
- sock.connect(_broker_socket_path)
391
- sock.sendall((json.dumps(request, separators=(",", ":")) + "\n").encode("utf-8"))
392
- line = _broker_readline(sock)
393
- except Exception:
394
- return None
395
-
396
- try:
397
- response = json.loads(line)
398
- except Exception:
399
- return None
400
- return response if isinstance(response, dict) else None
401
-
402
- def _broker_request_file_token(abs_path, operation):
403
- global _broker_request_seq
404
- if not _broker_enabled():
405
- return
406
-
407
- _broker_request_seq += 1
408
- request = {
409
- "id": "python-%d" % _broker_request_seq,
410
- "command": _broker_file_token_command,
411
- "runtime": "python",
412
- "operation": operation,
413
- "path": abs_path,
414
- "sessionId": _broker_session_id,
415
- }
416
- if _broker_tool_call_id:
417
- request["toolCallId"] = _broker_tool_call_id
418
- if _broker_trace_id:
419
- request["brokerTraceId"] = _broker_trace_id
420
-
421
- response = _broker_send_request(request)
422
- if response is None:
423
- # Match toybox's fail-to-sandbox behavior: if IPC is unavailable,
424
- # do not grant anything here; let the native sandbox decide.
425
- return
426
-
427
- token = response.get("token") if response.get("ok") is True else None
428
- if isinstance(token, str) and token:
429
- _broker_consume_token(token)
430
- return
431
- if response.get("decision") == "sandbox":
432
- return
433
-
434
- raise PermissionError(
435
- response.get("error")
436
- or "Brokered sandbox denied %s access to %s" % (operation, abs_path)
437
- )
438
-
439
- def _broker_notify_file_write_completed(abs_path, existed_before):
440
- global _broker_request_seq
441
- if existed_before:
442
- return
443
- if not _broker_write_completed_enabled():
444
- return
445
-
446
- _broker_request_seq += 1
447
- request = {
448
- "id": "python-%d" % _broker_request_seq,
449
- "command": "FileWriteCompleted",
450
- "runtime": "python",
451
- "operation": "write",
452
- "path": abs_path,
453
- "sessionId": _broker_session_id,
454
- }
455
- if _broker_tool_call_id:
456
- request["toolCallId"] = _broker_tool_call_id
457
- if _broker_trace_id:
458
- request["brokerTraceId"] = _broker_trace_id
459
- _broker_send_request(request)
460
-
461
- def _broker_request_host_operation(operation, primary_path, **fields):
462
- global _broker_request_seq
463
- if not _broker_host_ops_enabled():
464
- return False
465
-
466
- _broker_request_seq += 1
467
- request = {
468
- "id": "python-%d" % _broker_request_seq,
469
- "command": _broker_host_operation_command,
470
- "runtime": "python",
471
- "operation": operation,
472
- "sessionId": _broker_session_id,
473
- }
474
- request.update(fields)
475
- if _broker_tool_call_id:
476
- request["toolCallId"] = _broker_tool_call_id
477
- if _broker_trace_id:
478
- request["brokerTraceId"] = _broker_trace_id
479
-
480
- response = _broker_send_request(request)
481
- if response is None:
482
- return False
483
- if response.get("ok") is True:
484
- return True
485
- if response.get("decision") == "sandbox":
486
- return False
487
- raise PermissionError(
488
- response.get("error")
489
- or "Brokered sandbox denied host %s for %s" % (operation, primary_path)
490
- )
491
-
492
- def _broker_call_native_host_operation(fn, *args, **kwargs):
493
- global _broker_host_operation_depth
494
- _broker_host_operation_depth += 1
495
- try:
496
- return fn(*args, **kwargs)
497
- finally:
498
- _broker_host_operation_depth -= 1
499
-
500
- def _broker_operation_for_mode(mode):
501
- mode = mode or "r"
502
- return "write" if any(ch in mode for ch in "wax+") else "read"
503
-
504
- def _broker_operation_for_flags(flags):
505
- write_flags = (
506
- os.O_WRONLY
507
- | os.O_RDWR
508
- | os.O_CREAT
509
- | os.O_TRUNC
510
- | os.O_APPEND
511
- | getattr(os, "O_TMPFILE", 0)
512
- )
513
- return "write" if flags & write_flags else "read"
514
-
515
- def _broker_gate(file_path, operation, dir_fd=None):
516
- abs_path = _broker_abs_path(file_path, dir_fd=dir_fd)
517
- if abs_path:
518
- _broker_request_file_token(abs_path, operation)
519
-
520
- def _brokered_open(
521
- open_fn,
522
- file,
523
- mode="r",
524
- buffering=-1,
525
- encoding=None,
526
- errors=None,
527
- newline=None,
528
- closefd=True,
529
- opener=None,
530
- ):
531
- operation = _broker_operation_for_mode(mode)
532
- abs_path = _broker_abs_path(file)
533
- existed_before = bool(abs_path and os.path.exists(abs_path))
534
- if abs_path:
535
- _broker_request_file_token(abs_path, operation)
536
- file_obj = open_fn(file, mode, buffering, encoding, errors, newline, closefd, opener)
537
- if operation == "write" and abs_path and os.path.exists(abs_path):
538
- _broker_notify_file_write_completed(abs_path, existed_before)
539
- return file_obj
540
-
541
- def _brokered_builtin_open(
542
- file,
543
- mode="r",
544
- buffering=-1,
545
- encoding=None,
546
- errors=None,
547
- newline=None,
548
- closefd=True,
549
- opener=None,
550
- ):
551
- return _brokered_open(
552
- _orig_builtin_open,
553
- file, mode, buffering, encoding, errors, newline, closefd, opener,
554
- )
555
-
556
- def _brokered_io_open(
557
- file,
558
- mode="r",
559
- buffering=-1,
560
- encoding=None,
561
- errors=None,
562
- newline=None,
563
- closefd=True,
564
- opener=None,
565
- ):
566
- return _brokered_open(
567
- _orig_io_open,
568
- file, mode, buffering, encoding, errors, newline, closefd, opener,
569
- )
570
-
571
- def _brokered_os_open(path, flags, mode=0o777, *, dir_fd=None):
572
- _broker_gate(path, _broker_operation_for_flags(flags), dir_fd=dir_fd)
573
- if dir_fd is not None:
574
- return _orig_os_open(path, flags, mode, dir_fd=dir_fd)
575
- return _orig_os_open(path, flags, mode)
576
-
577
- def _brokered_os_mkdir(path, mode=0o777, *, dir_fd=None):
578
- abs_path = _broker_abs_path(path, dir_fd=dir_fd)
579
- if abs_path and isinstance(mode, int) and _broker_request_host_operation(
580
- "mkdir", abs_path, path=abs_path, mode=mode
581
- ):
582
- return None
583
- if dir_fd is not None:
584
- return _broker_call_native_host_operation(_orig_mkdir, path, mode, dir_fd=dir_fd)
585
- return _broker_call_native_host_operation(_orig_mkdir, path, mode)
586
-
587
- def _brokered_os_makedirs(name, mode=0o777, exist_ok=False):
588
- abs_path = _broker_abs_path(name)
589
- if abs_path and isinstance(mode, int):
590
- if not exist_ok and os.path.exists(abs_path):
591
- return _broker_call_native_host_operation(
592
- _orig_makedirs, name, mode=mode, exist_ok=exist_ok
593
- )
594
- if _broker_request_host_operation(
595
- "mkdir", abs_path, path=abs_path, recursive=True, mode=mode
596
- ):
597
- return None
598
- return _broker_call_native_host_operation(
599
- _orig_makedirs, name, mode=mode, exist_ok=exist_ok
600
- )
601
-
602
- def _brokered_os_rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None):
603
- from_path = _broker_abs_path(src, dir_fd=src_dir_fd)
604
- to_path = _broker_abs_path(dst, dir_fd=dst_dir_fd)
605
- if from_path and to_path and _broker_request_host_operation(
606
- "rename", from_path, **{"from": from_path, "to": to_path}
607
- ):
608
- return None
609
- if src_dir_fd is not None or dst_dir_fd is not None:
610
- return _broker_call_native_host_operation(
611
- _orig_rename, src, dst, src_dir_fd=src_dir_fd, dst_dir_fd=dst_dir_fd
612
- )
613
- return _broker_call_native_host_operation(_orig_rename, src, dst)
614
-
615
- def _brokered_os_replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None):
616
- from_path = _broker_abs_path(src, dir_fd=src_dir_fd)
617
- to_path = _broker_abs_path(dst, dir_fd=dst_dir_fd)
618
- if from_path and to_path and _broker_request_host_operation(
619
- "rename", from_path, **{"from": from_path, "to": to_path}
620
- ):
621
- return None
622
- if src_dir_fd is not None or dst_dir_fd is not None:
623
- return _broker_call_native_host_operation(
624
- _orig_replace, src, dst, src_dir_fd=src_dir_fd, dst_dir_fd=dst_dir_fd
625
- )
626
- return _broker_call_native_host_operation(_orig_replace, src, dst)
627
-
628
- def _brokered_os_chmod(path, mode, *, dir_fd=None, follow_symlinks=True):
629
- abs_path = _broker_abs_path(path, dir_fd=dir_fd)
630
- if abs_path and isinstance(mode, int) and follow_symlinks and _broker_request_host_operation(
631
- "chmod", abs_path, path=abs_path, mode=mode
632
- ):
633
- return None
634
- if dir_fd is not None:
635
- return _broker_call_native_host_operation(
636
- _orig_chmod, path, mode, dir_fd=dir_fd, follow_symlinks=follow_symlinks
637
- )
638
- return _broker_call_native_host_operation(
639
- _orig_chmod, path, mode, follow_symlinks=follow_symlinks
640
- )
641
-
642
- def _brokered_os_link(src, dst, *, src_dir_fd=None, dst_dir_fd=None, follow_symlinks=True):
643
- from_path = _broker_abs_path(src, dir_fd=src_dir_fd)
644
- to_path = _broker_abs_path(dst, dir_fd=dst_dir_fd)
645
- should_broker = follow_symlinks and from_path and to_path
646
- try:
647
- should_broker = should_broker and not os.path.islink(from_path)
648
- except Exception:
649
- should_broker = False
650
- if should_broker and _broker_request_host_operation(
651
- "link", from_path, **{"from": from_path, "to": to_path, "symbolic": False}
652
- ):
653
- return None
654
- if src_dir_fd is not None or dst_dir_fd is not None:
655
- return _broker_call_native_host_operation(
656
- _orig_link, src, dst, src_dir_fd=src_dir_fd, dst_dir_fd=dst_dir_fd,
657
- follow_symlinks=follow_symlinks
658
- )
659
- return _broker_call_native_host_operation(
660
- _orig_link, src, dst, follow_symlinks=follow_symlinks
661
- )
662
-
663
- def _brokered_os_symlink(src, dst, target_is_directory=False, *, dir_fd=None):
664
- source = None
665
- try:
666
- source = os.fspath(src)
667
- if isinstance(source, bytes):
668
- source = os.fsdecode(source)
669
- except (TypeError, UnicodeError):
670
- source = None
671
- to_path = _broker_abs_path(dst, dir_fd=dir_fd)
672
- if source and to_path and _broker_request_host_operation(
673
- "link", to_path, **{"from": source, "to": to_path, "symbolic": True}
674
- ):
675
- return None
676
- if dir_fd is not None:
677
- return _broker_call_native_host_operation(
678
- _orig_symlink, src, dst, target_is_directory, dir_fd=dir_fd
679
- )
680
- return _broker_call_native_host_operation(
681
- _orig_symlink, src, dst, target_is_directory
682
- )
683
-
684
- def _brokered_shutil_copyfile(src, dst, *, follow_symlinks=True):
685
- from_path = _broker_abs_path(src)
686
- to_path = _broker_abs_path(dst)
687
- if follow_symlinks and from_path and to_path and _broker_request_host_operation(
688
- "copy", from_path, **{"from": from_path, "to": to_path, "recursive": False}
689
- ):
690
- return dst
691
- return _broker_call_native_host_operation(
692
- _orig_shutil_copyfile, src, dst, follow_symlinks=follow_symlinks
693
- )
694
-
695
- def _brokered_shutil_copytree(
696
- src,
697
- dst,
698
- symlinks=False,
699
- ignore=None,
700
- copy_function=_COPYTREE_DEFAULT,
701
- ignore_dangling_symlinks=False,
702
- dirs_exist_ok=False,
703
- ):
704
- native_copy_function = (
705
- _orig_shutil_copy2
706
- if copy_function is _COPYTREE_DEFAULT
707
- else copy_function
708
- )
709
- can_broker = (
710
- symlinks is False
711
- and ignore is None
712
- and native_copy_function is _orig_shutil_copy2
713
- and ignore_dangling_symlinks is False
714
- and dirs_exist_ok is False
715
- )
716
- from_path = _broker_abs_path(src) if can_broker else None
717
- to_path = _broker_abs_path(dst) if can_broker else None
718
- if from_path and to_path and _broker_request_host_operation(
719
- "copy", from_path, **{"from": from_path, "to": to_path, "recursive": True}
720
- ):
721
- return dst
722
- return _broker_call_native_host_operation(
723
- _orig_shutil_copytree,
724
- src,
725
- dst,
726
- symlinks=symlinks,
727
- ignore=ignore,
728
- copy_function=native_copy_function,
729
- ignore_dangling_symlinks=ignore_dangling_symlinks,
730
- dirs_exist_ok=dirs_exist_ok,
731
- )
732
-
733
- def _brokered_path_mkdir(self, mode=0o777, parents=False, exist_ok=False):
734
- abs_path = _broker_abs_path(self)
735
- if abs_path and isinstance(mode, int):
736
- if not exist_ok and os.path.exists(abs_path):
737
- return _broker_call_native_host_operation(
738
- _orig_path_mkdir, self, mode=mode, parents=parents, exist_ok=exist_ok
739
- )
740
- if _broker_request_host_operation(
741
- "mkdir", abs_path, path=abs_path, recursive=parents, mode=mode
742
- ):
743
- return None
744
- return _broker_call_native_host_operation(
745
- _orig_path_mkdir, self, mode=mode, parents=parents, exist_ok=exist_ok
746
- )
747
-
748
- def _brokered_path_touch(self, mode=0o666, exist_ok=True):
749
- abs_path = _broker_abs_path(self)
750
- can_broker = abs_path and mode == 0o666 and (exist_ok or not os.path.exists(abs_path))
751
- if can_broker and _broker_request_host_operation("touch", abs_path, path=abs_path):
752
- return None
753
- return _broker_call_native_host_operation(
754
- _orig_path_touch, self, mode=mode, exist_ok=exist_ok
755
- )
756
-
757
279
  def _path_for_compare(path):
758
280
  return os.path.normcase(os.path.realpath(os.path.abspath(path)))
759
281
 
@@ -792,7 +314,7 @@ if _SESSION_ID:
792
314
  if not _report_path:
793
315
  return
794
316
  try:
795
- with _orig_builtin_open(_report_path, "a", encoding="utf-8") as f:
317
+ with open(_report_path, "a", encoding="utf-8") as f:
796
318
  f.write(json.dumps({
797
319
  "operation": "trash",
798
320
  "runtime": "python",
@@ -897,30 +419,11 @@ if _SESSION_ID:
897
419
  return False
898
420
 
899
421
  # -----------------------------------------------------------------------
900
- # 核心:移入回收站。
422
+ # 核心:尝试移入回收站。优先 binary,降级到平台内联实现。
901
423
  # 返回 True=已移入回收站;抛错=fail-closed,调用方不得真删。
902
424
  # -----------------------------------------------------------------------
903
425
 
904
- def _try_broker_delete(abs_path, recursive=False, force=False):
905
- if not _broker_host_ops_enabled():
906
- return "unavailable"
907
- try:
908
- if _broker_request_host_operation(
909
- "delete",
910
- abs_path,
911
- path=abs_path,
912
- deleteMode="trash",
913
- recursive=bool(recursive),
914
- force=bool(force),
915
- ):
916
- return "ok"
917
- return "unavailable"
918
- except PermissionError:
919
- return "denied"
920
- except Exception:
921
- return "unavailable"
922
-
923
- def _try_trash(abs_path, recursive=False, force=False):
426
+ def _try_trash(abs_path):
924
427
  if sys.platform == "win32" and _IN_SANDBOX:
925
428
  message = (
926
429
  "[safe-delete][SAFE_DELETE_FAIL_CLOSED] "
@@ -936,15 +439,6 @@ if _SESSION_ID:
936
439
  pass
937
440
  raise OSError(message)
938
441
  _check_bulk_delete_guard(abs_path)
939
-
940
- broker_result = _try_broker_delete(abs_path, recursive=recursive, force=force)
941
- if broker_result == "ok":
942
- return True
943
- if broker_result == "denied":
944
- raise PermissionError(
945
- "[safe-delete] broker denied delete: path=%s" % abs_path
946
- )
947
-
948
442
  if _try_trash_via_binary(abs_path):
949
443
  _record_trash(abs_path)
950
444
  return True
@@ -967,18 +461,17 @@ if _SESSION_ID:
967
461
  except OSError:
968
462
  return False
969
463
 
970
- def _is_under_root(root, abs_path):
464
+ def _is_under_os_tmp_dir(abs_path):
971
465
  try:
972
466
  target = _path_for_compare(os.fsdecode(abs_path))
973
- root_path = _path_for_compare(root)
974
- rel = os.path.relpath(target, root_path)
975
- except (TypeError, UnicodeError, ValueError):
467
+ except (TypeError, UnicodeError):
976
468
  return False
977
- return rel not in ("", ".") and rel != ".." and not rel.startswith(".." + os.sep) and not os.path.isabs(rel)
978
-
979
- def _is_under_os_tmp_dir(abs_path):
980
469
  for tmp_dir in _os_tmp_dirs:
981
- if _is_under_root(tmp_dir, abs_path):
470
+ try:
471
+ rel = os.path.relpath(target, tmp_dir)
472
+ except ValueError:
473
+ continue
474
+ if rel not in ("", ".") and rel != ".." and not rel.startswith(".." + os.sep) and not os.path.isabs(rel):
982
475
  return True
983
476
  return False
984
477
 
@@ -996,9 +489,6 @@ if _SESSION_ID:
996
489
  return True
997
490
  return False
998
491
 
999
- def _should_bypass_safe_delete(abs_path):
1000
- return _is_under_os_tmp_dir(abs_path) or _is_pip_site_packages_temp_dir(abs_path)
1001
-
1002
492
  # -----------------------------------------------------------------------
1003
493
  # 包装:os.remove / os.unlink (文件,不能是目录)
1004
494
  # -----------------------------------------------------------------------
@@ -1008,7 +498,7 @@ if _SESSION_ID:
1008
498
  if dir_fd is not None:
1009
499
  return _orig_remove(path, dir_fd=dir_fd)
1010
500
  abs_path = os.path.abspath(os.fspath(path))
1011
- if _should_bypass_safe_delete(abs_path):
501
+ if _is_under_os_tmp_dir(abs_path) or _is_pip_site_packages_temp_dir(abs_path):
1012
502
  return _orig_remove(path)
1013
503
  st = _safe_lstat(abs_path)
1014
504
  if not st:
@@ -1025,7 +515,7 @@ if _SESSION_ID:
1025
515
  if dir_fd is not None:
1026
516
  return _orig_rmdir(path, dir_fd=dir_fd)
1027
517
  abs_path = os.path.abspath(os.fspath(path))
1028
- if _should_bypass_safe_delete(abs_path):
518
+ if _is_under_os_tmp_dir(abs_path) or _is_pip_site_packages_temp_dir(abs_path):
1029
519
  return _orig_rmdir(path)
1030
520
  st = _safe_lstat(abs_path)
1031
521
  if not st:
@@ -1049,7 +539,7 @@ if _SESSION_ID:
1049
539
  path, ignore_errors=ignore_errors, onerror=onerror, **kwargs
1050
540
  )
1051
541
 
1052
- if _should_bypass_safe_delete(abs_path):
542
+ if _is_under_os_tmp_dir(abs_path) or _is_pip_site_packages_temp_dir(abs_path):
1053
543
  return _orig_shutil_rmtree(
1054
544
  path, ignore_errors=ignore_errors, onerror=onerror, **kwargs
1055
545
  )
@@ -1066,7 +556,7 @@ if _SESSION_ID:
1066
556
  )
1067
557
 
1068
558
  try:
1069
- _try_trash(abs_path, recursive=True)
559
+ _try_trash(abs_path)
1070
560
  except Exception as e:
1071
561
  if ignore_errors:
1072
562
  return
@@ -1081,7 +571,7 @@ if _SESSION_ID:
1081
571
 
1082
572
  def _safe_path_unlink(self, missing_ok=False):
1083
573
  abs_path = os.path.abspath(str(self))
1084
- if _should_bypass_safe_delete(abs_path):
574
+ if _is_under_os_tmp_dir(abs_path) or _is_pip_site_packages_temp_dir(abs_path):
1085
575
  return _orig_path_unlink(self, missing_ok=missing_ok)
1086
576
  st = _safe_lstat(abs_path)
1087
577
  if not st:
@@ -1094,7 +584,7 @@ if _SESSION_ID:
1094
584
 
1095
585
  def _safe_path_rmdir(self):
1096
586
  abs_path = os.path.abspath(str(self))
1097
- if _should_bypass_safe_delete(abs_path):
587
+ if _is_under_os_tmp_dir(abs_path) or _is_pip_site_packages_temp_dir(abs_path):
1098
588
  return _orig_path_rmdir(self)
1099
589
  st = _safe_lstat(abs_path)
1100
590
  if not st:
@@ -1109,28 +599,9 @@ if _SESSION_ID:
1109
599
  # 安装 patch
1110
600
  # -----------------------------------------------------------------------
1111
601
 
1112
- if _broker_enabled():
1113
- builtins.open = _brokered_builtin_open
1114
- io.open = _brokered_io_open
1115
- os.open = _brokered_os_open
1116
-
1117
- if _broker_host_ops_enabled():
1118
- os.mkdir = _brokered_os_mkdir
1119
- os.makedirs = _brokered_os_makedirs
1120
- os.rename = _brokered_os_rename
1121
- os.replace = _brokered_os_replace
1122
- os.chmod = _brokered_os_chmod
1123
- os.link = _brokered_os_link
1124
- os.symlink = _brokered_os_symlink
1125
- shutil.copyfile = _brokered_shutil_copyfile
1126
- shutil.copytree = _brokered_shutil_copytree
1127
- pathlib.Path.mkdir = _brokered_path_mkdir
1128
- pathlib.Path.touch = _brokered_path_touch
1129
-
1130
- if _SAFE_DELETE_ENABLED:
1131
- os.remove = _safe_remove
1132
- os.unlink = _safe_remove # CPython 里 os.unlink is os.remove,显式 patch 兼容其它实现
1133
- os.rmdir = _safe_rmdir
1134
- shutil.rmtree = _safe_shutil_rmtree
1135
- pathlib.Path.unlink = _safe_path_unlink
1136
- pathlib.Path.rmdir = _safe_path_rmdir
602
+ os.remove = _safe_remove
603
+ os.unlink = _safe_remove # CPython 里 os.unlink is os.remove,显式 patch 兼容其它实现
604
+ os.rmdir = _safe_rmdir
605
+ shutil.rmtree = _safe_shutil_rmtree
606
+ pathlib.Path.unlink = _safe_path_unlink
607
+ pathlib.Path.rmdir = _safe_path_rmdir
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tencent-ai/agent-sdk",
3
- "version": "0.3.206-dev.0c715ff.202607102010",
3
+ "version": "0.3.206",
4
4
  "description": "CodeBuddy Code SDK for JavaScript/TypeScript",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -31,7 +31,6 @@
31
31
  "zod": "^4.0.0"
32
32
  },
33
33
  "publishConfig": {
34
- "access": "public",
35
- "tag": "dev"
34
+ "access": "public"
36
35
  }
37
36
  }