@sellable/install 0.1.479 → 0.1.481
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 +2 -2
- package/lib/sellable-agent/fly-admin-image/admin-runtime.mjs +5 -5
- package/lib/sellable-agent/fly-customer-image/Dockerfile +4 -4
- package/lib/sellable-agent/fly-customer-image/customer-runtime.mjs +2 -2
- package/lib/sellable-agent/fly-runtime-identity.mjs +1 -1
- package/lib/sellable-agent/hermes-bridge.mjs +225 -13
- package/lib/sellable-agent/hermes-memory-snapshot.mjs +1 -1
- 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 +2 -2
- package/lib/sellable-agent/provisioning-adapter.mjs +4 -4
- 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.481
|
|
7
7
|
ARG MCP_PACKAGE=@sellable/mcp@0.1.760-wip.phase143.20260727100513
|
|
8
8
|
ARG INSTALLER_INTEGRITY
|
|
9
9
|
ARG MCP_INTEGRITY=sha512-muNXHuRnLTfsnW+MQUvK+p0VBZETDKeevr70iRliXyqE3/SLrZQJLL1laJzMo+qiUs9jMXMHdKOQfQqLiwJvtg==
|
|
10
10
|
|
|
11
|
-
RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.
|
|
11
|
+
RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.481" \
|
|
12
12
|
&& test "${MCP_PACKAGE}" = "@sellable/mcp@0.1.760-wip.phase143.20260727100513" \
|
|
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.479" \
|
|
|
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.481' || mcp.name !== '@sellable/mcp' || mcp.version !== '0.1.760-wip.phase143.20260727100513') 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.481', installerIntegrity: process.argv[1], mcpPackage: '@sellable/mcp@0.1.760-wip.phase143.20260727100513', 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.481` 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.481 .
|
|
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`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
ARG HERMES_IMAGE=nousresearch/hermes-agent@sha256:
|
|
1
|
+
ARG HERMES_IMAGE=nousresearch/hermes-agent@sha256:c0cab4e3711bcb27a312be1b3776254fc06fd50d5f7a6b8017915fc7171cb39e
|
|
2
2
|
FROM ${HERMES_IMAGE}
|
|
3
3
|
|
|
4
4
|
USER root
|
|
@@ -86,7 +86,7 @@ COPY hermes-memory-reconcile.sh /opt/sellable/share/hermes-memory-reconcile.sh
|
|
|
86
86
|
COPY fly-admin-image/rootfs/ /
|
|
87
87
|
|
|
88
88
|
RUN node --input-type=module -e \
|
|
89
|
-
'import { installHermesAgentBridge,
|
|
89
|
+
'import { installHermesAgentBridge, HERMES_AGENT_BRIDGE_DEDICATED_V020_CONTRACT } from "/usr/local/lib/sellable-agent/hermes-bridge.mjs"; installHermesAgentBridge({ sourceRoot: "/opt/hermes", contract: HERMES_AGENT_BRIDGE_DEDICATED_V020_CONTRACT });' \
|
|
90
90
|
&& node --input-type=module -e \
|
|
91
91
|
'await import("/usr/local/lib/sellable-agent/fly-runtime-identity.mjs");' \
|
|
92
92
|
&& chmod 0755 /etc \
|
|
@@ -1796,14 +1796,14 @@ async function flushHermesSnapshot({ client, profileId, profileRoot }) {
|
|
|
1796
1796
|
profileId,
|
|
1797
1797
|
profileRoot,
|
|
1798
1798
|
hermesRoot: DATA_ROOT,
|
|
1799
|
-
hermesVersion: "0.
|
|
1799
|
+
hermesVersion: "0.20.0",
|
|
1800
1800
|
debounceMs: 0,
|
|
1801
1801
|
upload: ({ archiveDigest, archiveBytes, sourceProfileId, bytes }) =>
|
|
1802
1802
|
client.putMemorySnapshot(
|
|
1803
1803
|
{
|
|
1804
1804
|
archiveDigest,
|
|
1805
1805
|
archiveBytes,
|
|
1806
|
-
hermesVersion: "0.
|
|
1806
|
+
hermesVersion: "0.20.0",
|
|
1807
1807
|
sourceProfileId,
|
|
1808
1808
|
},
|
|
1809
1809
|
bytes
|
|
@@ -2426,13 +2426,13 @@ async function runAdminProduction() {
|
|
|
2426
2426
|
profileId: activeLaunch.profile.profile,
|
|
2427
2427
|
profileRoot: activeLaunch.profile.profileHome,
|
|
2428
2428
|
hermesRoot: DATA_ROOT,
|
|
2429
|
-
hermesVersion: "0.
|
|
2429
|
+
hermesVersion: "0.20.0",
|
|
2430
2430
|
upload: ({ archiveDigest, archiveBytes, sourceProfileId, bytes }) =>
|
|
2431
2431
|
client.putMemorySnapshot(
|
|
2432
2432
|
{
|
|
2433
2433
|
archiveDigest,
|
|
2434
2434
|
archiveBytes,
|
|
2435
|
-
hermesVersion: "0.
|
|
2435
|
+
hermesVersion: "0.20.0",
|
|
2436
2436
|
sourceProfileId,
|
|
2437
2437
|
},
|
|
2438
2438
|
bytes
|
|
@@ -2554,7 +2554,7 @@ async function runAdminProduction() {
|
|
|
2554
2554
|
profileId: basename(profileContract.profileHome),
|
|
2555
2555
|
profileRoot: profileContract.profileHome,
|
|
2556
2556
|
hermesRoot: DATA_ROOT,
|
|
2557
|
-
hermesVersion: "0.
|
|
2557
|
+
hermesVersion: "0.20.0",
|
|
2558
2558
|
fetchLatest: () => client.getMemorySnapshot(),
|
|
2559
2559
|
});
|
|
2560
2560
|
if (!memoryRestore.ok) throw new Error(memoryRestore.code);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
ARG HERMES_IMAGE=nousresearch/hermes-agent@sha256:
|
|
1
|
+
ARG HERMES_IMAGE=nousresearch/hermes-agent@sha256:c0cab4e3711bcb27a312be1b3776254fc06fd50d5f7a6b8017915fc7171cb39e
|
|
2
2
|
FROM ${HERMES_IMAGE}
|
|
3
3
|
|
|
4
4
|
USER root
|
|
5
5
|
|
|
6
6
|
ARG MCP_PACKAGE=@sellable/mcp@0.1.804
|
|
7
7
|
ARG MCP_INTEGRITY=sha512-3bhenU9lVPXZuxmiPJYSBSlhEfUJTCPdB6RRL40RDaGYKdWoOiKNUhZLTgzc9F6C4uTMGBhT8T2DFmDKL37O/g==
|
|
8
|
-
ARG INSTALLER_PACKAGE=@sellable/install@0.1.
|
|
8
|
+
ARG INSTALLER_PACKAGE=@sellable/install@0.1.481
|
|
9
9
|
ARG TUS_JS_CLIENT_VERSION=4.3.1
|
|
10
|
-
ARG HERMES_VERSION=0.
|
|
10
|
+
ARG HERMES_VERSION=0.20.0
|
|
11
11
|
ARG MCP_TRUST_ROOT_B64
|
|
12
12
|
ARG TIRITH_VERSION=0.3.3
|
|
13
13
|
ARG PLAYWRIGHT_VERSION=1.61.1
|
|
@@ -63,7 +63,7 @@ COPY fly-customer-image/customer-runtime.mjs /usr/local/lib/sellable-agent/fly-c
|
|
|
63
63
|
COPY fly-customer-image/rootfs/ /
|
|
64
64
|
|
|
65
65
|
RUN node --input-type=module -e \
|
|
66
|
-
'import { installHermesAgentBridge,
|
|
66
|
+
'import { installHermesAgentBridge, HERMES_AGENT_BRIDGE_DEDICATED_V020_CONTRACT } from "/usr/local/lib/sellable-agent/hermes-bridge.mjs"; installHermesAgentBridge({ sourceRoot: "/opt/hermes", contract: HERMES_AGENT_BRIDGE_DEDICATED_V020_CONTRACT });' \
|
|
67
67
|
&& node --input-type=module -e \
|
|
68
68
|
'await import("/usr/local/lib/sellable-agent/fly-runtime-identity.mjs");' \
|
|
69
69
|
&& chmod 0555 /usr/local/lib/sellable-agent/*.mjs \
|
|
@@ -67,9 +67,9 @@ const RUNTIME_GENERATION = Number(
|
|
|
67
67
|
"0"
|
|
68
68
|
);
|
|
69
69
|
const BOOT_SESSION_ID = randomUUID();
|
|
70
|
-
const HERMES_VERSION = process.env.SELLABLE_AGENT_HERMES_VERSION ?? "0.
|
|
70
|
+
const HERMES_VERSION = process.env.SELLABLE_AGENT_HERMES_VERSION ?? "0.20.0";
|
|
71
71
|
const INSTALLER_PACKAGE =
|
|
72
|
-
process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ?? "@sellable/install@0.1.
|
|
72
|
+
process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ?? "@sellable/install@0.1.481";
|
|
73
73
|
const MCP_PACKAGE =
|
|
74
74
|
process.env.SELLABLE_AGENT_MCP_PACKAGE ??
|
|
75
75
|
"@sellable/mcp@0.1.804";
|
|
@@ -810,7 +810,7 @@ export function createFlyCustomerControlClient({
|
|
|
810
810
|
Number.isSafeInteger(value?.archiveBytes) &&
|
|
811
811
|
value.archiveBytes > 0 &&
|
|
812
812
|
value.archiveBytes <= 128 * 1024 * 1024 &&
|
|
813
|
-
value.hermesVersion === "0.
|
|
813
|
+
value.hermesVersion === "0.20.0" &&
|
|
814
814
|
/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/.test(value?.sourceProfileId ?? "");
|
|
815
815
|
const signedUrlAccepted = (value) => {
|
|
816
816
|
try {
|
|
@@ -142,6 +142,155 @@ def _sellable_agent_slack_api_kwargs():
|
|
|
142
142
|
return {"base_url": origin.rstrip("/") + "/api/"}
|
|
143
143
|
`;
|
|
144
144
|
|
|
145
|
+
const SLACK_MESSAGE_UNFURL_FILE_HELPER = `
|
|
146
|
+
# ${HERMES_AGENT_BRIDGE_MARKER}: recover files from bounded allowed-channel Slack message unfurls.
|
|
147
|
+
async def _sellable_agent_recover_slack_message_unfurl_files(
|
|
148
|
+
adapter,
|
|
149
|
+
attachments,
|
|
150
|
+
current_channel_id,
|
|
151
|
+
team_id,
|
|
152
|
+
existing_files=None,
|
|
153
|
+
):
|
|
154
|
+
if os.getenv("SELLABLE_AGENT_RUNTIME", "") != "1":
|
|
155
|
+
return []
|
|
156
|
+
if not current_channel_id or not team_id:
|
|
157
|
+
return []
|
|
158
|
+
|
|
159
|
+
message_unfurls = [
|
|
160
|
+
attachment
|
|
161
|
+
for attachment in list(attachments or [])
|
|
162
|
+
if isinstance(attachment, dict) and attachment.get("is_msg_unfurl") is True
|
|
163
|
+
][:3]
|
|
164
|
+
if not message_unfurls:
|
|
165
|
+
return []
|
|
166
|
+
|
|
167
|
+
client = adapter._team_clients.get(team_id)
|
|
168
|
+
if client is None:
|
|
169
|
+
logger.warning(
|
|
170
|
+
"[Slack] Refusing message-unfurl file recovery: exact workspace client is unavailable"
|
|
171
|
+
)
|
|
172
|
+
return []
|
|
173
|
+
|
|
174
|
+
allowed_channel_ids = {
|
|
175
|
+
channel_id.strip().upper()
|
|
176
|
+
for channel_id in os.getenv("SLACK_ALLOWED_CHANNELS", "").split(",")
|
|
177
|
+
if channel_id.strip()
|
|
178
|
+
}
|
|
179
|
+
if not allowed_channel_ids:
|
|
180
|
+
logger.warning(
|
|
181
|
+
"[Slack] Refusing message-unfurl file recovery: allowed channels are unavailable"
|
|
182
|
+
)
|
|
183
|
+
return []
|
|
184
|
+
|
|
185
|
+
seen_file_ids = {
|
|
186
|
+
str(file_obj.get("id"))
|
|
187
|
+
for file_obj in (existing_files or [])
|
|
188
|
+
if isinstance(file_obj, dict) and file_obj.get("id")
|
|
189
|
+
}
|
|
190
|
+
recovered = []
|
|
191
|
+
for attachment in message_unfurls:
|
|
192
|
+
target_channel_id = str(attachment.get("channel_id") or "")
|
|
193
|
+
target_ts = str(attachment.get("ts") or "")
|
|
194
|
+
if (
|
|
195
|
+
target_channel_id.upper() not in allowed_channel_ids
|
|
196
|
+
or re.fullmatch(r"\\d+\\.\\d{6}", target_ts) is None
|
|
197
|
+
):
|
|
198
|
+
continue
|
|
199
|
+
|
|
200
|
+
thread_ts = str(attachment.get("thread_ts") or "")
|
|
201
|
+
if thread_ts and re.fullmatch(r"\\d+\\.\\d{6}", thread_ts) is None:
|
|
202
|
+
thread_ts = ""
|
|
203
|
+
|
|
204
|
+
permalink = str(
|
|
205
|
+
attachment.get("from_url") or attachment.get("title_link") or ""
|
|
206
|
+
)
|
|
207
|
+
if permalink:
|
|
208
|
+
try:
|
|
209
|
+
from html import unescape
|
|
210
|
+
from urllib.parse import parse_qs, urlsplit
|
|
211
|
+
|
|
212
|
+
parsed = urlsplit(unescape(permalink))
|
|
213
|
+
path_match = re.fullmatch(
|
|
214
|
+
r"/archives/([CGD][A-Z0-9]{8,})/p(\\d{16})",
|
|
215
|
+
parsed.path,
|
|
216
|
+
re.IGNORECASE,
|
|
217
|
+
)
|
|
218
|
+
if (
|
|
219
|
+
parsed.scheme != "https"
|
|
220
|
+
or not parsed.hostname
|
|
221
|
+
or not parsed.hostname.lower().endswith(".slack.com")
|
|
222
|
+
or parsed.username
|
|
223
|
+
or parsed.password
|
|
224
|
+
or parsed.port is not None
|
|
225
|
+
or path_match is None
|
|
226
|
+
or path_match.group(1).upper() != target_channel_id
|
|
227
|
+
):
|
|
228
|
+
continue
|
|
229
|
+
packed_ts = path_match.group(2)
|
|
230
|
+
permalink_ts = f"{packed_ts[:-6]}.{packed_ts[-6:]}"
|
|
231
|
+
if permalink_ts != target_ts:
|
|
232
|
+
continue
|
|
233
|
+
permalink_thread_ts = (parse_qs(parsed.query).get("thread_ts") or [""])[0]
|
|
234
|
+
if re.fullmatch(r"\\d+\\.\\d{6}", permalink_thread_ts or ""):
|
|
235
|
+
thread_ts = permalink_thread_ts
|
|
236
|
+
except (TypeError, ValueError):
|
|
237
|
+
continue
|
|
238
|
+
|
|
239
|
+
if attachment.get("is_reply_unfurl") and not thread_ts:
|
|
240
|
+
logger.warning(
|
|
241
|
+
"[Slack] Refusing reply-unfurl file recovery without an exact thread root"
|
|
242
|
+
)
|
|
243
|
+
continue
|
|
244
|
+
|
|
245
|
+
try:
|
|
246
|
+
if thread_ts and thread_ts != target_ts:
|
|
247
|
+
response = await client.conversations_replies(
|
|
248
|
+
channel=target_channel_id,
|
|
249
|
+
ts=thread_ts,
|
|
250
|
+
oldest=target_ts,
|
|
251
|
+
latest=target_ts,
|
|
252
|
+
inclusive=True,
|
|
253
|
+
limit=1,
|
|
254
|
+
)
|
|
255
|
+
else:
|
|
256
|
+
response = await client.conversations_history(
|
|
257
|
+
channel=target_channel_id,
|
|
258
|
+
oldest=target_ts,
|
|
259
|
+
latest=target_ts,
|
|
260
|
+
inclusive=True,
|
|
261
|
+
limit=1,
|
|
262
|
+
)
|
|
263
|
+
except Exception as exc:
|
|
264
|
+
logger.warning(
|
|
265
|
+
"[Slack] Message-unfurl file recovery failed for %s: %s",
|
|
266
|
+
target_ts,
|
|
267
|
+
type(exc).__name__,
|
|
268
|
+
)
|
|
269
|
+
continue
|
|
270
|
+
|
|
271
|
+
linked_message = next(
|
|
272
|
+
(
|
|
273
|
+
message
|
|
274
|
+
for message in ((response or {}).get("messages") or [])
|
|
275
|
+
if isinstance(message, dict) and str(message.get("ts") or "") == target_ts
|
|
276
|
+
),
|
|
277
|
+
None,
|
|
278
|
+
)
|
|
279
|
+
if linked_message is None:
|
|
280
|
+
continue
|
|
281
|
+
for file_obj in linked_message.get("files") or []:
|
|
282
|
+
if not isinstance(file_obj, dict):
|
|
283
|
+
continue
|
|
284
|
+
file_id = str(file_obj.get("id") or "")
|
|
285
|
+
if re.fullmatch(r"F[A-Z0-9]{8,}", file_id) is None or file_id in seen_file_ids:
|
|
286
|
+
continue
|
|
287
|
+
seen_file_ids.add(file_id)
|
|
288
|
+
recovered.append(file_obj)
|
|
289
|
+
if len(recovered) >= 10:
|
|
290
|
+
return recovered
|
|
291
|
+
return recovered
|
|
292
|
+
`;
|
|
293
|
+
|
|
145
294
|
const MCP_META_HELPER = `
|
|
146
295
|
# ${HERMES_AGENT_BRIDGE_MARKER}: request-scoped Sellable MCP metadata.
|
|
147
296
|
def _sellable_agent_call_meta():
|
|
@@ -556,7 +705,7 @@ export function patchHermesSourceFile(patchKind, source) {
|
|
|
556
705
|
let patched = replaceExactlyOnce(
|
|
557
706
|
source,
|
|
558
707
|
"logger = logging.getLogger(__name__)\n",
|
|
559
|
-
`logger = logging.getLogger(__name__)\n${SECRET_FD_HELPER}${SLACK_DEDICATED_TEST_API_HELPER}`,
|
|
708
|
+
`logger = logging.getLogger(__name__)\n${SECRET_FD_HELPER}${SLACK_DEDICATED_TEST_API_HELPER}${SLACK_MESSAGE_UNFURL_FILE_HELPER}`,
|
|
560
709
|
"v0.19 dedicated Slack helper",
|
|
561
710
|
);
|
|
562
711
|
patched = replaceExactlyOnce(
|
|
@@ -580,14 +729,36 @@ export function patchHermesSourceFile(patchKind, source) {
|
|
|
580
729
|
);
|
|
581
730
|
patched = replaceExactlyOnce(
|
|
582
731
|
patched,
|
|
583
|
-
|
|
584
|
-
|
|
732
|
+
[
|
|
733
|
+
" primary_client = AsyncWebClient(",
|
|
734
|
+
" token=primary_token,",
|
|
735
|
+
" user_agent_prefix=_HERMES_SLACK_USER_AGENT_PREFIX,",
|
|
736
|
+
" )",
|
|
737
|
+
].join("\n"),
|
|
738
|
+
[
|
|
739
|
+
" primary_client = AsyncWebClient(",
|
|
740
|
+
" token=primary_token,",
|
|
741
|
+
" user_agent_prefix=_HERMES_SLACK_USER_AGENT_PREFIX,",
|
|
742
|
+
" **_sellable_agent_slack_api_kwargs(),",
|
|
743
|
+
" )",
|
|
744
|
+
].join("\n"),
|
|
585
745
|
"v0.19 dedicated Slack app API client",
|
|
586
746
|
);
|
|
587
747
|
patched = replaceExactlyOnce(
|
|
588
748
|
patched,
|
|
589
|
-
|
|
590
|
-
|
|
749
|
+
[
|
|
750
|
+
" client = AsyncWebClient(",
|
|
751
|
+
" token=token,",
|
|
752
|
+
" user_agent_prefix=_HERMES_SLACK_USER_AGENT_PREFIX,",
|
|
753
|
+
" )",
|
|
754
|
+
].join("\n"),
|
|
755
|
+
[
|
|
756
|
+
" client = AsyncWebClient(",
|
|
757
|
+
" token=token,",
|
|
758
|
+
" user_agent_prefix=_HERMES_SLACK_USER_AGENT_PREFIX,",
|
|
759
|
+
" **_sellable_agent_slack_api_kwargs(),",
|
|
760
|
+
" )",
|
|
761
|
+
].join("\n"),
|
|
591
762
|
"v0.19 dedicated Slack workspace API client",
|
|
592
763
|
);
|
|
593
764
|
patched = replaceExactlyOnce(
|
|
@@ -610,6 +781,19 @@ export function patchHermesSourceFile(patchKind, source) {
|
|
|
610
781
|
].join("\n"),
|
|
611
782
|
"v0.19 dedicated Slack request identity",
|
|
612
783
|
);
|
|
784
|
+
patched = replaceExactlyOnce(
|
|
785
|
+
patched,
|
|
786
|
+
' files = event.get("files", [])',
|
|
787
|
+
[
|
|
788
|
+
' files = list(event.get("files") or [])',
|
|
789
|
+
" files.extend(",
|
|
790
|
+
" await _sellable_agent_recover_slack_message_unfurl_files(",
|
|
791
|
+
" self, slack_attachments, channel_id, team_id, files",
|
|
792
|
+
" )",
|
|
793
|
+
" )",
|
|
794
|
+
].join("\n"),
|
|
795
|
+
"v0.19 dedicated Slack message-unfurl files",
|
|
796
|
+
);
|
|
613
797
|
return patched;
|
|
614
798
|
}
|
|
615
799
|
|
|
@@ -800,29 +984,57 @@ export const HERMES_AGENT_BRIDGE_V019_CONTRACT = normalizeContract({
|
|
|
800
984
|
export const HERMES_AGENT_BRIDGE_CONTRACT_V019 = HERMES_AGENT_BRIDGE_V019_CONTRACT;
|
|
801
985
|
|
|
802
986
|
export const HERMES_AGENT_BRIDGE_DEDICATED_V019_CONTRACT = normalizeContract({
|
|
803
|
-
hermesVersion: "0.19.
|
|
987
|
+
hermesVersion: "0.19.1",
|
|
804
988
|
versionFile: {
|
|
805
989
|
path: "hermes_cli/__init__.py",
|
|
806
|
-
sha256: "
|
|
990
|
+
sha256: "653172511583adb549dc18fa71d6dde11dcbf2b85db8513ce896f8631e94fffd",
|
|
807
991
|
},
|
|
808
992
|
files: [
|
|
809
993
|
{
|
|
810
994
|
path: "gateway/config.py",
|
|
811
995
|
patchKind: "gateway-config-dedicated-v019",
|
|
812
|
-
sourceSha256: "
|
|
813
|
-
patchedSha256: "
|
|
996
|
+
sourceSha256: "c5138c0dce57ee148399b01fc4ec56f6cf1d8d0229b16c338b01254b59816e7f",
|
|
997
|
+
patchedSha256: "6970e3fec4c0fbe3357f8f8e03950f129e3f1c98178308bfb7f2ab99dfbc020e",
|
|
998
|
+
},
|
|
999
|
+
{
|
|
1000
|
+
path: "plugins/platforms/slack/adapter.py",
|
|
1001
|
+
patchKind: "slack-adapter-dedicated-v019",
|
|
1002
|
+
sourceSha256: "a58a82ce2af5137bf2452c89a5aaed6d6af562eef6fdad5597be17e15a4227ce",
|
|
1003
|
+
patchedSha256: "5b43bcb637f6cd602b2bd8642310091b4633b0934d14149d87665a91b512bba8",
|
|
1004
|
+
},
|
|
1005
|
+
{
|
|
1006
|
+
path: "tools/mcp_tool.py",
|
|
1007
|
+
patchKind: "mcp-tool",
|
|
1008
|
+
sourceSha256: "562e48fa192562000c852103c4f9f2e939dd41398605731b709389e03fd4f22d",
|
|
1009
|
+
patchedSha256: "9259001873878c6d696e6ad811e3bf42204c07d421f0685382656f913504f497",
|
|
1010
|
+
},
|
|
1011
|
+
],
|
|
1012
|
+
});
|
|
1013
|
+
|
|
1014
|
+
export const HERMES_AGENT_BRIDGE_DEDICATED_V020_CONTRACT = normalizeContract({
|
|
1015
|
+
hermesVersion: "0.20.0",
|
|
1016
|
+
versionFile: {
|
|
1017
|
+
path: "hermes_cli/__init__.py",
|
|
1018
|
+
sha256: "e4c421279251971d07f84628d1d59222f0368ab297ce8fd0dff10e5938fe971e",
|
|
1019
|
+
},
|
|
1020
|
+
files: [
|
|
1021
|
+
{
|
|
1022
|
+
path: "gateway/config.py",
|
|
1023
|
+
patchKind: "gateway-config-dedicated-v019",
|
|
1024
|
+
sourceSha256: "c5138c0dce57ee148399b01fc4ec56f6cf1d8d0229b16c338b01254b59816e7f",
|
|
1025
|
+
patchedSha256: "6970e3fec4c0fbe3357f8f8e03950f129e3f1c98178308bfb7f2ab99dfbc020e",
|
|
814
1026
|
},
|
|
815
1027
|
{
|
|
816
1028
|
path: "plugins/platforms/slack/adapter.py",
|
|
817
1029
|
patchKind: "slack-adapter-dedicated-v019",
|
|
818
|
-
sourceSha256: "
|
|
819
|
-
patchedSha256: "
|
|
1030
|
+
sourceSha256: "2fa41bb753b7c855c6aadaacbfdaec36d1cadb580afe47a8ee1cfecbb185dedf",
|
|
1031
|
+
patchedSha256: "846fe4865e42dca3a52aae66132db2a2ba8fdfbca74eca026c28881a7d1a59c5",
|
|
820
1032
|
},
|
|
821
1033
|
{
|
|
822
1034
|
path: "tools/mcp_tool.py",
|
|
823
1035
|
patchKind: "mcp-tool",
|
|
824
|
-
sourceSha256: "
|
|
825
|
-
patchedSha256: "
|
|
1036
|
+
sourceSha256: "f9d50eec7b98819fa91b8ce640c8a32eff0726e0f349832763852bd82bbbb958",
|
|
1037
|
+
patchedSha256: "a59146b2cce167591858a37a6f2c4d7be0d504fcbe73c8bb517388c826975cf0",
|
|
826
1038
|
},
|
|
827
1039
|
],
|
|
828
1040
|
});
|
|
@@ -45,7 +45,7 @@ export const HERMES_SNAPSHOT_CRON = Object.freeze({
|
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
const HERMES = "/opt/hermes/.venv/bin/hermes";
|
|
48
|
-
const VERSION = "0.
|
|
48
|
+
const VERSION = "0.20.0";
|
|
49
49
|
const ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
|
|
50
50
|
const SHA256 = /^[a-f0-9]{64}$/;
|
|
51
51
|
const MAX_BYTES = 128 * 1024 * 1024;
|
|
@@ -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.481";
|
|
42
42
|
const MCP_PACKAGE = "@sellable/mcp@0.1.760-wip.phase143.20260727100513";
|
|
43
43
|
const HERMES_VERSION = "0.18.0";
|
|
44
44
|
const SHA256 = /^[a-f0-9]{64}$/;
|
|
@@ -1540,7 +1540,7 @@ export function compileClaimToProfileDesired(activeClaim, config) {
|
|
|
1540
1540
|
]) ||
|
|
1541
1541
|
pinned.hermesCli !== "hermes" ||
|
|
1542
1542
|
pinned.hermesVersion !== "0.18.0" ||
|
|
1543
|
-
pinned.installerPackage !== "@sellable/install@0.1.
|
|
1543
|
+
pinned.installerPackage !== "@sellable/install@0.1.481" ||
|
|
1544
1544
|
pinned.mcpPackage !==
|
|
1545
1545
|
"@sellable/mcp@0.1.760-wip.phase143.20260727100513" ||
|
|
1546
1546
|
!Array.isArray(policy.toolInclude) ||
|
|
@@ -197,7 +197,7 @@ function validateDesired(desired) {
|
|
|
197
197
|
desired.serviceCredentialGeneration < 1 ||
|
|
198
198
|
desired.hermesCli !== "hermes" ||
|
|
199
199
|
desired.hermesVersion !== "0.18.0" ||
|
|
200
|
-
desired.installerPackage !== "@sellable/install@0.1.
|
|
200
|
+
desired.installerPackage !== "@sellable/install@0.1.481" ||
|
|
201
201
|
desired.mcpPackage !==
|
|
202
202
|
"@sellable/mcp@0.1.760-wip.phase143.20260727100513" ||
|
|
203
203
|
!Array.isArray(desired.toolInclude) ||
|
|
@@ -2081,7 +2081,7 @@ function validateNativeSlackDesired(desired) {
|
|
|
2081
2081
|
!SHA256.test(desired.policyHash ?? "") ||
|
|
2082
2082
|
!SHA256.test(desired.accessPolicyHash ?? "") ||
|
|
2083
2083
|
!SHA256.test(desired.runtimeDesiredHash ?? "") ||
|
|
2084
|
-
desired.hermesVersion !== "0.
|
|
2084
|
+
desired.hermesVersion !== "0.20.0" ||
|
|
2085
2085
|
!/^@sellable\/install@\d+\.\d+\.\d+(?:[-.A-Za-z0-9]+)?$/.test(
|
|
2086
2086
|
desired.installerPackage ?? ""
|
|
2087
2087
|
) ||
|
|
@@ -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.
|
|
28
|
+
export const PINNED_INSTALL_PACKAGE = "@sellable/install@0.1.481";
|
|
29
29
|
export const PINNED_MCP_PACKAGE =
|
|
30
30
|
"@sellable/mcp@0.1.760-wip.phase143.20260727100513";
|
|
31
31
|
|
|
@@ -612,7 +612,7 @@ function inspectProvisionedProfile({
|
|
|
612
612
|
!matchesReadback(manifest, request) ||
|
|
613
613
|
manifest.serviceCredentialReference !== serviceCredentialReference ||
|
|
614
614
|
manifest.installerPackage !== PINNED_INSTALL_PACKAGE ||
|
|
615
|
-
manifest.installerVersion !== "0.1.
|
|
615
|
+
manifest.installerVersion !== "0.1.481" ||
|
|
616
616
|
manifest.mcpPackage !== PINNED_MCP_PACKAGE ||
|
|
617
617
|
manifest.credentialKeyVersion !== credentialKeyVersion ||
|
|
618
618
|
!/^[a-f0-9]{16}$/.test(manifest.credentialFingerprint) ||
|
|
@@ -826,7 +826,7 @@ function successReceipt({
|
|
|
826
826
|
subject: `agent-profile:${observed.profileId}`,
|
|
827
827
|
cli: {
|
|
828
828
|
installPackage: PINNED_INSTALL_PACKAGE,
|
|
829
|
-
installVersion: "0.1.
|
|
829
|
+
installVersion: "0.1.481",
|
|
830
830
|
mcpPackage: PINNED_MCP_PACKAGE,
|
|
831
831
|
command: "hermes profile bootstrap",
|
|
832
832
|
},
|
|
@@ -874,7 +874,7 @@ function failure(code, stages, extra = {}, request = null) {
|
|
|
874
874
|
: "agent-profile:unbound",
|
|
875
875
|
cli: {
|
|
876
876
|
installPackage: PINNED_INSTALL_PACKAGE,
|
|
877
|
-
installVersion: "0.1.
|
|
877
|
+
installVersion: "0.1.481",
|
|
878
878
|
mcpPackage: PINNED_MCP_PACKAGE,
|
|
879
879
|
command: "hermes profile bootstrap",
|
|
880
880
|
},
|