@sellable/install 0.1.624 → 0.1.625-wip.phase189.20260813.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/container/Dockerfile +4 -4
- package/container/README.md +1 -1
- package/lib/sellable-agent/fly-admin-image/admin-runtime.mjs +34 -21
- package/lib/sellable-agent/fly-customer-image/Dockerfile +1 -1
- package/lib/sellable-agent/fly-customer-image/customer-runtime.mjs +50 -2
- package/lib/sellable-agent/fly-customer-worker.mjs +6 -2
- package/lib/sellable-agent/host-bootstrap.mjs +1 -1
- package/lib/sellable-agent/host-worker.mjs +1 -1
- package/lib/sellable-agent/profile-materializer.mjs +1 -1
- package/lib/sellable-agent/provisioning-adapter.mjs +1 -1
- package/package.json +1 -1
package/container/Dockerfile
CHANGED
|
@@ -3,12 +3,12 @@ FROM ${HERMES_IMAGE}
|
|
|
3
3
|
|
|
4
4
|
USER root
|
|
5
5
|
|
|
6
|
-
ARG INSTALLER_PACKAGE=@sellable/install@0.1.
|
|
6
|
+
ARG INSTALLER_PACKAGE=@sellable/install@0.1.625-wip.phase189.20260813.1
|
|
7
7
|
ARG MCP_PACKAGE=@sellable/mcp@0.1.867
|
|
8
8
|
ARG INSTALLER_INTEGRITY
|
|
9
9
|
ARG MCP_INTEGRITY=sha512-8acJ5MfqgXiu9ylK65LlQ7LUBN5GN5fEXOwDTArxYAN7nBvVLhdz0nTGMERc6qCFNBbILTKvo4IErJOnAcJTDA==
|
|
10
10
|
|
|
11
|
-
RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.
|
|
11
|
+
RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.625-wip.phase189.20260813.1" \
|
|
12
12
|
&& test "${MCP_PACKAGE}" = "@sellable/mcp@0.1.867" \
|
|
13
13
|
&& test -n "${INSTALLER_INTEGRITY}" \
|
|
14
14
|
&& test "$(npm view "${INSTALLER_PACKAGE}" dist.integrity)" = "${INSTALLER_INTEGRITY}" \
|
|
@@ -23,9 +23,9 @@ RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.624" \
|
|
|
23
23
|
&& mkdir -p /opt/sellable-agent/install-root /opt/sellable-agent/mcp-root \
|
|
24
24
|
&& npm install --prefix /opt/sellable-agent/install-root --omit=dev --ignore-scripts --no-audit --no-fund "${INSTALLER_PACKAGE}" \
|
|
25
25
|
&& npm install --prefix /opt/sellable-agent/mcp-root --omit=dev --ignore-scripts --no-audit --no-fund "${MCP_PACKAGE}" \
|
|
26
|
-
&& node --input-type=module -e "import { readFileSync } from 'node:fs'; const install = JSON.parse(readFileSync('/opt/sellable-agent/install-root/node_modules/@sellable/install/package.json')); const mcp = JSON.parse(readFileSync('/opt/sellable-agent/mcp-root/node_modules/@sellable/mcp/package.json')); if (install.name !== '@sellable/install' || install.version !== '0.1.
|
|
26
|
+
&& node --input-type=module -e "import { readFileSync } from 'node:fs'; const install = JSON.parse(readFileSync('/opt/sellable-agent/install-root/node_modules/@sellable/install/package.json')); const mcp = JSON.parse(readFileSync('/opt/sellable-agent/mcp-root/node_modules/@sellable/mcp/package.json')); if (install.name !== '@sellable/install' || install.version !== '0.1.625-wip.phase189.20260813.1' || mcp.name !== '@sellable/mcp' || mcp.version !== '0.1.867') throw new Error('package identity rejected');" \
|
|
27
27
|
&& node --input-type=module -e "import { buildExternalRuntimeClosure } from '/opt/sellable-agent/install-root/node_modules/@sellable/install/lib/sellable-agent/external-runtime-builder.mjs'; const built = buildExternalRuntimeClosure({ mcpPackageRoot: '/opt/sellable-agent/mcp-root/node_modules/@sellable/mcp', mcpNodeModulesRoot: '/opt/sellable-agent/mcp-root/node_modules', hermesSourceRoot: '/opt/hermes', ownerUid: 0, ownerGid: 0 }); if (!built.closureDigest) throw new Error('runtime closure rejected');" \
|
|
28
|
-
&& node --input-type=module -e "import { chmodSync, writeFileSync } from 'node:fs'; const release = { installerPackage: '@sellable/install@0.1.
|
|
28
|
+
&& node --input-type=module -e "import { chmodSync, writeFileSync } from 'node:fs'; const release = { installerPackage: '@sellable/install@0.1.625-wip.phase189.20260813.1', installerIntegrity: process.argv[1], mcpPackage: '@sellable/mcp@0.1.867', mcpIntegrity: process.argv[2] }; writeFileSync('/opt/sellable-agent/release.json', JSON.stringify(release) + '\\n', { mode: 0o444 }); chmodSync('/opt/sellable-agent/release.json', 0o444);" "${INSTALLER_INTEGRITY}" "${MCP_INTEGRITY}" \
|
|
29
29
|
&& npm cache clean --force
|
|
30
30
|
|
|
31
31
|
COPY entrypoint.sh /usr/local/bin/sellable-agent-container-entrypoint
|
package/container/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
This image is a dedicated Agent worker/runtime boundary beside an existing Hermes dashboard. It never replaces or reconfigures the dashboard container.
|
|
4
4
|
|
|
5
5
|
Build from this directory after
|
|
6
|
-
`@sellable/install@0.1.
|
|
6
|
+
`@sellable/install@0.1.625-wip.phase189.20260813.1` is
|
|
7
7
|
published:
|
|
8
8
|
|
|
9
9
|
```sh
|
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
buildAdminAgentServiceEnvironment,
|
|
43
43
|
buildNativeHermesLaunch,
|
|
44
44
|
buildRuntimeServingObservation,
|
|
45
|
+
isOperationBoundBackupClaim,
|
|
45
46
|
} from "../admin-artifact/node_modules/@sellable/install/lib/sellable-agent/fly-customer-worker.mjs";
|
|
46
47
|
import sodium from "../admin-artifact/node_modules/libsodium-wrappers/dist/modules-esm/libsodium-wrappers.mjs";
|
|
47
48
|
import { SELLABLE_ALLOWED_TOOLSETS } from "../fly-capabilities-bridge.mjs";
|
|
@@ -1262,7 +1263,13 @@ function operationIdentity(claim, exchange) {
|
|
|
1262
1263
|
|
|
1263
1264
|
function operationSnapshotIdentity(claim, exchange) {
|
|
1264
1265
|
const authority = claim?.runtimeAuthority;
|
|
1265
|
-
if (
|
|
1266
|
+
if (
|
|
1267
|
+
!isOperationBoundBackupClaim(claim) ||
|
|
1268
|
+
authority?.scope !== "ASSIGNED" ||
|
|
1269
|
+
authority.runtimeArtifactId !== authority.assignedRuntimeArtifactId
|
|
1270
|
+
) {
|
|
1271
|
+
return undefined;
|
|
1272
|
+
}
|
|
1266
1273
|
return {
|
|
1267
1274
|
operationId: claim.operation.id,
|
|
1268
1275
|
authorityGeneration: authority.authorityGeneration,
|
|
@@ -3261,6 +3268,27 @@ async function runAdminProduction() {
|
|
|
3261
3268
|
exchange,
|
|
3262
3269
|
client,
|
|
3263
3270
|
});
|
|
3271
|
+
if (isOperationBoundBackupClaim(claim)) {
|
|
3272
|
+
const snapshotIdentity = operationSnapshotIdentity(claim, exchange);
|
|
3273
|
+
if (!snapshotIdentity) {
|
|
3274
|
+
throw new Error("admin_operation_backup_claim_rejected");
|
|
3275
|
+
}
|
|
3276
|
+
const profile = activeLaunch?.profile ?? profileContractForClaim(claim);
|
|
3277
|
+
const backup = await flushHermesSnapshot({
|
|
3278
|
+
client,
|
|
3279
|
+
profileId: basename(profile.profileHome),
|
|
3280
|
+
profileRoot: profile.profileHome,
|
|
3281
|
+
operationIdentity: snapshotIdentity,
|
|
3282
|
+
});
|
|
3283
|
+
if (!backup.ok) {
|
|
3284
|
+
throw new Error("admin_operation_backup_proof_unavailable");
|
|
3285
|
+
}
|
|
3286
|
+
operationHeartbeat.assertHealthy();
|
|
3287
|
+
await operationHeartbeat.stop();
|
|
3288
|
+
operationHeartbeat = null;
|
|
3289
|
+
failures = 0;
|
|
3290
|
+
continue;
|
|
3291
|
+
}
|
|
3264
3292
|
await activeModelHealthReporter?.stop();
|
|
3265
3293
|
activeModelHealthReporter = null;
|
|
3266
3294
|
await stopNativeGateway(activeGateway);
|
|
@@ -3347,18 +3375,6 @@ async function runAdminProduction() {
|
|
|
3347
3375
|
generationFence: claim.adminRuntimeGeneration.fence,
|
|
3348
3376
|
profileContract,
|
|
3349
3377
|
};
|
|
3350
|
-
const upgradeBackup =
|
|
3351
|
-
claim.runtimeAuthority?.scope === "CANDIDATE"
|
|
3352
|
-
? await flushHermesSnapshot({
|
|
3353
|
-
client,
|
|
3354
|
-
profileId: basename(profileContract.profileHome),
|
|
3355
|
-
profileRoot: profileContract.profileHome,
|
|
3356
|
-
operationIdentity: operationSnapshotIdentity(claim, exchange),
|
|
3357
|
-
})
|
|
3358
|
-
: null;
|
|
3359
|
-
if (upgradeBackup && !upgradeBackup.ok) {
|
|
3360
|
-
throw new Error("admin_upgrade_backup_proof_unavailable");
|
|
3361
|
-
}
|
|
3362
3378
|
const memoryRestore = await restoreLatestHermesSnapshot({
|
|
3363
3379
|
profileId: basename(profileContract.profileHome),
|
|
3364
3380
|
profileRoot: profileContract.profileHome,
|
|
@@ -3403,14 +3419,11 @@ async function runAdminProduction() {
|
|
|
3403
3419
|
installed,
|
|
3404
3420
|
desiredLifecycle
|
|
3405
3421
|
);
|
|
3406
|
-
const memorySnapshot =
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
profileRoot: profile.profileHome,
|
|
3412
|
-
operationIdentity: operationSnapshotIdentity(claim, exchange),
|
|
3413
|
-
}));
|
|
3422
|
+
const memorySnapshot = await flushHermesSnapshot({
|
|
3423
|
+
client,
|
|
3424
|
+
profileId: profile.profile,
|
|
3425
|
+
profileRoot: profile.profileHome,
|
|
3426
|
+
});
|
|
3414
3427
|
const settings = settingsProof(
|
|
3415
3428
|
imported.receipt.generationRoot,
|
|
3416
3429
|
imported.receipt.settingsDigest
|
|
@@ -6,7 +6,7 @@ USER root
|
|
|
6
6
|
|
|
7
7
|
ARG MCP_PACKAGE=@sellable/mcp@0.1.867
|
|
8
8
|
ARG MCP_INTEGRITY=sha512-8acJ5MfqgXiu9ylK65LlQ7LUBN5GN5fEXOwDTArxYAN7nBvVLhdz0nTGMERc6qCFNBbILTKvo4IErJOnAcJTDA==
|
|
9
|
-
ARG INSTALLER_PACKAGE=@sellable/install@0.1.
|
|
9
|
+
ARG INSTALLER_PACKAGE=@sellable/install@0.1.625-wip.phase189.20260813.1
|
|
10
10
|
ARG ADMIN_MCP_PACKAGE=@sellable/admin-mcp@0.1.186-wip.phase158.20260802034727
|
|
11
11
|
ARG ADMIN_MCP_INTEGRITY=sha512-qYNew5wd2IfgVcp1UYOG9QvpF/8Mx19YJ5HQtMKzvSfUf3evePjtaKsoXLf2C/GUJ5QlLlHJo84VWOI3V01+9A==
|
|
12
12
|
ARG TUS_JS_CLIENT_VERSION=4.3.1
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
buildRuntimeServingObservation,
|
|
23
23
|
clearCustomerRuntimeSecrets,
|
|
24
24
|
installCustomerRuntimeSecrets,
|
|
25
|
+
isOperationBoundBackupClaim,
|
|
25
26
|
} from "../fly-customer-worker.mjs";
|
|
26
27
|
import {
|
|
27
28
|
claimWithSoulObservation,
|
|
@@ -98,7 +99,7 @@ const BOOT_SESSION_ID = randomUUID();
|
|
|
98
99
|
const HERMES_VERSION = process.env.SELLABLE_AGENT_HERMES_VERSION ?? "0.20.0";
|
|
99
100
|
const INSTALLER_PACKAGE =
|
|
100
101
|
process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ??
|
|
101
|
-
"@sellable/install@0.1.
|
|
102
|
+
"@sellable/install@0.1.625-wip.phase189.20260813.1";
|
|
102
103
|
const MCP_PACKAGE =
|
|
103
104
|
process.env.SELLABLE_AGENT_MCP_PACKAGE ?? "@sellable/mcp@0.1.867";
|
|
104
105
|
|
|
@@ -402,6 +403,26 @@ function operationIdentity(claim, exchange) {
|
|
|
402
403
|
};
|
|
403
404
|
}
|
|
404
405
|
|
|
406
|
+
function operationSnapshotIdentity(claim, exchange) {
|
|
407
|
+
const authority = claim?.runtimeAuthority;
|
|
408
|
+
if (
|
|
409
|
+
!isOperationBoundBackupClaim(claim) ||
|
|
410
|
+
authority?.scope !== "ASSIGNED" ||
|
|
411
|
+
authority.runtimeArtifactId !== authority.assignedRuntimeArtifactId
|
|
412
|
+
) {
|
|
413
|
+
return undefined;
|
|
414
|
+
}
|
|
415
|
+
return {
|
|
416
|
+
operationId: claim.operation.id,
|
|
417
|
+
authorityGeneration: authority.authorityGeneration,
|
|
418
|
+
runtimeArtifactId: authority.assignedRuntimeArtifactId,
|
|
419
|
+
sourceMachineId: exchange.workerId,
|
|
420
|
+
sourceMachineVersion: authority.machineVersion,
|
|
421
|
+
sourceBootSessionId: BOOT_SESSION_ID,
|
|
422
|
+
profileSchemaVersion: "customer-native-profile/v1",
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
|
|
405
426
|
export function customerServingObservation(activeRuntime, exchange) {
|
|
406
427
|
try {
|
|
407
428
|
const authority = activeRuntime?.claim?.runtimeAuthority;
|
|
@@ -2631,7 +2652,12 @@ function completionReceipt({
|
|
|
2631
2652
|
};
|
|
2632
2653
|
}
|
|
2633
2654
|
|
|
2634
|
-
async function flushHermesSnapshot({
|
|
2655
|
+
async function flushHermesSnapshot({
|
|
2656
|
+
client,
|
|
2657
|
+
profileId,
|
|
2658
|
+
profileRoot,
|
|
2659
|
+
operationIdentity,
|
|
2660
|
+
}) {
|
|
2635
2661
|
try {
|
|
2636
2662
|
markHermesSnapshotDirty(profileRoot);
|
|
2637
2663
|
return await reconcileHermesSnapshot({
|
|
@@ -2640,6 +2666,7 @@ async function flushHermesSnapshot({ client, profileId, profileRoot }) {
|
|
|
2640
2666
|
hermesRoot: DATA_ROOT,
|
|
2641
2667
|
hermesVersion: HERMES_VERSION,
|
|
2642
2668
|
debounceMs: 0,
|
|
2669
|
+
operationIdentity,
|
|
2643
2670
|
upload: ({ archiveDigest, archiveBytes, sourceProfileId, bytes }) =>
|
|
2644
2671
|
client.putMemorySnapshot(
|
|
2645
2672
|
{
|
|
@@ -2647,6 +2674,7 @@ async function flushHermesSnapshot({ client, profileId, profileRoot }) {
|
|
|
2647
2674
|
archiveBytes,
|
|
2648
2675
|
hermesVersion: HERMES_VERSION,
|
|
2649
2676
|
sourceProfileId,
|
|
2677
|
+
...(operationIdentity ?? {}),
|
|
2650
2678
|
},
|
|
2651
2679
|
bytes
|
|
2652
2680
|
),
|
|
@@ -3054,6 +3082,26 @@ async function main() {
|
|
|
3054
3082
|
exchange,
|
|
3055
3083
|
client,
|
|
3056
3084
|
});
|
|
3085
|
+
if (isOperationBoundBackupClaim(claim)) {
|
|
3086
|
+
const snapshotIdentity = operationSnapshotIdentity(claim, exchange);
|
|
3087
|
+
if (!snapshotIdentity) {
|
|
3088
|
+
throw new Error("customer_operation_backup_claim_rejected");
|
|
3089
|
+
}
|
|
3090
|
+
const backup = await flushHermesSnapshot({
|
|
3091
|
+
client,
|
|
3092
|
+
profileId: claim.operation.profileId,
|
|
3093
|
+
profileRoot: join(PROFILES_ROOT, claim.operation.profileId),
|
|
3094
|
+
operationIdentity: snapshotIdentity,
|
|
3095
|
+
});
|
|
3096
|
+
if (!backup.ok) {
|
|
3097
|
+
throw new Error("customer_operation_backup_proof_unavailable");
|
|
3098
|
+
}
|
|
3099
|
+
operationHeartbeat.assertHealthy();
|
|
3100
|
+
await operationHeartbeat.stop();
|
|
3101
|
+
operationHeartbeat = null;
|
|
3102
|
+
failures = 0;
|
|
3103
|
+
continue;
|
|
3104
|
+
}
|
|
3057
3105
|
await activeRuntime?.modelHealthReporter?.stop();
|
|
3058
3106
|
await endpointRelay.fenceActive("LIFECYCLE_REFRESH");
|
|
3059
3107
|
await stopNativeGateway(activeRuntime?.gateway);
|
|
@@ -32,6 +32,11 @@ function stableJson(value) {
|
|
|
32
32
|
return JSON.stringify(value);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/** The only claim that may write an operation-bound snapshot without applying. */
|
|
36
|
+
export function isOperationBoundBackupClaim(claim) {
|
|
37
|
+
return claim?.operation?.stage === "BACKING_UP";
|
|
38
|
+
}
|
|
39
|
+
|
|
35
40
|
// CUSTOMER and ADMIN runtimes share this one serving-observation builder.
|
|
36
41
|
export function buildRuntimeServingObservation(input = {}) {
|
|
37
42
|
const keys = [
|
|
@@ -56,8 +61,7 @@ export function buildRuntimeServingObservation(input = {}) {
|
|
|
56
61
|
"nativeGateway",
|
|
57
62
|
"customerRouting",
|
|
58
63
|
];
|
|
59
|
-
const identity = (value) =>
|
|
60
|
-
typeof value === "string" && SAFE_ID.test(value);
|
|
64
|
+
const identity = (value) => typeof value === "string" && SAFE_ID.test(value);
|
|
61
65
|
const mcp = (value, name) =>
|
|
62
66
|
exactKeys(value, ["serverInfoName", "toolCount"]) &&
|
|
63
67
|
value.serverInfoName === name &&
|
|
@@ -38,7 +38,7 @@ import { installAgentHostServices } from "./service-installer.mjs";
|
|
|
38
38
|
const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
|
|
39
39
|
const VERSION = "sellable-agent-host-bootstrap/v1";
|
|
40
40
|
const RECEIPT_VERSION = "sellable-agent-host-registration/v1";
|
|
41
|
-
const INSTALLER_PACKAGE = "@sellable/install@0.1.
|
|
41
|
+
const INSTALLER_PACKAGE = "@sellable/install@0.1.625-wip.phase189.20260813.1";
|
|
42
42
|
const MCP_PACKAGE = "@sellable/mcp@0.1.867";
|
|
43
43
|
const HERMES_VERSION = "0.18.0";
|
|
44
44
|
const SHA256 = /^[a-f0-9]{64}$/;
|
|
@@ -1547,7 +1547,7 @@ export function compileClaimToProfileDesired(activeClaim, config) {
|
|
|
1547
1547
|
pinned.hermesCli !== "hermes" ||
|
|
1548
1548
|
pinned.hermesVersion !== "0.18.0" ||
|
|
1549
1549
|
pinned.installerPackage !==
|
|
1550
|
-
"@sellable/install@0.1.
|
|
1550
|
+
"@sellable/install@0.1.625-wip.phase189.20260813.1" ||
|
|
1551
1551
|
pinned.mcpPackage !== "@sellable/mcp@0.1.867" ||
|
|
1552
1552
|
!Array.isArray(policy.toolInclude) ||
|
|
1553
1553
|
policy.toolInclude.length === 0 ||
|
|
@@ -279,7 +279,7 @@ function validateDesired(desired) {
|
|
|
279
279
|
desired.hermesCli !== "hermes" ||
|
|
280
280
|
desired.hermesVersion !== "0.18.0" ||
|
|
281
281
|
desired.installerPackage !==
|
|
282
|
-
"@sellable/install@0.1.
|
|
282
|
+
"@sellable/install@0.1.625-wip.phase189.20260813.1" ||
|
|
283
283
|
desired.mcpPackage !== "@sellable/mcp@0.1.867" ||
|
|
284
284
|
!Array.isArray(desired.toolInclude) ||
|
|
285
285
|
desired.toolInclude.length === 0 ||
|
|
@@ -26,7 +26,7 @@ import { deriveContainedProfileId } from "./profile-materializer.mjs";
|
|
|
26
26
|
|
|
27
27
|
export const PROVISIONING_ACTION = "PROVISION_HERMES_PROFILE";
|
|
28
28
|
export const PINNED_INSTALL_PACKAGE =
|
|
29
|
-
"@sellable/install@0.1.
|
|
29
|
+
"@sellable/install@0.1.625-wip.phase189.20260813.1";
|
|
30
30
|
export const PINNED_MCP_PACKAGE = "@sellable/mcp@0.1.867";
|
|
31
31
|
const PINNED_INSTALL_VERSION = PINNED_INSTALL_PACKAGE.slice(
|
|
32
32
|
PINNED_INSTALL_PACKAGE.lastIndexOf("@") + 1
|