@kyan-du/agent-wechat-cli 0.14.5 → 0.14.6

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/dist/cli.js CHANGED
@@ -9410,9 +9410,26 @@ function isReconcileableContainer(info, inventory) {
9410
9410
  const id = inventory?.containerId;
9411
9411
  return Boolean(id && (info.Id === id || info.Id.startsWith(id) || id.startsWith(info.Id)));
9412
9412
  }
9413
+ function inventoryBinding(live, inventory) {
9414
+ if (!inventory) return "absent";
9415
+ if (live && !isReconcileableContainer(live, inventory)) return "stale";
9416
+ return "trusted";
9417
+ }
9413
9418
  function hasOwnedVolume(existing, name, role) {
9414
9419
  return existing.Name === name && existing.Driver === "local" && existing.Labels?.[INSTANCE_LABEL] === "default" && existing.Labels?.[VOLUME_ROLE_LABEL] === role;
9415
9420
  }
9421
+ var DESTINATIONS = ["/data", "/home/wechat"];
9422
+ function sameFixedInstance(evidence) {
9423
+ if (evidence.containerName !== evidence.inventory.containerName) return false;
9424
+ const roles = ["data", "wechat-home"];
9425
+ return roles.every((role, index) => {
9426
+ const volume = evidence.volumes[index];
9427
+ const name = evidence.inventory.volumes[index];
9428
+ if (!volume || !hasOwnedVolume(volume, name, role)) return false;
9429
+ const mounted = (evidence.mounts ?? []).filter((mount) => mount.Destination === DESTINATIONS[index]);
9430
+ return mounted.length === 1 && mounted[0].Type === "volume" && mounted[0].Name === name;
9431
+ });
9432
+ }
9416
9433
 
9417
9434
  // src/lifecycle.ts
