@kyan-du/agent-wechat-cli 0.14.5 → 0.15.1
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 +36 -11
- package/dist/image-compatibility.json +1 -1
- package/package.json +1 -1
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
|
-
|
|
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
|
|
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)
|
|
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.
|
|
9810
|
+
var VERSION = false ? "0.0.0-test" : "0.15.1";
|
|
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
|
|
9978
|
+
inventory: inventoryBinding(container, inventory)
|
|
9954
9979
|
};
|
|
9955
9980
|
}
|
|
9956
9981
|
async function syncServer(binary, sha256) {
|