@sellable/install 0.1.757 → 0.1.758

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.
@@ -3,12 +3,12 @@ FROM ${HERMES_IMAGE}
3
3
 
4
4
  USER root
5
5
 
6
- ARG INSTALLER_PACKAGE=@sellable/install@0.1.757
6
+ ARG INSTALLER_PACKAGE=@sellable/install@0.1.758
7
7
  ARG MCP_PACKAGE=@sellable/mcp@0.1.938
8
8
  ARG INSTALLER_INTEGRITY
9
9
  ARG MCP_INTEGRITY=sha512-wcVCiCXVvKeE/SufP+2iXk8zgzwYWh78M/1vwa7oorF9UZbzut9szyZV47t4iMX9owYgBVaGwdlOC6eX8VQX4A==
10
10
 
11
- RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.757" \
11
+ RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.758" \
12
12
  && test "${MCP_PACKAGE}" = "@sellable/mcp@0.1.938" \
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.757" \
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.757' || mcp.name !== '@sellable/mcp' || mcp.version !== '0.1.938') throw new Error('package identity rejected');" \
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.758' || mcp.name !== '@sellable/mcp' || mcp.version !== '0.1.938') 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.757', installerIntegrity: process.argv[1], mcpPackage: '@sellable/mcp@0.1.938', 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}" \
28
+ && node --input-type=module -e "import { chmodSync, writeFileSync } from 'node:fs'; const release = { installerPackage: '@sellable/install@0.1.758', installerIntegrity: process.argv[1], mcpPackage: '@sellable/mcp@0.1.938', 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
@@ -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.757` is
6
+ `@sellable/install@0.1.758` is
7
7
  published:
8
8
 
9
9
  ```sh
@@ -8,7 +8,7 @@ ENV PLAYWRIGHT_BROWSERS_PATH=/opt/hermes/.playwright
8
8
 
9
9
  ARG MCP_PACKAGE=@sellable/mcp@0.1.938
10
10
  ARG MCP_INTEGRITY=sha512-wcVCiCXVvKeE/SufP+2iXk8zgzwYWh78M/1vwa7oorF9UZbzut9szyZV47t4iMX9owYgBVaGwdlOC6eX8VQX4A==
11
- ARG INSTALLER_PACKAGE=@sellable/install@0.1.757
11
+ ARG INSTALLER_PACKAGE=@sellable/install@0.1.758
12
12
  ARG ADMIN_MCP_PACKAGE=@sellable/admin-mcp@0.1.202
13
13
  ARG ADMIN_MCP_INTEGRITY=sha512-ym3aye/0vQ8tfULJlKz9JFOxvIQsl1G+n3np+TTgK/tecwNblBo/j3AkTnRqH9iomKzPbZzP+n4tEQsvsU8ByA==
14
14
  ARG TUS_JS_CLIENT_VERSION=4.3.1