9418
9435
  function docker(args, options = {}) {
@@ -9511,6 +9528,17 @@ function assertOwnedVolumes(inventory) {
9511
9528
  function assertOwnedContainer(info, inventory) {
9512
9529
  if (!isReconcileableContainer(info, inventory)) throw new CliError("CONTAINER_OWNERSHIP_MISMATCH", "refusing to operate on an unowned container with the fixed name", EXIT.ENVIRONMENT);
9513
9530
  }
9531
+ function rebindIfSameInstance(info, inventory) {
9532
+ if (isReconcileableContainer(info, inventory)) return inventory;
9533
+ const roles = ["data", "wechat-home"];
9534
+ const volumes = roles.map((_role, index) => inspectVolume(inventory.volumes[index]));
9535
+ if (!sameFixedInstance({ containerName: CONTAINER_NAME, volumes, mounts: info.Mounts, inventory })) {
9536
+ throw new CliError("CONTAINER_OWNERSHIP_MISMATCH", "refusing to operate on an unowned container with the fixed name", EXIT.ENVIRONMENT);
9537
+ }
9538
+ const next = { ...inventory, containerId: info.Id, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
9539
+ saveInventory(next);
9540
+ return next;
9541
+ }
9514
9542
  function clearContainerIdentity(inventory) {
9515
9543
  const info = inspectContainer();
9516
9544
  if (!info) throw new CliError("INSTANCE_NOT_RUNNING", "trusted container is required to clear container identity", EXIT.CLEANUP);
@@ -9578,14 +9606,14 @@ async function startInstance(options) {
9578
9606
  const existing = inspectContainer();
9579
9607
  const current = loadInventory();
9580
9608
  if (existing) {
9581
- assertOwnedContainer(existing, current);
9609
+ if (!current) throw new CliError("INSTANCE_INVENTORY_MISSING", "existing container has no trusted inventory", EXIT.ENVIRONMENT);
9610
+ const bound = rebindIfSameInstance(existing, current);
9582
9611
  if (options.outbound && Object.keys(options.outbound).length > 0) {
9583
9612
  throw new CliError("OUTBOUND_RESTART_REQUIRED", "outbound policy changed; run wx restart to recreate the container", EXIT.ARGUMENT);
9584
9613
  }
9585
- if (!current) throw new CliError("INSTANCE_INVENTORY_MISSING", "existing container has no trusted inventory", EXIT.ENVIRONMENT);
9586
9614
  if (!existing.State?.Running) docker(["start", CONTAINER_NAME], { inherit: true });
9587
9615
  await waitCompatible(options.token);
9588
- return current;
9616
+ return bound;
9589
9617
  }
9590
9618
  const selected = resolveImage({ explicit: options.image, pull: options.pull, noPull: options.noPull, localDefault: options.localDefault });
9591
9619
  const provisional = createInventory(selected.requestedReference, options.identity, selected.digest);
@@ -9634,8 +9662,8 @@ function stopInstance() {
9634
9662
  const info = inspectContainer();
9635
9663
  if (!info) return { stopped: false };
9636
9664
  const inventory = loadInventory();
9637
- assertOwnedContainer(info, inventory);
9638
9665
  if (!inventory) throw new CliError("INSTANCE_INVENTORY_MISSING", "refusing to remove an unowned container", EXIT.ENVIRONMENT);
9666
+ rebindIfSameInstance(info, inventory);
9639
9667
  docker(["rm", "-f", info.Id], { inherit: true });
9640
9668
  return { stopped: true };
9641
9669
  }
@@ -9676,8 +9704,8 @@ async function replaceImage(options) {
9676
9704
  const previous = loadInventory();
9677
9705
  if (!previous) throw new CliError("INSTANCE_INVENTORY_MISSING", "start the instance before image upgrade", EXIT.ENVIRONMENT);
9678
9706
  const info = inspectContainer();
9679
- if (info) assertOwnedContainer(info, previous);
9680
- const reconciled = previous;
9707
+ if (info) rebindIfSameInstance(info, previous);
9708
+ const reconciled = loadInventory() ?? previous;
9681
9709
  const selected = resolveImage({ explicit: options.image, pull: true, localDefault: previous.imageRef });
9682
9710
  if (selected.digest === reconciled.imageDigest) return reconciled;
9683
9711
  if (info) {
@@ -9779,7 +9807,7 @@ function checkCliUpgrade(currentVersion, readLatest = () => execFileSync2("npm",
9779
9807
  }
9780
9808
 
9781
9809
  // src/cli.ts
9782
- var VERSION = false ? "0.0.0-test" : "0.14.5";
9810
+ var VERSION = false ? "0.0.0-test" : "0.14.6";
9783
9811
  var MAX_UPLOAD_BYTES = 50 * 1024 * 1024;
9784
9812
  function readToken() {
9785
9813
  try {
@@ -9942,15 +9970,12 @@ function programStatus() {
9942
9970
  const inventory = loadInventory();
9943
9971
  if (!dockerAvailable()) throw new CliError("DOCKER_UNAVAILABLE", "Docker daemon is unavailable", EXIT.ENVIRONMENT, { diagnostics: { docker: "unavailable", inventory: inventory ? "trusted" : "absent" } });
9944
9972
  const container = inspectContainer();
9945
- if (container) {
9946
- if (!inventory) throw new CliError("INSTANCE_INVENTORY_MISSING", "existing container has no trusted inventory", EXIT.ENVIRONMENT);
9947
- }
9948
9973
  return {
9949
9974
  cliVersion: VERSION,
9950
9975
  docker: "available",
9951
9976
  container: container ? container.State?.Running ? "running" : "stopped" : "absent",
9952
9977
  imageDigest: inventory?.imageDigest,
9953
- inventory: inventory ? "trusted" : "absent"
9978
+ inventory: inventoryBinding(container, inventory)
9954
9979
  };
9955
9980
  }
9956
9981
  async function syncServer(binary, sha256) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "cliVersion": "0.14.5",
3
+ "cliVersion": "0.14.6",
4
4
  "repository": "ghcr.io/kyan-du/agent-wechat",
5
5
  "apiVersion": 1,
6
6
  "allowedReferences": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kyan-du/agent-wechat-cli",
3
- "version": "0.14.5",
3
+ "version": "0.14.6",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "wx": "./dist/cli.js"