portacode 1.4.18__py3-none-any.whl → 1.4.18.dev0__py3-none-any.whl

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.
portacode/_version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.4.18'
32
- __version_tuple__ = version_tuple = (1, 4, 18)
31
+ __version__ = version = '1.4.18.dev0'
32
+ __version_tuple__ = version_tuple = (1, 4, 18, 'dev0')
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -408,7 +408,7 @@ Deletes a managed container from Proxmox (stopping it first if necessary) and re
408
408
 
409
409
  **Payload Fields:**
410
410
 
411
- * `ctid` (string, optional): Identifier of the container to delete. If omitted, the handler resolves the CTID from the managed container records using `child_device_id`.
411
+ * `ctid` (string, required): Identifier of the container to delete.
412
412
  * `child_device_id` (string, required): Dashboard `Device.id` that should own the container metadata being purged.
413
413
 
414
414
  **Responses:**
@@ -62,18 +62,16 @@ class BaseHandler(ABC):
62
62
  # Get client session manager from context
63
63
  client_session_manager = self.context.get("client_session_manager")
64
64
 
65
- bypass_session_gate = bool(payload.get("bypass_session_gate"))
66
65
  if client_session_manager and client_session_manager.has_interested_clients():
67
66
  # Get target sessions
68
67
  target_sessions = client_session_manager.get_target_sessions(project_id)
69
- if not target_sessions and not bypass_session_gate:
68
+ if not target_sessions:
70
69
  logger.debug("handler: No target sessions found, skipping response send")
71
70
  return
72
71
 
73
72
  # Add session targeting information
74
73
  enhanced_payload = dict(payload)
75
- if target_sessions:
76
- enhanced_payload["client_sessions"] = target_sessions
74
+ enhanced_payload["client_sessions"] = target_sessions
77
75
 
78
76
  # Add backward compatibility reply_channel (first session if not provided)
79
77
  if not reply_channel:
@@ -218,4 +216,4 @@ class SyncHandler(BaseHandler):
218
216
  logger.exception("Error in sync handler %s: %s", self.command_name, exc)
219
217
  # Extract project_id from original message for error targeting
220
218
  project_id = message.get("project_id")