@@ -122,7 +122,7 @@ const RUNTIME_GENERATION = Number(
122
122
  const BOOT_SESSION_ID = randomUUID();
123
123
  const HERMES_VERSION = process.env.SELLABLE_AGENT_HERMES_VERSION ?? "0.21.3";
124
124
  const INSTALLER_PACKAGE =
125
- process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ?? "@sellable/install@0.1.757";
125
+ process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ?? "@sellable/install@0.1.758";
126
126
  const MCP_PACKAGE =
127
127
  process.env.SELLABLE_AGENT_MCP_PACKAGE ?? "@sellable/mcp@0.1.938";
128
128
  export const ENDPOINT_MAX_CONCURRENT_RUNS = 10;
@@ -233,6 +233,14 @@ const TRANSIENT_PROFILE_PATHS = new Set([
233
233
  // symlink remains rejected below.
234
234
  ".config/pulse",
235
235
  ]);
236
+
237
+ export function isHermesTransientProfilePath(relativePath) {
238
+ const [topLevel] = relativePath.split("/", 1);
239
+ return (
240
+ TRANSIENT_PROFILE_ROOTS.has(topLevel) ||
241
+ TRANSIENT_PROFILE_PATHS.has(relativePath)
242
+ );
243
+ }
236
244
  // The encrypted Fly volume remains the authoritative full profile. The
237
245
  // portable disaster-recovery archive also carries state.db and sessions so a
238
246
  // replacement volume retains chat history and Slack thread routing. Caches,
@@ -464,10 +472,7 @@ function mergeHermesStateEntries(
464
472
  // runtime root, so it is disposable legacy state rather than profile
465
473
  // content.
466
474
  const relativePath = relativeRoot ? `${relativeRoot}/${name}` : name;
467
- if (
468
- (!relativeRoot && TRANSIENT_PROFILE_ROOTS.has(name)) ||
469
- TRANSIENT_PROFILE_PATHS.has(relativePath)
470
- ) {
475
+ if (isHermesTransientProfilePath(relativePath)) {
471
476
  continue;
472
477
  }
473
478
  const from = join(source, 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.757";
41
+ const INSTALLER_PACKAGE = "@sellable/install@0.1.758";
42
42
  const MCP_PACKAGE = "@sellable/mcp@0.1.938";
43
43
  const HERMES_VERSION = "0.18.0";
44
44
  const SHA256 = /^[a-f0-9]{64}$/;
@@ -1546,7 +1546,7 @@ export function compileClaimToProfileDesired(activeClaim, config) {
1546
1546
  ]) ||
1547
1547
  pinned.hermesCli !== "hermes" ||
1548
1548
  pinned.hermesVersion !== "0.18.0" ||
1549
- pinned.installerPackage !== "@sellable/install@0.1.757" ||
1549
+ pinned.installerPackage !== "@sellable/install@0.1.758" ||
1550
1550
  pinned.mcpPackage !== "@sellable/mcp@0.1.938" ||
1551
1551
  !Array.isArray(policy.toolInclude) ||
1552
1552
  policy.toolInclude.length === 0 ||
@@ -42,6 +42,7 @@ import {
42
42
  HERMES_SNAPSHOT_HOOKS,
43
43
  HERMES_SNAPSHOT_HOOK_ALLOWLIST_BYTES,
44
44
  applyHermesSellableHostedPolicy,
45
+ isHermesTransientProfilePath,
45
46
  linkHermesState,
46
47
  mergeHermesState,
47
48
  } from "./hermes-memory-snapshot.mjs";
@@ -311,7 +312,7 @@ function validateDesired(desired) {
311
312
  desired.serviceCredentialGeneration < 1 ||
312
313
  desired.hermesCli !== "hermes" ||
313
314
  desired.hermesVersion !== "0.18.0" ||
314
- desired.installerPackage !== "@sellable/install@0.1.757" ||
315
+ desired.installerPackage !== "@sellable/install@0.1.758" ||
315
316
  desired.mcpPackage !== "@sellable/mcp@0.1.938" ||
316
317
  !Array.isArray(desired.toolInclude) ||
317
318
  desired.toolInclude.length === 0 ||
@@ -897,16 +898,21 @@ function renderStagedProfile(stageRoot, desired) {
897
898
  return manifest;
898
899
  }
899
900
 
900
- function inventory(root) {
901
+ function inventory(root, { skipTransient = false } = {}) {
901
902
  const files = [];
902
903
  const walk = (pathValue, relativePath) => {
903
904
  const link = lstatSync(pathValue);
904
905
  if (link.isSymbolicLink()) throw new Error("profile symlink rejected");
905
906
  if (link.isDirectory()) {
906
907
  for (const name of readdirSync(pathValue).sort()) {
908
+ const nextRelative = relativePath
909
+ ? `${relativePath}/${name}`
910
+ : name;
911
+ if (skipTransient && isHermesTransientProfilePath(nextRelative))
912
+ continue;
907
913
  walk(
908
914
  join(pathValue, name),
909
- relativePath ? `${relativePath}/${name}` : name
915
+ nextRelative
910
916
  );
911
917
  }
912
918
  return;
@@ -2784,7 +2790,12 @@ export function validateNativeSlackCustomerProfile({ desired, profileRoot }) {
2784
2790
  ) {
2785
2791
  return { ok: false, code: "native_slack_profile_path_invalid" };
2786
2792
  }
2787
- const found = inventory(profileRoot);
2793
+ // Runtime caches and live gateway coordination files are disposable and
2794
+ // can contain large dependency trees, sockets, or symlinks. They are
2795
+ // already excluded from profile replacement and snapshots; traversing
2796
+ // them here only blocks the lifecycle heartbeat before replacement even
2797
+ // starts. Keep the closed inventory walk for every durable path.
2798
+ const found = inventory(profileRoot, { skipTransient: true });
2788
2799
  const serverOwned = [...NATIVE_SLACK_CUSTOMER_PROFILE_INVENTORY].sort();
2789
2800
  if (serverOwned.some((logicalPath) => !found.includes(logicalPath))) {
2790
2801
  return { ok: false, code: "native_slack_profile_inventory_open" };
@@ -25,7 +25,7 @@ import { fileURLToPath } from "node:url";
25
25
  import { deriveContainedProfileId } from "./profile-materializer.mjs";
26
26
 
27
27
  export const PROVISIONING_ACTION = "PROVISION_HERMES_PROFILE";
28
- export const PINNED_INSTALL_PACKAGE = "@sellable/install@0.1.757";
28
+ export const PINNED_INSTALL_PACKAGE = "@sellable/install@0.1.758";
29
29
  export const PINNED_MCP_PACKAGE = "@sellable/mcp@0.1.938";
30
30
  const PINNED_INSTALL_VERSION = PINNED_INSTALL_PACKAGE.slice(
31
31
  PINNED_INSTALL_PACKAGE.lastIndexOf("@") + 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/install",
3
- "version": "0.1.757",
3
+ "version": "0.1.758",
4
4
  "type": "module",
5
5
  "description": "One-command installer for Sellable MCP in Claude Code, Codex, and Hermes",
6
6
  "bin": {