portacode 1.4.11.dev0__py3-none-any.whl → 1.4.12.dev1__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.

Potentially problematic release.


This version of portacode might be problematic. Click here for more details.

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.11.dev0'
32
- __version_tuple__ = version_tuple = (1, 4, 11, 'dev0')
31
+ __version__ = version = '1.4.12.dev1'
32
+ __version_tuple__ = version_tuple = (1, 4, 12, 'dev1')
33
33
 
34
34
  __commit_id__ = commit_id = None
portacode/cli.py CHANGED
@@ -405,6 +405,45 @@ def send_control(message: str, gateway: str | None) -> None: # noqa: D401 – C
405
405
  finally:
406
406
  await mgr.stop()
407
407
 
408
+ asyncio.run(_run())
409
+
410
+
411
+ @cli.command("revert_proxmox_infra")
412
+ @click.option("--gateway", "gateway", "-g", help="Gateway websocket URL (overrides env/ default)")
413
+ def revert_proxmox_infra(gateway: str | None) -> None: # noqa: D401 – Click callback
414
+ """Revert the Proxmox infrastructure configuration stored on this device."""
415
+
416
+ target_gateway = gateway or os.getenv(GATEWAY_ENV) or GATEWAY_URL
417
+
418
+ async def _run() -> None:
419
+ keypair = get_or_create_keypair()
420
+ mgr = ConnectionManager(target_gateway, keypair, debug=False)
421
+ await mgr.start()
422
+
423
+ for _ in range(20):
424
+ if mgr.mux is not None:
425
+ break
426
+ await asyncio.sleep(0.1)
427
+ if mgr.mux is None:
428
+ click.echo("Failed to initialise connection – aborting.")
429
+ await mgr.stop()
430
+ return
431
+
432
+ ctl = mgr.mux.get_channel(0)
433
+ await ctl.send({"cmd": "revert_proxmox_infra"})
434
+
435
+ try:
436
+ with click.progressbar(length=30, label="Waiting for revert response") as bar:
437
+ for _ in range(30):
438
+ try:
439
+ reply = await asyncio.wait_for(ctl.recv(), timeout=0.1)
440
+ click.echo(click.style("< " + json.dumps(reply, indent=2), fg="cyan"))
441
+ except asyncio.TimeoutError:
442
+ pass
443
+ bar.update(1)
444
+ finally:
445
+ await mgr.stop()
446
+
408
447
  asyncio.run(_run())
409
448
 
410
449
 
@@ -322,7 +322,7 @@ This action does not require any payload fields.
322
322
 
323
323
  ### `setup_proxmox_infra`
324
324
 
325
- Configures a Proxmox node for Portacode infrastructure usage (API token storage, default storage selection, and bridge setup). Handled by [`ConfigureProxmoxInfraHandler`](./proxmox_infra.py).
325
+ Configures a Proxmox node for Portacode infrastructure usage (API token validation, automatic storage/template detection, bridge/NAT setup, and connectivity verification). Handled by [`ConfigureProxmoxInfraHandler`](./proxmox_infra.py).
326
326
 
327
327
  **Payload Fields:**
328
328
 