221
- await self.send_error(str(exc), reply_channel, project_id)
219
+ await self.send_error(str(exc), reply_channel, project_id)
@@ -116,7 +116,6 @@ def _emit_progress_event(
116
116
  payload["details"] = details
117
117
  if on_behalf_of_device:
118
118
  payload["on_behalf_of_device"] = str(on_behalf_of_device)
119
- payload["bypass_session_gate"] = True
120
119
 
121
120
  future = asyncio.run_coroutine_threadsafe(handler.send_response(payload), loop)
122
121
  future.add_done_callback(
@@ -1180,7 +1179,7 @@ def _build_bootstrap_steps(
1180
1179
  steps.append(
1181
1180
  {
1182
1181
  "name": "add_ssh_key",
1183
- "cmd": f"install -d -m 700 /home/{user}/.ssh && echo '{ssh_key}' >> /home/{user}/.ssh/authorized_keys && chown -R {user}:$(id -gn {shlex.quote(user)}) /home/{user}/.ssh",
1182
+ "cmd": f"install -d -m 700 /home/{user}/.ssh && echo '{ssh_key}' >> /home/{user}/.ssh/authorized_keys && chown -R {user}:{user} /home/{user}/.ssh",
1184
1183
  "retries": 0,
1185
1184
  }
1186
1185
  )
@@ -1400,25 +1399,6 @@ def _parse_ctid(message: Dict[str, Any]) -> int:
1400
1399
  raise ValueError("ctid is required")
1401
1400
 
1402
1401
 
1403
- def _resolve_vmid_for_device(device_id: str) -> int:
1404
- _initialize_managed_containers_state()
1405
- records = list(_MANAGED_CONTAINERS_STATE.get("records", {}).values())
1406
- for record in records:
1407
- record_device_id = record.get("device_id")
1408
- if record_device_id is None:
1409
- continue
1410
- if str(record_device_id) != str(device_id):
1411
- continue
1412
- vmid = record.get("vmid")
1413
- if vmid is None:
1414
- continue
1415
- try:
1416
- return int(str(vmid).strip())
1417
- except ValueError:
1418
- raise ValueError("ctid must be an integer") from None
1419
- raise ValueError("ctid is required for remove_proxmox_container")
1420
-
1421
-
1422
1402
  def _ensure_container_managed(
1423
1403
  proxmox: Any, node: str, vmid: int, *, device_id: Optional[str] = None
1424
1404
  ) -> Tuple[Dict[str, Any], Dict[str, Any]]:
@@ -1464,14 +1444,6 @@ def _su_command(user: str, command: str) -> str:
1464
1444
  return f"su - {user} -s /bin/sh -c {shlex.quote(command)}"
1465
1445
 
1466
1446
 
1467
- def _resolve_user_group(vmid: int, user: str) -> str:
1468
- res = _run_pct(vmid, f"id -gn {shlex.quote(user)}")
1469
- group = (res.get("stdout") or "").strip()
1470
- if group:
1471
- return f"{user}:{group}"
1472
- return f"{user}:{user}"
1473
-
1474
-
1475
1447
  def _resolve_portacode_cli_path(vmid: int, user: str) -> str:
1476
1448
  """Resolve the full path to the portacode CLI inside the container."""
1477
1449
  res = _run_pct(vmid, _su_command(user, "command -v portacode"))
@@ -1508,13 +1480,12 @@ def _push_bytes_to_container(
1508
1480
  ) -> None:
1509
1481
  logger.debug("Preparing to push %d bytes to container vmid=%s path=%s for user=%s", len(data), vmid, path, user)
1510
1482
  tmp_path: Optional[str] = None
1511
- owner = _resolve_user_group(vmid, user)
1512
1483
  try:
1513
1484
  parent = Path(path).parent
1514
1485
  parent_str = parent.as_posix()
1515
1486
  if parent_str not in {"", ".", "/"}:
1516
1487
  _run_pct_exec_check(vmid, ["mkdir", "-p", parent_str])
1517
- _run_pct_exec_check(vmid, ["chown", "-R", owner, parent_str])
1488
+ _run_pct_exec_check(vmid, ["chown", "-R", f"{user}:{user}", parent_str])
1518
1489
 
1519
1490
  with tempfile.NamedTemporaryFile(delete=False) as tmp:
1520
1491
  tmp.write(data)
@@ -1526,7 +1497,7 @@ def _push_bytes_to_container(
1526
1497
  if push_res.returncode != 0:
1527
1498
  raise RuntimeError(push_res.stderr or push_res.stdout or f"pct push returned {push_res.returncode}")
1528
1499
 
1529
- _run_pct_exec_check(vmid, ["chown", owner, path])
1500
+ _run_pct_exec_check(vmid, ["chown", f"{user}:{user}", path])
1530
1501
  _run_pct_exec_check(vmid, ["chmod", format(mode, "o"), path])
1531
1502
  logger.debug("Successfully pushed %d bytes to vmid=%s path=%s", len(data), vmid, path)
1532
1503
  except Exception as exc:
@@ -1545,8 +1516,7 @@ def _resolve_portacode_key_dir(vmid: int, user: str) -> str:
1545
1516
  data_home = _run_pct_check(vmid, data_dir_cmd)["stdout"].strip()
1546
1517
  portacode_dir = f"{data_home}/portacode"
1547
1518
  _run_pct_exec_check(vmid, ["mkdir", "-p", portacode_dir])
1548
- owner = _resolve_user_group(vmid, user)
1549
- _run_pct_exec_check(vmid, ["chown", "-R", owner, portacode_dir])
1519
+ _run_pct_exec_check(vmid, ["chown", "-R", f"{user}:{user}", portacode_dir])
1550
1520
  return f"{portacode_dir}/keys"
1551
1521
 
1552
1522
 
@@ -2351,7 +2321,6 @@ class CreateProxmoxContainerHandler(SyncHandler):
2351
2321
  "setup_steps": steps,
2352
2322
  "device_id": device_id,
2353
2323
  "on_behalf_of_device": device_id,
2354
- "bypass_session_gate": True,
2355
2324
  "service_installed": service_installed,
2356
2325
  "request_id": request_id,
2357
2326
  },
@@ -2378,6 +2347,7 @@ class CreateProxmoxContainerHandler(SyncHandler):
2378
2347
  "event": "proxmox_container_accepted",
2379
2348
  "success": True,
2380
2349
  "message": "Provisioning accepted; resources reserved.",
2350
+ "device_id": device_id,
2381
2351
  "request_id": request_id,
2382
2352
  }
2383
2353
 
@@ -2577,13 +2547,10 @@ class RemoveProxmoxContainerHandler(SyncHandler):
2577
2547
  return "remove_proxmox_container"
2578
2548
 
2579
2549
  def execute(self, message: Dict[str, Any]) -> Dict[str, Any]:
2550
+ vmid = _parse_ctid(message)
2580
2551
  child_device_id = (message.get("child_device_id") or "").strip()
2581
2552
  if not child_device_id:
2582
2553
  raise ValueError("child_device_id is required for remove_proxmox_container")
2583
- try:
2584
- vmid = _parse_ctid(message)
2585
- except ValueError:
2586
- vmid = _resolve_vmid_for_device(child_device_id)
2587
2554
  config = _ensure_infra_configured()
2588
2555
  proxmox = _connect_proxmox(config)
2589
2556
  node = _get_node_from_config(config)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: portacode
3
- Version: 1.4.18
3
+ Version: 1.4.18.dev0
4
4
  Summary: Portacode CLI client and SDK
5
5
  Home-page: https://github.com/portacode/portacode
6
6
  Author: Meena Erian
@@ -1,7 +1,7 @@
1
1
  portacode/README.md,sha256=4dKtpvR8LNgZPVz37GmkQCMWIr_u25Ao63iW56s7Ke4,775
2
2
  portacode/__init__.py,sha256=oB3sV1wXr-um-RXio73UG8E5Xx6cF2ZVJveqjNmC-vQ,1086
3
3
  portacode/__main__.py,sha256=jmHTGC1hzmo9iKJLv-SSYe9BSIbPPZ2IOpecI03PlTs,296
4
- portacode/_version.py,sha256=ver_5YwV6iEZGHA-LSfN0xE_LIPi_0Lc9SHbQX2D7zw,706
4
+ portacode/_version.py,sha256=yA2sKupgNCrFCGL5pCY3CIzvzrKLzwboOhvQKU_KGWI,719
5
5
  portacode/cli.py,sha256=mGLKoZ-T2FBF7IA9wUq0zyG0X9__-A1ao7gajjcVRH8,21828
6
6
  portacode/data.py,sha256=5-s291bv8J354myaHm1Y7CQZTZyRzMU3TGe5U4hb-FA,1591
7
7
  portacode/keypair.py,sha256=0OO4vHDcF1XMxCDqce61xFTlFwlTcmqe5HyGsXFEt7s,5838
@@ -14,15 +14,15 @@ portacode/connection/client.py,sha256=jtLb9_YufqPkzi9t8VQH3iz_JEMisbtY6a8L9U5wei
14
14
  portacode/connection/multiplex.py,sha256=L-TxqJ_ZEbfNEfu1cwxgJ5vUdyRzZjsMy2Kx1diiZys,5237
15
15
  portacode/connection/terminal.py,sha256=n1Uu92JacV5K6d1Qwx94Tw9OB2Tpke5HqsW2NDn76Ls,49032
16
16
  portacode/connection/handlers/README.md,sha256=HsLZG1QK1JNm67HsgL6WoDg9nxzKXxwkc5fJPFJdX5g,12169
17
- portacode/connection/handlers/WEBSOCKET_PROTOCOL.md,sha256=Btbt3UVUvXG5t2HB0_ani0eQNnUPUCLWaqlvCHTaWfo,103727
17
+ portacode/connection/handlers/WEBSOCKET_PROTOCOL.md,sha256=R9trHDWDuADIY2Xs2LrpIw1himtxE-NDb_6CzNVNVcM,103625
18
18
  portacode/connection/handlers/__init__.py,sha256=WSeBmi65GWFQPYt9M3E10rn0uZ_EPCJzNJOzSf2HZyw,2921
19
- portacode/connection/handlers/base.py,sha256=OPg4EsMqqR_59-uQ6UYloFU5RX0474m4Ot4oXOuWals,10367
19
+ portacode/connection/handlers/base.py,sha256=oENFb-Fcfzwk99Qx8gJQriEMiwSxwygwjOiuCH36hM4,10231
20
20
  portacode/connection/handlers/chunked_content.py,sha256=h6hXRmxSeOgnIxoU8CkmvEf2Odv-ajPrpHIe_W3GKcA,9251
21
21
  portacode/connection/handlers/diff_handlers.py,sha256=iYTIRCcpEQ03vIPKZCsMTE5aZbQw6sF04M3dM6rUV8Q,24477
22
22
  portacode/connection/handlers/file_handlers.py,sha256=nAJH8nXnX07xxD28ngLpgIUzcTuRwZBNpEGEKdRqohw,39507
23
23
  portacode/connection/handlers/project_aware_file_handlers.py,sha256=AqgMnDqX2893T2NsrvUSCwjN5VKj4Pb2TN0S_SuboOE,9803
24
24
  portacode/connection/handlers/project_state_handlers.py,sha256=v6ZefGW9i7n1aZLq2jOGumJIjYb6aHlPI4m1jkYewm8,1686
25
- portacode/connection/handlers/proxmox_infra.py,sha256=y7Vx8OCGw5OUV00lT946yOjXdDed2CxenveffSnGAlI,100690
25
+ portacode/connection/handlers/proxmox_infra.py,sha256=EzxN6czFMcvIcOVmNFyBoSQoFfg1GN0aWxdSnN7NVfk,99532
26
26
  portacode/connection/handlers/registry.py,sha256=qXGE60sYEWg6ZtVQzFcZ5YI2XWR6lMgw4hAL9x5qR1I,6181
27
27
  portacode/connection/handlers/session.py,sha256=uNGfiO_1B9-_yjJKkpvmbiJhIl6b-UXlT86UTfd6WYE,42219
28
28
  portacode/connection/handlers/system_handlers.py,sha256=fr12QpOr_Z8KYGUU-AYrTQwRPAcrLK85hvj3SEq1Kw8,14757
@@ -65,7 +65,7 @@ portacode/utils/__init__.py,sha256=NgBlWTuNJESfIYJzP_3adI1yJQJR0XJLRpSdVNaBAN0,3
65
65
  portacode/utils/diff_apply.py,sha256=4Oi7ft3VUCKmiUE4VM-OeqO7Gk6H7PF3WnN4WHXtjxI,15157
66
66
  portacode/utils/diff_renderer.py,sha256=S76StnQ2DLfsz4Gg0m07UwPfRp8270PuzbNaQq-rmYk,13850
67
67
  portacode/utils/ntp_clock.py,sha256=VqCnWCTehCufE43W23oB-WUdAZGeCcLxkmIOPwInYHc,2499
68
- portacode-1.4.18.dist-info/licenses/LICENSE,sha256=2FGbCnUDgRYuQTkB1O1dUUpu5CVAjK1j4_p6ack9Z54,1066
68
+ portacode-1.4.18.dev0.dist-info/licenses/LICENSE,sha256=2FGbCnUDgRYuQTkB1O1dUUpu5CVAjK1j4_p6ack9Z54,1066
69
69
  test_modules/README.md,sha256=Do_agkm9WhSzueXjRAkV_xEj6Emy5zB3N3VKY5Roce8,9274
70
70
  test_modules/__init__.py,sha256=1LcbHodIHsB0g-g4NGjSn6AMuCoGbymvXPYLOb6Z7F0,53
71
71
  test_modules/test_device_online.py,sha256=QtYq0Dq9vME8Gp2O4fGSheqVf8LUtpsSKosXXk56gGM,1654
@@ -91,8 +91,8 @@ testing_framework/core/playwright_manager.py,sha256=Tw46qwxIhOFkS48C2IWIQHHNpEe-
91
91
  testing_framework/core/runner.py,sha256=j2QwNJmAxVBmJvcbVS7DgPJUKPNzqfLmt_4NNdaKmZU,19297
92
92
  testing_framework/core/shared_cli_manager.py,sha256=BESSNtyQb7BOlaOvZmm04T8Uezjms4KCBs2MzTxvzYQ,8790
93
93
  testing_framework/core/test_discovery.py,sha256=2FZ9fJ8Dp5dloA-fkgXoJ_gCMC_nYPBnA3Hs2xlagzM,4928
94
- portacode-1.4.18.dist-info/METADATA,sha256=Umbaduyx9KBfBweiAoFPYo6JFM0IIUxCM8FjNh3ePi8,13046
95
- portacode-1.4.18.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
96
- portacode-1.4.18.dist-info/entry_points.txt,sha256=lLUUL-BM6_wwe44Xv0__5NQ1BnAz6jWjSMFvZdWW3zU,48
97
- portacode-1.4.18.dist-info/top_level.txt,sha256=TGhTYUxfW8SyVZc_zGgzjzc24gGT7nSw8Qf73liVRKM,41
98
- portacode-1.4.18.dist-info/RECORD,,
94
+ portacode-1.4.18.dev0.dist-info/METADATA,sha256=wRHmdC2IMhBneJ0RTBUzCwCdzh1Xvda78wK1LlvV14E,13051
95
+ portacode-1.4.18.dev0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
96
+ portacode-1.4.18.dev0.dist-info/entry_points.txt,sha256=lLUUL-BM6_wwe44Xv0__5NQ1BnAz6jWjSMFvZdWW3zU,48
97
+ portacode-1.4.18.dev0.dist-info/top_level.txt,sha256=TGhTYUxfW8SyVZc_zGgzjzc24gGT7nSw8Qf73liVRKM,41
98
+ portacode-1.4.18.dev0.dist-info/RECORD,,