@sellable/install 0.1.751 → 0.1.753

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.751
6
+ ARG INSTALLER_PACKAGE=@sellable/install@0.1.753
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.751" \
11
+ RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.753" \
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.751" \
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.751' || 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.753' || 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.751', 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.753', 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.751` is
6
+ `@sellable/install@0.1.753` is
7
7
  published:
8
8
 
9
9
  ```sh
@@ -30,6 +30,21 @@ const MAX_FILE_BYTES = 64 * 1024;
30
30
  const MAX_FRAGMENT_BYTES = 192 * 1024;
31
31
  const MAX_TOTAL_BYTES = 1024 * 1024;
32
32
 
33
+ function readNativeSkillName(content) {
34
+ const lines = content.split("\n");
35
+ if (lines[0] !== "---") reject("skill_frontmatter_rejected");
36
+ const end = lines.indexOf("---", 1);
37
+ if (end < 2) reject("skill_frontmatter_rejected");
38
+ const names = lines
39
+ .slice(1, end)
40
+ .map((line) => /^name:\s*([a-z0-9][a-z0-9-]{0,63})\s*$/.exec(line)?.[1])
41
+ .filter(Boolean);
42
+ if (names.length !== 1 || !ID.test(names[0])) {
43
+ reject("skill_frontmatter_rejected");
44
+ }
45
+ return names[0];
46
+ }
47
+
33
48
  function sha256(value) {
34
49
  return createHash("sha256").update(value).digest("hex");
35
50
  }
@@ -200,7 +215,9 @@ function normalizeFile(value, fragmentKind) {
200
215
  kind: fragmentKind,
201
216
  path: value.path,
202
217
  mode: value.mode,
203
- ...(value.type === "cron" ? { name: value.name } : {}),
218
+ ...(value.type === "cron"
219
+ ? { name: value.name }
220
+ : { nativeName: readNativeSkillName(value.content) }),
204
221
  content: value.content,
205
222
  sha256: sha256(bytes),
206
223
  });