@@ -333,7 +333,133 @@ Configures a Proxmox node for Portacode infrastructure usage (API token storage,
333
333
  **Responses:**
334
334
 
335
335
  * On success, the device will emit a [`proxmox_infra_configured`](#proxmox_infra_configured-event) event with the persisted infra snapshot.
336
- * On failure, the device will emit an [`error`](#error) event with details (e.g., permission issues, missing proxmoxer/dnsmasq, or missing root privileges).
336
+ * On failure, the device will emit an [`error`](#error) event with details (e.g., permission issues, missing proxmoxer/dnsmasq, missing root privileges, or failed network verification).
337
+
338
+ ### `revert_proxmox_infra`
339
+
340
+ Reverts the Proxmox infrastructure network changes and clears the stored API token. Handled by [`RevertProxmoxInfraHandler`](./proxmox_infra.py).
341
+
342
+ **Payload Fields:**
343
+
344
+ This action does not require any payload fields.
345
+
346
+ **Responses:**
347
+
348
+ * On success, the device will emit a [`proxmox_infra_reverted`](#proxmox_infra_reverted-event) event containing the cleared snapshot.
349
+
350
+ ### `create_proxmox_container`
351
+
352
+ Creates a Portacode-managed LXC container, starts it, and bootstraps the Portacode service by running the commands from [`proxmox_management/setup_portacode.py`](../../proxmox_management/setup_portacode.py). Handled by [`CreateProxmoxContainerHandler`](./proxmox_infra.py).
353
+
354
+ **Payload Fields:**
355
+
356
+ * `template` (string, required): Template identifier to use for the CT (e.g., `local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst`).
357
+ * `disk_gib` (integer, optional): Rootfs size in GiB (defaults to 32).
358
+ * `ram_mib` (integer, optional): Memory size in MiB (defaults to 2048).
359
+ * `cpus` (integer, optional): Number of CPU cores (defaults to 1).
360
+ * `hostname` (string, optional): Desired hostname inside the container; defaults to `ct<vmid>`.
361
+ * `username` (string, optional): OS user to provision (defaults to `svcuser`).
362
+ * `password` (string, optional): Password for the user (used only during provisioning).
363
+ * `ssh_key` (string, optional): SSH public key to add to the user.
364
+
365
+ **Responses:**
366
+
367
+ * On success, the device will emit a [`proxmox_container_created`](#proxmox_container_created-event) event that includes the Portacode auth key produced inside the container.
368
+ * On failure, the device will emit an [`error`](#error) event.
369
+
370
+ ### `start_proxmox_container`
371
+
372
+ Starts a previously provisioned, Portacode-managed LXC container. Handled by [`StartProxmoxContainerHandler`](./proxmox_infra.py).
373
+
374
+ **Payload Fields:**
375
+
376
+ * `ctid` (string, required): Identifier of the container to start.
377
+
378
+ **Responses:**
379
+
380
+ * Emits a [`proxmox_container_action`](#proxmox_container_action-event) event with `action="start"` and the refreshed infra snapshot.
381
+ * Emits an [`error`](#error) event when the request cannot be fulfilled (e.g., missing infra config, CT not tagged as managed, or API failure).
382
+
383
+ ### `stop_proxmox_container`
384
+
385
+ Stops a running Portacode-managed container. Handled by [`StopProxmoxContainerHandler`](./proxmox_infra.py).
386
+
387
+ **Payload Fields:**
388
+
389
+ * `ctid` (string, required): Identifier of the container to stop.
390
+
391
+ **Responses:**
392
+
393
+ * Emits a [`proxmox_container_action`](#proxmox_container_action-event) event with `action="stop"` and the refreshed infra snapshot.
394
+ * Emits an [`error`](#error) event on failure.
395
+
396
+ ### `remove_proxmox_container`
397
+
398
+ Deletes a managed container from Proxmox (stopping it first if necessary) and removes the stored metadata file. Handled by [`RemoveProxmoxContainerHandler`](./proxmox_infra.py).
399
+
400
+ **Payload Fields:**
401
+
402
+ * `ctid` (string, required): Identifier of the container to delete.
403
+
404
+ **Responses:**
405
+
406
+ * Emits a [`proxmox_container_action`](#proxmox_container_action-event) event with `action="remove"` and the refreshed infra snapshot after deletion.
407
+ * Emits an [`error`](#error) event on failure.
408
+
409
+ ### `proxmox_container_created`
410
+
411
+ Emitted after a successful `create_proxmox_container` action. Contains the new container ID, the Portacode public key produced inside the container, and the bootstrap logs.
412
+
413
+ **Event Fields:**
414
+
415
+ * `success` (boolean): True when the CT and Portacode bootstrap succeed.
416
+ * `message` (string): Human-readable summary (e.g., `Container 103 is ready`).
417
+ * `ctid` (string): The numeric CT ID.
418
+ * `public_key` (string): Portacode public auth key created inside the new container.
419
+ * `container` (object): Metadata such as `vmid`, `hostname`, `template`, `storage`, `disk_gib`, `ram_mib`, and `cpus`.
420
+ * `setup_steps` (array[object]): Detailed bootstrap step results (name, stdout/stderr, elapsed time, and status).
421
+
422
+ ### `proxmox_container_progress`
423
+
424
+ Sent intermittently while `create_proxmox_container` is executing so callers can display a progress indicator. Each notification describes the currently running step (validation, provisioning, or each bootstrap command) and whether it succeeded or failed.
425
+
426
+ **Event Fields:**
427
+
428
+ * `step_index` (integer): 1-based index of the current step inside the entire provisioning sequence.
429
+ * `total_steps` (integer): Total number of steps that must run before provisioning completes.
430
+ * `step_name` (string): Internal step identifier (e.g., `create_container`, `apt_update`, `portacode_connect`).
431
+ * `step_label` (string): Human-friendly label suitable for UI (e.g., `Create container`, `Apt update`).
432
+ * `status` (string): One of `in_progress`, `completed`, or `failed`.
433
+ * `phase` (string): Either `lifecycle` (environment/container lifecycle) or `bootstrap` (per-command bootstrap work).
434
+ * `message` (string): Short description of what is happening or why a failure occurred.
435
+ * `details` (object, optional): Contains `attempt` (if retries were needed) and `error_summary` when a step fails.
436
+ * `request_id` (string, optional): Mirrors the request ID from the incoming `create_proxmox_container` payload when available.
437
+
438
+ ### `start_portacode_service`
439
+
440
+ Runs `sudo portacode service install` inside the container after the dashboard has created the corresponding Device record with the supplied public key.
441
+
442
+ **Payload Fields:**
443
+
444
+ * `ctid` (string, required): Container ID target.
445
+ * `step_index` (integer, required): Next step index to render inside `proxmox_container_progress`.
446
+ * `total_steps` (integer, required): The overall total number of steps (including lifecycle, bootstrap, and service installation).
447
+
448
+ **Responses:**
449
+
450
+ * Emits additional [`proxmox_container_progress`](#proxmox_container_progress-event) events to report the authentication and service-install steps.
451
+ * On success, emits a [`proxmox_service_started`](#proxmox_service_started-event).
452
+ * On failure, emits a generic [`error`](#error) event.
453
+
454
+ ### `proxmox_service_started`
455
+
456
+ Indicates that `portacode service install` finished successfully inside a managed container.
457
+
458
+ **Event Fields:**
459
+
460
+ * `success` (boolean): True when the install succeeded.
461
+ * `message` (string): Success summary (e.g., `Portacode service install completed`).
462
+ * `ctid` (string): Container ID.
337
463
 
338
464
  ### `clock_sync_request`
339
465
 
@@ -980,20 +1106,37 @@ Provides system information in response to a `system_info` action. Handled by [`
980
1106
  * `proxmox` (object): Detection hints for Proxmox VE nodes:
981
1107
  * `is_proxmox_node` (boolean): True when Proxmox artifacts (e.g., `/etc/proxmox-release`) exist.
982
1108
  * `version` (string|null): Raw contents of `/etc/proxmox-release` when readable.
983
- * `infra` (object): Portacode infrastructure configuration snapshot:
984
- * `configured` (boolean): True when `setup_proxmox_infra` stored an API token.
985
- * `host` (string|null): Hostname used for the API client (usually `localhost`).
986
- * `node` (string|null): Proxmox node name that was targeted.
987
- * `user` (string|null): API token owner (e.g., `root@pam`).
988
- * `token_name` (string|null): API token identifier.
989
- * `default_storage` (string|null): Storage pool chosen for future containers.
990
- * `templates` (array[string]): Cached list of available LXC templates.
991
- * `last_verified` (string|null): ISO timestamp when the token was last validated.
992
- * `network` (object):
993
- * `applied` (boolean): True when the bridge/NAT services were successfully configured.
994
- * `message` (string|null): Informational text about the network setup attempt.
995
- * `bridge` (string): The bridge interface configured (typically `vmbr1`).
996
- * `node_status` (object|null): Status response returned by the Proxmox API when validating the token.
1109
+ * `infra` (object): Portacode infrastructure configuration snapshot:
1110
+ * `configured` (boolean): True when `setup_proxmox_infra` stored an API token.
1111
+ * `host` (string|null): Hostname used for the API client (usually `localhost`).
1112
+ * `node` (string|null): Proxmox node name that was targeted.
1113
+ * `user` (string|null): API token owner (e.g., `root@pam`).
1114
+ * `token_name` (string|null): API token identifier.
1115
+ * `default_storage` (string|null): Storage pool chosen for future containers.
1116
+ * `templates` (array[string]): Cached list of available LXC templates.
1117
+ * `last_verified` (string|null): ISO timestamp when the token was last validated.
1118
+ * `network` (object):
1119
+ * `applied` (boolean): True when the bridge/NAT services were successfully configured.
1120
+ * `message` (string|null): Informational text about the network setup attempt.
1121
+ * `bridge` (string): The bridge interface configured (typically `vmbr1`).
1122
+ * `health` (string|null): `"healthy"` when the connectivity verification succeeded.
1123
+ * `node_status` (object|null): Status response returned by the Proxmox API when validating the token.
1124
+ * `managed_containers` (object): Cached summary of the Portacode-managed containers:
1125
+ * `updated_at` (string): ISO timestamp when this snapshot was last refreshed.
1126
+ * `count` (integer): Number of managed containers.
1127
+ * `total_ram_mib` (integer): RAM footprint summed across all containers.
1128
+ * `total_disk_gib` (integer): Disk footprint summed across all containers.
1129
+ * `total_cpu_share` (number): CPU shares requested across all containers.
1130
+ * `containers` (array[object]): Container summaries with the following fields:
1131
+ * `vmid` (string|null): Numeric CT ID.
1132
+ * `hostname` (string|null): Hostname configured in the CT.
1133
+ * `template` (string|null): Template identifier used.
1134
+ * `storage` (string|null): Storage pool backing the rootfs.
1135
+ * `disk_gib` (integer): Rootfs size in GiB.
1136
+ * `ram_mib` (integer): Memory size in MiB.
1137
+ * `cpu_share` (number): vCPU-equivalent share requested at creation.
1138
+ * `status` (string): Lowercase lifecycle status (e.g., `running`, `stopped`, `deleted`).
1139
+ * `created_at` (string|null): ISO timestamp recorded when the CT was provisioned.
997
1140
  * `portacode_version` (string): Installed CLI version returned by `portacode.__version__`.
998
1141
 
999
1142
  ### `proxmox_infra_configured`
@@ -1006,6 +1149,59 @@ Emitted after a successful `setup_proxmox_infra` action. The event reports the s
1006
1149
  * `message` (string): User-facing summary (e.g., "Proxmox infrastructure configured").
1007
1150
  * `infra` (object): Same snapshot described under [`system_info`](#system_info-event) `proxmox.infra`.
1008
1151
 
1152
+ ### `proxmox_infra_reverted`
1153
+
1154
+ Emitted after a successful `revert_proxmox_infra` action. Indicates the infra config is no longer present and the network was restored.
1155
+
1156
+ **Event Fields:**
1157
+
1158
+ * `success` (boolean): True when the revert completed.
1159
+ * `message` (string): Summary (e.g., "Proxmox infrastructure configuration reverted").
1160
+ * `infra` (object): Snapshot with `configured=false` (matching [`system_info`](#system_info-event) `proxmox.infra`).
1161
+
1162
+ ### `proxmox_container_created`
1163
+
1164
+ Emitted after a successful `create_proxmox_container` action to report the newly created CT, its Portacode public key, and the bootstrap logs.
1165
+
1166
+ **Event Fields:**
1167
+
1168
+ * `success` (boolean): True when the CT provisioning and `portacode connect` steps complete.
1169
+ * `message` (string): Human-readable summary (e.g., `Container 102 is ready`).
1170
+ * `ctid` (string): The container ID that was created.
1171
+ * `public_key` (string): Portacode public auth key discovered inside the container.
1172
+ * `container` (object): Metadata such as `vmid`, `hostname`, `template`, `storage`, `disk_gib`, `ram_mib`, and `cpus`.
1173
+ * `setup_steps` (array[object]): Detailed bootstrap step reports including stdout/stderr, elapsed time, and pass/fail status.
1174
+
1175
+ ### `proxmox_container_progress`
1176
+
1177
+ Sent continuously while `create_proxmox_container` runs so dashboards can show a progress bar tied to each lifecycle and bootstrap step.
1178
+
1179
+ **Event Fields:**
1180
+
1181
+ * `step_index` (integer): 1-based position of the step inside the entire provisioning workflow.
1182
+ * `total_steps` (integer): Total number of lifecycle and bootstrap steps for the current operation.
1183
+ * `step_name` (string): Internal identifier (e.g., `validate_environment`, `install_deps`, `portacode_connect`).
1184
+ * `step_label` (string): Friendly label suitable for the UI.
1185
+ * `status` (string): One of `in_progress`, `completed`, or `failed`.
1186
+ * `phase` (string): Either `lifecycle` (node validation/container lifecycle) or `bootstrap` (commands run inside the CT).
1187
+ * `message` (string): Short human-readable description of the action or failure.
1188
+ * `details` (object, optional): Contains `attempt` (when retries are used) and `error_summary` on failure.
1189
+ * `request_id` (string, optional): Mirrors the `create_proxmox_container` request when provided.
1190
+
1191
+ ### `proxmox_container_action`
1192
+
1193
+ Emitted after `start_proxmox_container`, `stop_proxmox_container`, or `remove_proxmox_container` commands complete. Each event includes the refreshed infra snapshot so dashboards can immediately display the latest managed container totals even though the `proxmox.infra.managed_containers` cache updates only every ~30 seconds.
1194
+
1195
+ **Event Fields:**
1196
+
1197
+ * `action` (string): The action that ran (`start`, `stop`, or `remove`).
1198
+ * `success` (boolean): True when the requested action succeeded.
1199
+ * `ctid` (string): Target CT ID.
1200
+ * `message` (string): Human-friendly summary (e.g., `Stopped container 103`).
1201
+ * `status` (string): The container’s new status (e.g., `running`, `stopped`, `deleted`).
1202
+ * `details` (object, optional): Exit status information (e.g., `exitstatus`, `stop_exitstatus`, `delete_exitstatus`).
1203
+ * `infra` (object): Same snapshot described under [`system_info`](#system_info-event) `proxmox.infra`, including the updated `managed_containers` summary.
1204
+
1009
1205
  ### <a name="clock_sync_response"></a>`clock_sync_response`
1010
1206
 
1011
1207
  Reply sent by the gateway immediately after receiving a `clock_sync_request`. Devices use this event plus the measured round-trip time to keep their local `ntp_clock` offset accurate.
@@ -14,6 +14,7 @@ from .terminal_handlers import (
14
14
  TerminalListHandler,
15
15
  )
16
16
  from .system_handlers import SystemInfoHandler
17
+ from .update_handler import UpdatePortacodeHandler
17
18
  from .file_handlers import (
18
19
  FileReadHandler,
19
20
  FileWriteHandler,
@@ -40,8 +41,15 @@ from .project_state_handlers import (
40
41
  ProjectStateGitRevertHandler,
41
42
  ProjectStateGitCommitHandler,
42
43
  )
43
- from .update_handler import UpdatePortacodeHandler
44
- from .proxmox_infra import ConfigureProxmoxInfraHandler
44
+ from .proxmox_infra import (
45
+ ConfigureProxmoxInfraHandler,
46
+ CreateProxmoxContainerHandler,
47
+ RevertProxmoxInfraHandler,
48
+ StartPortacodeServiceHandler,
49
+ StartProxmoxContainerHandler,
50
+ StopProxmoxContainerHandler,
51
+ RemoveProxmoxContainerHandler,
52
+ )
45
53
 
46
54
  __all__ = [
47
55
  "BaseHandler",
@@ -54,6 +62,7 @@ __all__ = [
54
62
  "TerminalListHandler",
55
63
  "SystemInfoHandler",
56
64
  "ConfigureProxmoxInfraHandler",
65
+ "CreateProxmoxContainerHandler",
57
66
  # File operation handlers (optional - register as needed)
58
67
  "FileReadHandler",
59
68
  "FileWriteHandler",
@@ -79,5 +88,10 @@ __all__ = [
79
88
  "ProjectStateGitUnstageHandler",
80
89
  "ProjectStateGitRevertHandler",
81
90
  "ProjectStateGitCommitHandler",
91
+ "StartPortacodeServiceHandler",
92
+ "StartProxmoxContainerHandler",
93
+ "StopProxmoxContainerHandler",
94
+ "RemoveProxmoxContainerHandler",
82
95
  "UpdatePortacodeHandler",
96
+ "RevertProxmoxInfraHandler",
83
97
  ]