@sellable/install 0.1.578-wip.phase170.20260809.2 → 0.1.578
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 +2 -2
- package/lib/sellable-agent/fly-admin-image/Dockerfile +0 -13
- package/lib/sellable-agent/fly-admin-image/admin-runtime.mjs +1 -82
- package/lib/sellable-agent/fly-customer-image/Dockerfile +2 -11
- package/lib/sellable-agent/fly-customer-image/customer-runtime.mjs +1 -1
- package/lib/sellable-agent/hermes-bridge.mjs +0 -123
- package/lib/sellable-agent/host-bootstrap.mjs +1 -1
- package/lib/sellable-agent/host-worker.mjs +5 -12
- package/lib/sellable-agent/profile-materializer.mjs +14 -169
- package/lib/sellable-agent/provisioning-adapter.mjs +4 -4
- package/package.json +1 -1
- package/skill-templates/refill-sends.md +8 -0
- package/lib/sellable-agent/fly-skills-bridge-exec.mjs +0 -45
- package/lib/sellable-agent/fly-skills-bridge.mjs +0 -955
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.577
|
|
7
7
|
ARG MCP_PACKAGE=@sellable/mcp@0.1.858
|
|
8
8
|
ARG INSTALLER_INTEGRITY
|
|
9
9
|
ARG MCP_INTEGRITY=sha512-8yiUhwMbBk/KxZAXGXTsEHiN8XeB/qCqNgfApew0rhViJqiLlDN8oS67pZW5iB5gdmeuv4du0jx9Lhq/blr9hQ==
|
|
10
10
|
|
|
11
|
-
RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.
|
|
11
|
+
RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.577" \
|
|
12
12
|
&& test "${MCP_PACKAGE}" = "@sellable/mcp@0.1.858" \
|
|
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.578-wip.phase170.202608
|
|
|
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.577' || mcp.name !== '@sellable/mcp' || mcp.version !== '0.1.858') 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.577', installerIntegrity: process.argv[1], mcpPackage: '@sellable/mcp@0.1.858', 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,13 +3,13 @@
|
|
|
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.577` is
|
|
7
7
|
published:
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
10
|
docker build --platform linux/amd64 \
|
|
11
11
|
--build-arg INSTALLER_INTEGRITY='sha512-…' \
|
|
12
|
-
--tag sellable-agent-host:0.1.
|
|
12
|
+
--tag sellable-agent-host:0.1.577 .
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Create a private `bootstrap/` directory owned by root with mode `0700`. It must contain `bootstrap.json`, `provider-auth`, and `slack-app`, each owned by root with mode `0600`. `bootstrap.json` contains only non-secret identities, hashes, package integrities, and the control-plane URL. The other two files contain the provider JSON and global Slack app token whose hashes are pinned by `bootstrap.json`.
|
|
@@ -86,8 +86,6 @@ COPY hermes-bridge.mjs /usr/local/lib/sellable-agent/hermes-bridge.mjs
|
|
|
86
86
|
COPY hermes-memory-snapshot.mjs /usr/local/lib/sellable-agent/hermes-memory-snapshot.mjs
|
|
87
87
|
COPY fly-soul-bridge.mjs /usr/local/lib/sellable-agent/fly-soul-bridge.mjs
|
|
88
88
|
COPY fly-soul-bridge-exec.mjs /usr/local/lib/sellable-agent/fly-soul-bridge-exec.mjs
|
|
89
|
-
COPY fly-skills-bridge.mjs /usr/local/lib/sellable-agent/fly-skills-bridge.mjs
|
|
90
|
-
COPY fly-skills-bridge-exec.mjs /usr/local/lib/sellable-agent/fly-skills-bridge-exec.mjs
|
|
91
89
|
COPY soul-artifact-validator.mjs /usr/local/lib/sellable-agent/soul-artifact-validator.mjs
|
|
92
90
|
COPY hermes-memory-dirty.mjs /opt/sellable/bin/hermes-memory-dirty
|
|
93
91
|
COPY hermes-memory-reconcile.sh /opt/sellable/share/hermes-memory-reconcile.sh
|
|
@@ -109,18 +107,9 @@ RUN node --input-type=module -e \
|
|
|
109
107
|
'import("file:///usr/local/lib/sellable-agent/fly-soul-bridge-exec.mjs").then(({ runFlySoulBridgeExecCli }) => runFlySoulBridgeExecCli());' \
|
|
110
108
|
> /usr/local/bin/sellable-soul-bridge-exec \
|
|
111
109
|
&& chmod 0555 /usr/local/bin/sellable-soul-bridge-exec \
|
|
112
|
-
&& printf '%s\n' \
|
|
113
|
-
'#!/usr/bin/env node' \
|
|
114
|
-
'import("file:///usr/local/lib/sellable-agent/fly-skills-bridge-exec.mjs").then(({ runFlySkillsBridgeExecCli }) => runFlySkillsBridgeExecCli());' \
|
|
115
|
-
> /usr/local/bin/sellable-skills-bridge-exec \
|
|
116
|
-
&& chmod 0555 /usr/local/bin/sellable-skills-bridge-exec \
|
|
117
110
|
&& sha256sum /usr/local/lib/sellable-agent/fly-soul-bridge.mjs \
|
|
118
111
|
> /usr/local/share/sellable-agent/soul-bridge-source.sha256 \
|
|
119
|
-
&& sha256sum /usr/local/lib/sellable-agent/fly-skills-bridge.mjs \
|
|
120
|
-
/usr/local/lib/sellable-agent/fly-skills-bridge-exec.mjs \
|
|
121
|
-
> /usr/local/share/sellable-agent/skills-bridge-source.sha256 \
|
|
122
112
|
&& chmod 0444 /usr/local/share/sellable-agent/soul-bridge-source.sha256 \
|
|
123
|
-
/usr/local/share/sellable-agent/skills-bridge-source.sha256 \
|
|
124
113
|
&& chmod 0755 /etc \
|
|
125
114
|
&& chmod 0555 \
|
|
126
115
|
/usr/local/lib/sellable-agent/admin-runtime/admin-runtime.mjs \
|
|
@@ -133,8 +122,6 @@ RUN node --input-type=module -e \
|
|
|
133
122
|
/usr/local/lib/sellable-agent/hermes-memory-snapshot.mjs \
|
|
134
123
|
/usr/local/lib/sellable-agent/fly-soul-bridge.mjs \
|
|
135
124
|
/usr/local/lib/sellable-agent/fly-soul-bridge-exec.mjs \
|
|
136
|
-
/usr/local/lib/sellable-agent/fly-skills-bridge.mjs \
|
|
137
|
-
/usr/local/lib/sellable-agent/fly-skills-bridge-exec.mjs \
|
|
138
125
|
/usr/local/lib/sellable-agent/soul-artifact-validator.mjs \
|
|
139
126
|
/opt/sellable/bin/hermes-memory-dirty \
|
|
140
127
|
/opt/sellable/bin/hermes-endpoint-cron \
|
|
@@ -622,78 +622,6 @@ function installAdminModelConfig(profileRoot, modelConfig) {
|
|
|
622
622
|
}
|
|
623
623
|
}
|
|
624
624
|
|
|
625
|
-
const ADMIN_LIVE_SKILLS_CONFIG_KEYS = Object.freeze([
|
|
626
|
-
"disabled",
|
|
627
|
-
"platform_disabled",
|
|
628
|
-
]);
|
|
629
|
-
|
|
630
|
-
function adminPreservedSkillsIdentity(profileRoot) {
|
|
631
|
-
if (!existsSync(profileRoot)) return null;
|
|
632
|
-
const entries = [];
|
|
633
|
-
const skillsRoot = join(profileRoot, "skills");
|
|
634
|
-
const walk = (directory, relativePath = "") => {
|
|
635
|
-
for (const name of readdirSync(directory).sort()) {
|
|
636
|
-
const nextRelative = relativePath ? `${relativePath}/${name}` : name;
|
|
637
|
-
if (nextRelative === "sellable") continue;
|
|
638
|
-
const path = join(directory, name);
|
|
639
|
-
const stat = lstatSync(path);
|
|
640
|
-
if (stat.isSymbolicLink()) {
|
|
641
|
-
throw new Error("admin_runtime_live_skills_symlink_rejected");
|
|
642
|
-
}
|
|
643
|
-
if (stat.isDirectory()) walk(path, nextRelative);
|
|
644
|
-
else if (stat.isFile()) {
|
|
645
|
-
entries.push({
|
|
646
|
-
path: nextRelative,
|
|
647
|
-
sha256: sha256(readFileSync(path)),
|
|
648
|
-
});
|
|
649
|
-
} else throw new Error("admin_runtime_live_skills_entry_rejected");
|
|
650
|
-
}
|
|
651
|
-
};
|
|
652
|
-
if (existsSync(skillsRoot)) walk(skillsRoot);
|
|
653
|
-
const configPath = join(profileRoot, "config.yaml");
|
|
654
|
-
let disabled = {};
|
|
655
|
-
if (existsSync(configPath)) {
|
|
656
|
-
const document = parseDocument(readFileSync(configPath, "utf8"));
|
|
657
|
-
if (document.errors.length > 0) {
|
|
658
|
-
throw new Error("admin_runtime_live_skills_config_rejected");
|
|
659
|
-
}
|
|
660
|
-
const skills = document.toJS()?.skills;
|
|
661
|
-
if (skills && typeof skills === "object" && !Array.isArray(skills)) {
|
|
662
|
-
disabled = Object.fromEntries(
|
|
663
|
-
ADMIN_LIVE_SKILLS_CONFIG_KEYS.filter((key) =>
|
|
664
|
-
Object.prototype.hasOwnProperty.call(skills, key)
|
|
665
|
-
).map((key) => [key, skills[key]])
|
|
666
|
-
);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
return sha256(canonicalJson({ disabled, entries }));
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
function mergeAdminLiveSkillsConfig(sourceRoot, targetRoot) {
|
|
673
|
-
const sourcePath = join(sourceRoot, "config.yaml");
|
|
674
|
-
const targetPath = join(targetRoot, "config.yaml");
|
|
675
|
-
if (!existsSync(sourcePath) || !existsSync(targetPath)) return;
|
|
676
|
-
const sourceDocument = parseDocument(readFileSync(sourcePath, "utf8"));
|
|
677
|
-
const targetDocument = parseDocument(readFileSync(targetPath, "utf8"));
|
|
678
|
-
if (sourceDocument.errors.length > 0 || targetDocument.errors.length > 0) {
|
|
679
|
-
throw new Error("admin_runtime_live_skills_config_rejected");
|
|
680
|
-
}
|
|
681
|
-
const sourceSkills = sourceDocument.toJS()?.skills;
|
|
682
|
-
if (
|
|
683
|
-
!sourceSkills ||
|
|
684
|
-
typeof sourceSkills !== "object" ||
|
|
685
|
-
Array.isArray(sourceSkills)
|
|
686
|
-
) {
|
|
687
|
-
return;
|
|
688
|
-
}
|
|
689
|
-
for (const key of ADMIN_LIVE_SKILLS_CONFIG_KEYS) {
|
|
690
|
-
if (Object.prototype.hasOwnProperty.call(sourceSkills, key)) {
|
|
691
|
-
targetDocument.setIn(["skills", key], structuredClone(sourceSkills[key]));
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
atomicPrivateFile(targetPath, targetDocument.toString());
|
|
695
|
-
}
|
|
696
|
-
|
|
697
625
|
async function materializeAdminProfile({
|
|
698
626
|
profileContract,
|
|
699
627
|
settingsRoot,
|
|
@@ -799,6 +727,7 @@ async function materializeAdminProfile({
|
|
|
799
727
|
},
|
|
800
728
|
});
|
|
801
729
|
installAdminModelConfig(stageRoot, modelConfig);
|
|
730
|
+
mergeHermesState(profileHome, stageRoot);
|
|
802
731
|
installAdminHermesMemoryHook(stageRoot);
|
|
803
732
|
stageAdminRuntimeTree(stageRoot);
|
|
804
733
|
return stage;
|
|
@@ -822,16 +751,6 @@ async function materializeAdminProfile({
|
|
|
822
751
|
rmSync(stageRoot, { recursive: true, force: true });
|
|
823
752
|
return { status: "RESTAGE", stagedAuthority: finalAuthority };
|
|
824
753
|
}
|
|
825
|
-
const liveSkillsIdentity = adminPreservedSkillsIdentity(profileHome);
|
|
826
|
-
mergeHermesState(profileHome, stageRoot);
|
|
827
|
-
mergeAdminLiveSkillsConfig(profileHome, stageRoot);
|
|
828
|
-
if (
|
|
829
|
-
liveSkillsIdentity !== null &&
|
|
830
|
-
adminPreservedSkillsIdentity(stageRoot) !== liveSkillsIdentity
|
|
831
|
-
) {
|
|
832
|
-
rmSync(stageRoot, { recursive: true, force: true });
|
|
833
|
-
return { status: "RESTAGE", stagedAuthority: finalAuthority };
|
|
834
|
-
}
|
|
835
754
|
const stagedSoulPath = join(stageRoot, "SOUL.md");
|
|
836
755
|
const stagedSoul = lstatSync(stagedSoulPath);
|
|
837
756
|
const stagedSoulBytes = readFileSync(stagedSoulPath);
|
|
@@ -6,7 +6,7 @@ USER root
|
|
|
6
6
|
|
|
7
7
|
ARG MCP_PACKAGE=@sellable/mcp@0.1.858
|
|
8
8
|
ARG MCP_INTEGRITY=sha512-8yiUhwMbBk/KxZAXGXTsEHiN8XeB/qCqNgfApew0rhViJqiLlDN8oS67pZW5iB5gdmeuv4du0jx9Lhq/blr9hQ==
|
|
9
|
-
ARG INSTALLER_PACKAGE=@sellable/install@0.1.
|
|
9
|
+
ARG INSTALLER_PACKAGE=@sellable/install@0.1.577
|
|
10
10
|
ARG TUS_JS_CLIENT_VERSION=4.3.1
|
|
11
11
|
ARG HERMES_VERSION=0.20.0
|
|
12
12
|
ARG TIRITH_VERSION=0.3.3
|
|
@@ -59,7 +59,7 @@ RUN --mount=type=secret,id=mcp_trust_root,required=true \
|
|
|
59
59
|
/etc/cont-init.d/02-reconcile-profiles \
|
|
60
60
|
&& npm cache clean --force
|
|
61
61
|
|
|
62
|
-
COPY mcp-context-proxy.mjs mcp-runtime-binding.mjs fly-customer-model.mjs fly-customer-worker.mjs profile-materializer.mjs hermes-bridge.mjs hermes-memory-snapshot.mjs fly-runtime-identity.mjs fly-soul-bridge.mjs fly-soul-bridge-exec.mjs
|
|
62
|
+
COPY mcp-context-proxy.mjs mcp-runtime-binding.mjs fly-customer-model.mjs fly-customer-worker.mjs profile-materializer.mjs hermes-bridge.mjs hermes-memory-snapshot.mjs fly-runtime-identity.mjs fly-soul-bridge.mjs fly-soul-bridge-exec.mjs soul-artifact-validator.mjs model-auth-reconciler.mjs model-auth-canary-reseed.mjs model-health-reporter.mjs \
|
|
63
63
|
/usr/local/lib/sellable-agent/
|
|
64
64
|
COPY hermes-memory-dirty.mjs /opt/sellable/bin/hermes-memory-dirty
|
|
65
65
|
COPY hermes-memory-reconcile.sh /opt/sellable/share/hermes-memory-reconcile.sh
|
|
@@ -86,18 +86,9 @@ RUN node --input-type=module -e \
|
|
|
86
86
|
'import("file:///usr/local/lib/sellable-agent/fly-soul-bridge-exec.mjs").then(({ runFlySoulBridgeExecCli }) => runFlySoulBridgeExecCli());' \
|
|
87
87
|
> /usr/local/bin/sellable-soul-bridge-exec \
|
|
88
88
|
&& chmod 0555 /usr/local/bin/sellable-soul-bridge-exec \
|
|
89
|
-
&& printf '%s\n' \
|
|
90
|
-
'#!/usr/bin/env node' \
|
|
91
|
-
'import("file:///usr/local/lib/sellable-agent/fly-skills-bridge-exec.mjs").then(({ runFlySkillsBridgeExecCli }) => runFlySkillsBridgeExecCli());' \
|
|
92
|
-
> /usr/local/bin/sellable-skills-bridge-exec \
|
|
93
|
-
&& chmod 0555 /usr/local/bin/sellable-skills-bridge-exec \
|
|
94
89
|
&& sha256sum /usr/local/lib/sellable-agent/fly-soul-bridge.mjs \
|
|
95
90
|
> /usr/local/share/sellable-agent/soul-bridge-source.sha256 \
|
|
96
|
-
&& sha256sum /usr/local/lib/sellable-agent/fly-skills-bridge.mjs \
|
|
97
|
-
/usr/local/lib/sellable-agent/fly-skills-bridge-exec.mjs \
|
|
98
|
-
> /usr/local/share/sellable-agent/skills-bridge-source.sha256 \
|
|
99
91
|
&& chmod 0444 /usr/local/share/sellable-agent/soul-bridge-source.sha256 \
|
|
100
|
-
/usr/local/share/sellable-agent/skills-bridge-source.sha256 \
|
|
101
92
|
&& chmod 0755 /etc \
|
|
102
93
|
&& chmod 0555 /usr/local/lib/sellable-agent/*.mjs \
|
|
103
94
|
&& chmod 0555 /opt/sellable/bin/hermes-memory-dirty /opt/sellable/bin/hermes-endpoint-cron \
|
|
@@ -94,7 +94,7 @@ const BOOT_SESSION_ID = randomUUID();
|
|
|
94
94
|
const HERMES_VERSION = process.env.SELLABLE_AGENT_HERMES_VERSION ?? "0.20.0";
|
|
95
95
|
const INSTALLER_PACKAGE =
|
|
96
96
|
process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ??
|
|
97
|
-
"@sellable/install@0.1.
|
|
97
|
+
"@sellable/install@0.1.577";
|
|
98
98
|
const MCP_PACKAGE =
|
|
99
99
|
process.env.SELLABLE_AGENT_MCP_PACKAGE ??
|
|
100
100
|
"@sellable/mcp@0.1.858";
|
|
@@ -1584,113 +1584,6 @@ export function patchHermesSourceFile(patchKind, source) {
|
|
|
1584
1584
|
return patched;
|
|
1585
1585
|
}
|
|
1586
1586
|
|
|
1587
|
-
if (patchKind === "skills-cache-freshness-v020") {
|
|
1588
|
-
let patched = replaceExactlyOnce(
|
|
1589
|
-
source,
|
|
1590
|
-
" sig.append((str(d), m))",
|
|
1591
|
-
[
|
|
1592
|
-
" skill_files = []",
|
|
1593
|
-
" for root, dirs, files in os.walk(d, followlinks=False):",
|
|
1594
|
-
" dirs[:] = sorted(",
|
|
1595
|
-
" name for name in dirs",
|
|
1596
|
-
" if not os.path.islink(os.path.join(root, name))",
|
|
1597
|
-
" )",
|
|
1598
|
-
' if "SKILL.md" not in files:',
|
|
1599
|
-
" continue",
|
|
1600
|
-
' skill_path = os.path.join(root, "SKILL.md")',
|
|
1601
|
-
" try:",
|
|
1602
|
-
" skill_stat = os.stat(skill_path, follow_symlinks=False)",
|
|
1603
|
-
" skill_files.append(",
|
|
1604
|
-
" (skill_path, skill_stat.st_mtime_ns, skill_stat.st_size)",
|
|
1605
|
-
" )",
|
|
1606
|
-
" except OSError:",
|
|
1607
|
-
" continue",
|
|
1608
|
-
" sig.append((str(d), m, tuple(skill_files)))",
|
|
1609
|
-
].join("\n"),
|
|
1610
|
-
"v0.20 live SKILL.md signature"
|
|
1611
|
-
);
|
|
1612
|
-
patched = replaceExactlyOnce(
|
|
1613
|
-
patched,
|
|
1614
|
-
" disabled = set() if skip_disabled else _get_disabled_skill_names()",
|
|
1615
|
-
[
|
|
1616
|
-
" disabled = _get_disabled_skill_names()",
|
|
1617
|
-
" filtered_disabled = set() if skip_disabled else disabled",
|
|
1618
|
-
].join("\n"),
|
|
1619
|
-
"v0.20 shared disabled signature"
|
|
1620
|
-
);
|
|
1621
|
-
patched = replaceExactlyOnce(
|
|
1622
|
-
patched,
|
|
1623
|
-
" if name in disabled:\n continue",
|
|
1624
|
-
" if name in filtered_disabled:\n continue",
|
|
1625
|
-
"v0.20 filtered disabled behavior"
|
|
1626
|
-
);
|
|
1627
|
-
patched = replaceExactlyOnce(
|
|
1628
|
-
patched,
|
|
1629
|
-
" skills = []\n seen_names: set = set()",
|
|
1630
|
-
[
|
|
1631
|
-
" # A signature change invalidates both filtered and unfiltered",
|
|
1632
|
-
" # variants together; neither waits for the 30-second TTL.",
|
|
1633
|
-
" if cached is not None and cached[0] != signature:",
|
|
1634
|
-
" _SKILLS_CACHE.clear()",
|
|
1635
|
-
"",
|
|
1636
|
-
" skills = []",
|
|
1637
|
-
" seen_names: set = set()",
|
|
1638
|
-
].join("\n"),
|
|
1639
|
-
"v0.20 both-variant cache invalidation"
|
|
1640
|
-
);
|
|
1641
|
-
return patched;
|
|
1642
|
-
}
|
|
1643
|
-
|
|
1644
|
-
if (patchKind === "skills-prompt-freshness-v020") {
|
|
1645
|
-
let patched = replaceExactlyOnce(
|
|
1646
|
-
source,
|
|
1647
|
-
"_SKILLS_PROMPT_CACHE_LOCK = threading.Lock()",
|
|
1648
|
-
[
|
|
1649
|
-
"_SKILLS_PROMPT_CACHE_LOCK = threading.Lock()",
|
|
1650
|
-
"_SELLABLE_AGENT_SKILLS_PROMPT_SIGNATURE = None",
|
|
1651
|
-
].join("\n"),
|
|
1652
|
-
"v0.20 prompt signature state"
|
|
1653
|
-
);
|
|
1654
|
-
patched = replaceExactlyOnce(
|
|
1655
|
-
patched,
|
|
1656
|
-
" disabled = get_disabled_skill_names(_platform_hint or None)\n cache_key = (",
|
|
1657
|
-
[
|
|
1658
|
-
" disabled = get_disabled_skill_names(_platform_hint or None)",
|
|
1659
|
-
" signature_roots = [skills_dir, *external_dirs]",
|
|
1660
|
-
" live_signature = tuple(",
|
|
1661
|
-
" (",
|
|
1662
|
-
" str(root),",
|
|
1663
|
-
" tuple(",
|
|
1664
|
-
" (path, tuple(values))",
|
|
1665
|
-
" for path, values in sorted(_build_skills_manifest(root).items())",
|
|
1666
|
-
" ),",
|
|
1667
|
-
" )",
|
|
1668
|
-
" for root in signature_roots",
|
|
1669
|
-
" if root.exists()",
|
|
1670
|
-
" )",
|
|
1671
|
-
" cache_key = (",
|
|
1672
|
-
].join("\n"),
|
|
1673
|
-
"v0.20 prompt live signature"
|
|
1674
|
-
);
|
|
1675
|
-
patched = replaceExactlyOnce(
|
|
1676
|
-
patched,
|
|
1677
|
-
" tuple(sorted(compact_categories or ())),\n )\n with _SKILLS_PROMPT_CACHE_LOCK:\n cached = _SKILLS_PROMPT_CACHE.get(cache_key)",
|
|
1678
|
-
[
|
|
1679
|
-
" tuple(sorted(compact_categories or ())),",
|
|
1680
|
-
" live_signature,",
|
|
1681
|
-
" )",
|
|
1682
|
-
" global _SELLABLE_AGENT_SKILLS_PROMPT_SIGNATURE",
|
|
1683
|
-
" with _SKILLS_PROMPT_CACHE_LOCK:",
|
|
1684
|
-
" if _SELLABLE_AGENT_SKILLS_PROMPT_SIGNATURE != live_signature:",
|
|
1685
|
-
" _SKILLS_PROMPT_CACHE.clear()",
|
|
1686
|
-
" _SELLABLE_AGENT_SKILLS_PROMPT_SIGNATURE = live_signature",
|
|
1687
|
-
" cached = _SKILLS_PROMPT_CACHE.get(cache_key)",
|
|
1688
|
-
].join("\n"),
|
|
1689
|
-
"v0.20 prompt cache invalidation"
|
|
1690
|
-
);
|
|
1691
|
-
return patched;
|
|
1692
|
-
}
|
|
1693
|
-
|
|
1694
1587
|
throw new HermesAgentBridgeError(
|
|
1695
1588
|
"HERMES_BRIDGE_UNKNOWN_PATCH_KIND",
|
|
1696
1589
|
`Unknown Hermes bridge patch kind: ${patchKind}`,
|
|
@@ -1949,22 +1842,6 @@ export const HERMES_AGENT_BRIDGE_DEDICATED_V020_CONTRACT = normalizeContract({
|
|
|
1949
1842
|
patchedSha256:
|
|
1950
1843
|
"90c98514a8c6c4078dacdd67a92cf749bd174ec2c074226163c6cb07ca3df59f",
|
|
1951
1844
|
},
|
|
1952
|
-
{
|
|
1953
|
-
path: "tools/skills_tool.py",
|
|
1954
|
-
patchKind: "skills-cache-freshness-v020",
|
|
1955
|
-
sourceSha256:
|
|
1956
|
-
"6cfe456c8872c91309083694290e5e2cbdb64a1b2f4ac9c2cb38973fab2228ab",
|
|
1957
|
-
patchedSha256:
|
|
1958
|
-
"9a1b1417879d9aac6d5b6e1713237193009e2d67dbc691db35ef5940e94f9397",
|
|
1959
|
-
},
|
|
1960
|
-
{
|
|
1961
|
-
path: "agent/prompt_builder.py",
|
|
1962
|
-
patchKind: "skills-prompt-freshness-v020",
|
|
1963
|
-
sourceSha256:
|
|
1964
|
-
"2a8a8b2b6c0ff830349f68b5c2f26bf2c9871ae03caf516cff3628c00b5769c7",
|
|
1965
|
-
patchedSha256:
|
|
1966
|
-
"4a55eb6dd4e79d35fca9fd02544444576c892ca02dfebb0c97954156cc470fdb",
|
|
1967
|
-
},
|
|
1968
1845
|
],
|
|
1969
1846
|
});
|
|
1970
1847
|
|
|
@@ -39,7 +39,7 @@ 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
41
|
const INSTALLER_PACKAGE =
|
|
42
|
-
"@sellable/install@0.1.
|
|
42
|
+
"@sellable/install@0.1.577";
|
|
43
43
|
const MCP_PACKAGE = "@sellable/mcp@0.1.858";
|
|
44
44
|
const HERMES_VERSION = "0.18.0";
|
|
45
45
|
const SHA256 = /^[a-f0-9]{64}$/;
|
|
@@ -29,7 +29,6 @@ import {
|
|
|
29
29
|
relative,
|
|
30
30
|
resolve,
|
|
31
31
|
} from "node:path";
|
|
32
|
-
import { readSkillsProofObservation } from "./fly-skills-bridge.mjs";
|
|
33
32
|
import {
|
|
34
33
|
commitRetainedProfilePromotion,
|
|
35
34
|
computeAgentProfileDigest,
|
|
@@ -78,11 +77,6 @@ const SECRET_PATTERN =
|
|
|
78
77
|
/sat_[A-Za-z0-9_-]+|xox[bap]-[A-Za-z0-9-]+|asec\.v1\.|authorization[_-]?code|access[_-]?token|refresh[_-]?token/i;
|
|
79
78
|
const STATE_FILE = "worker-state.json";
|
|
80
79
|
|
|
81
|
-
export function attachSkillsProofObservation(observed, profileRoot) {
|
|
82
|
-
const skills = readSkillsProofObservation(profileRoot);
|
|
83
|
-
return skills ? { ...observed, skills } : observed;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
80
|
function stableJson(value) {
|
|
87
81
|
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
|
88
82
|
if (value && typeof value === "object") {
|
|
@@ -1546,8 +1540,10 @@ export function compileClaimToProfileDesired(activeClaim, config) {
|
|
|
1546
1540
|
]) ||
|
|
1547
1541
|
pinned.hermesCli !== "hermes" ||
|
|
1548
1542
|
pinned.hermesVersion !== "0.18.0" ||
|
|
1549
|
-
pinned.installerPackage !==
|
|
1550
|
-
|
|
1543
|
+
pinned.installerPackage !==
|
|
1544
|
+
"@sellable/install@0.1.577" ||
|
|
1545
|
+
pinned.mcpPackage !==
|
|
1546
|
+
"@sellable/mcp@0.1.858" ||
|
|
1551
1547
|
!Array.isArray(policy.toolInclude) ||
|
|
1552
1548
|
policy.toolInclude.length === 0 ||
|
|
1553
1549
|
!Number.isSafeInteger(slack.generation) ||
|
|
@@ -2352,10 +2348,7 @@ export function createLocalPinnedActionPorts(config, dependencies = {}) {
|
|
|
2352
2348
|
observed.process.uid !== config.runtimeUid
|
|
2353
2349
|
)
|
|
2354
2350
|
throw new Error("runtime observation identity rejected");
|
|
2355
|
-
return
|
|
2356
|
-
observed,
|
|
2357
|
-
join(realpathSync(config.profilesRoot), context.profileId)
|
|
2358
|
-
);
|
|
2351
|
+
return observed;
|
|
2359
2352
|
};
|
|
2360
2353
|
const ensureRefreshTarget = async () => {
|
|
2361
2354
|
if (refreshPrepared) return;
|