@@ -282,6 +299,11 @@ export function buildDefaultProfileBundle({
282
299
  new Set(files.map((file) => file.path)).size !== files.length ||
283
300
  new Set(files.filter((file) => file.type === "skill").map((file) => file.id))
284
301
  .size !== files.filter((file) => file.type === "skill").length ||
302
+ new Set(
303
+ files
304
+ .filter((file) => file.type === "skill")
305
+ .map((file) => file.nativeName)
306
+ ).size !== files.filter((file) => file.type === "skill").length ||
285
307
  new Set(files.filter((file) => file.type === "cron").map((file) => file.name))
286
308
  .size !== files.filter((file) => file.type === "cron").length
287
309
  ) {
@@ -359,6 +359,7 @@ function readBundle(bundleRoot) {
359
359
  entry.mode !== "0444" ||
360
360
  entry.path !== expectedPath ||
361
361
  !SHA256.test(entry.sha256 ?? "") ||
362
+ (entry.type === "skill" && !MANAGED_ID.test(entry.nativeName ?? "")) ||
362
363
  (entry.type === "cron" &&
363
364
  (!MANAGED_ID.test(entry.name ?? "") ||
364
365
  !entry.name.startsWith("sellable-default-")))
@@ -588,7 +589,12 @@ export async function reconcileDefaultProfileBundle({
588
589
  if (sha256(readRegular(plan.path, 64 * 1024)) !== entry.sha256)
589
590
  throw new Error("default_profile_skill_readback_rejected");
590
591
  }
591
- actions.push({ type: "skill", id: entry.id, status: plan.status });
592
+ actions.push({
593
+ type: "skill",
594
+ id: entry.id,
595
+ nativeName: entry.nativeName,
596
+ status: plan.status,
597
+ });
592
598
  receiptEntries.push({
593
599
  type: "skill",
594
600
  id: entry.id,
@@ -43,7 +43,7 @@ ARG STRIPE_CLI_PACKAGE=@stripe/cli-linux-x64@1.45.0
43
43
  ARG STRIPE_CLI_INTEGRITY=sha512-1ZhoPpoweYfynqsvhCLlTjZ7lPz5IKtxqAMT5MBy6zrwLRTP9x0T6r8h/jLYL8lRH1c7zC/6X6/XUu2V+r9Bog==
44
44
  ARG DEFAULT_PROFILE_BUNDLE_FIXTURE_VERSION=1
45
45
  ARG DEFAULT_PROFILE_BUNDLE_VERSION=3
46
- ARG DEFAULT_PROFILE_BUNDLE_DIGEST=8030143cc1a10928564511f24d44643bd697d573332324c5d9a7a32d4fdbaf85
46
+ ARG DEFAULT_PROFILE_BUNDLE_DIGEST=197fb4ed5a60cd1a3a06a46aa1fc53a04bb1e6c1f872e96a0ce2cc28bf2856de
47
47
 
48
48
  COPY --from=slack-pp-cli-builder --chmod=0555 /out/slack-pp-cli /usr/local/bin/slack-pp-cli
49
49
 
@@ -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.751
11
+ ARG INSTALLER_PACKAGE=@sellable/install@0.1.753
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
@@ -21,7 +21,7 @@ ARG PLAYWRIGHT_BROWSER_REVISION=1234
21
21
  ARG TIRITH_ARCHIVE_SHA256=6cdbe35e8f9ccf42e70ad95b501c93cd218ac18201c3df958d54f6ba0d995ce2
22
22
  ARG DEFAULT_PROFILE_BUNDLE_FIXTURE_VERSION=1
23
23
  ARG DEFAULT_PROFILE_BUNDLE_VERSION=3
24
- ARG DEFAULT_PROFILE_BUNDLE_DIGEST=7e8e6ff740f11aaaa3d6da2e9f067a66866d259ac4233036ff691dae973ce5f3
24
+ ARG DEFAULT_PROFILE_BUNDLE_DIGEST=301ed49582dbfb29453ff2c2fa26579da6771d19f58e12218c5400db2e14318d
25
25
 
26
26
  RUN --mount=type=secret,id=mcp_trust_root,required=true \
27
27
  test -s /run/secrets/mcp_trust_root \
@@ -121,7 +121,7 @@ const RUNTIME_GENERATION = Number(
121
121
  const BOOT_SESSION_ID = randomUUID();
122
122
  const HERMES_VERSION = process.env.SELLABLE_AGENT_HERMES_VERSION ?? "0.21.3";
123
123
  const INSTALLER_PACKAGE =
124
- process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ?? "@sellable/install@0.1.751";
124
+ process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ?? "@sellable/install@0.1.753";
125
125
  const MCP_PACKAGE =
126
126
  process.env.SELLABLE_AGENT_MCP_PACKAGE ?? "@sellable/mcp@0.1.938";
127
127
  export const ENDPOINT_MAX_CONCURRENT_RUNS = 10;
@@ -1041,7 +1041,7 @@ export function executeExternalSkillsBridgeOperation(
1041
1041
 
1042
1042
  /**
1043
1043
  * @param {{
1044
- * actions?: Array<{type: string, id: string}>,
1044
+ * actions?: Array<{type: string, id: string, nativeName?: string}>,
1045
1045
  * profileId?: string,
1046
1046
  * dataRoot?: string,
1047
1047
  * bridge?: typeof executeExternalSkillsBridgeOperation,
@@ -1062,17 +1062,27 @@ export function proveDefaultProfileNativeSkills({
1062
1062
  callerProfileId: profileId,
1063
1063
  ...(nativeCallTimeoutMs === undefined ? {} : { nativeCallTimeoutMs }),
1064
1064
  };
1065
+ for (const action of managed) {
1066
+ if (!SAFE_NAME.test(action.nativeName ?? ""))
1067
+ fail("default_profile_native_skill_name_missing");
1068
+ }
1065
1069
  const inventory = bridge({ operation: "list" }, options);
1066
1070
  const proofs = managed.map((action) => {
1067
- const skill = inventory.skills.find((entry) => entry.name === action.id);
1071
+ const skill = inventory.skills.find(
1072
+ (entry) => entry.name === action.nativeName
1073
+ );
1068
1074
  if (!skill) fail("default_profile_native_skill_missing");
1069
1075
  const viewed = bridge(
1070
1076
  { operation: "read", skillId: skill.skillId },
1071
1077
  options
1072
1078
  );
1073
- if (!viewed.ok || viewed.skill?.name !== action.id)
1079
+ if (!viewed.ok || viewed.skill?.name !== action.nativeName)
1074
1080
  fail("default_profile_native_skill_readback_rejected");
1075
- return { id: action.id, fileSha256: viewed.fileSha256 };
1081
+ return {
1082
+ id: action.id,
1083
+ nativeName: action.nativeName,
1084
+ fileSha256: viewed.fileSha256,
1085
+ };
1076
1086
  });
1077
1087
  return { status: "PROVEN", digest: sha256(stableJson(proofs)) };
1078
1088
  }
@@ -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.751";
41
+ const INSTALLER_PACKAGE = "@sellable/install@0.1.753";
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.751" ||
1549
+ pinned.installerPackage !== "@sellable/install@0.1.753" ||
1550
1550
  pinned.mcpPackage !== "@sellable/mcp@0.1.938" ||
1551
1551
  !Array.isArray(policy.toolInclude) ||
1552
1552
  policy.toolInclude.length === 0 ||
@@ -282,7 +282,7 @@ function validateDesired(desired) {
282
282
  desired.serviceCredentialGeneration < 1 ||
283
283
  desired.hermesCli !== "hermes" ||
284
284
  desired.hermesVersion !== "0.18.0" ||
285
- desired.installerPackage !== "@sellable/install@0.1.751" ||
285
+ desired.installerPackage !== "@sellable/install@0.1.753" ||
286
286
  desired.mcpPackage !== "@sellable/mcp@0.1.938" ||
287
287
  !Array.isArray(desired.toolInclude) ||
288
288
  desired.toolInclude.length === 0 ||
@@ -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.751";
28
+ export const PINNED_INSTALL_PACKAGE = "@sellable/install@0.1.753";
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.751",
3
+ "version": "0.1.753",
4
4
  "type": "module",
5
5
  "description": "One-command installer for Sellable MCP in Claude Code, Codex, and Hermes",
6
6
  "bin": {