@sellable/install 0.1.799 → 0.1.800
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-customer-image/Dockerfile +1 -1
- package/lib/sellable-agent/fly-customer-image/claude-code-runs-api.d.mts +2 -1
- package/lib/sellable-agent/fly-customer-image/claude-code-runs-api.mjs +47 -21
- package/lib/sellable-agent/fly-customer-image/customer-runtime.mjs +1 -1
- package/lib/sellable-agent/fly-customer-image/runs-api-connections.d.mts +6 -1
- package/lib/sellable-agent/fly-customer-image/runs-api-connections.mjs +26 -11
- package/lib/sellable-agent/fly-customer-image/runs-api-health-check.mjs +12 -6
- 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.800
|
|
7
7
|
ARG MCP_PACKAGE=@sellable/mcp@0.1.957
|
|
8
8
|
ARG INSTALLER_INTEGRITY
|
|
9
9
|
ARG MCP_INTEGRITY=sha512-tIZuO5IEanT/afamDIWdorUNMdqZA6xnjL9jGAmGqYIlIqkXdHB9slWiwfLfmM44iEp7OT98IBHJlvbpMThk6A==
|
|
10
10
|
|
|
11
|
-
RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.
|
|
11
|
+
RUN test "${INSTALLER_PACKAGE}" = "@sellable/install@0.1.800" \
|
|
12
12
|
&& test "${MCP_PACKAGE}" = "@sellable/mcp@0.1.957" \
|
|
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.799" \
|
|
|
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.800' || mcp.name !== '@sellable/mcp' || mcp.version !== '0.1.957') 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.800', installerIntegrity: process.argv[1], mcpPackage: '@sellable/mcp@0.1.957', 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.800` 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.957
|
|
10
10
|
ARG MCP_INTEGRITY=sha512-tIZuO5IEanT/afamDIWdorUNMdqZA6xnjL9jGAmGqYIlIqkXdHB9slWiwfLfmM44iEp7OT98IBHJlvbpMThk6A==
|
|
11
|
-
ARG INSTALLER_PACKAGE=@sellable/install@0.1.
|
|
11
|
+
ARG INSTALLER_PACKAGE=@sellable/install@0.1.800
|
|
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
|
|
@@ -58,7 +58,8 @@ export function validateClaudeRunsRequest(
|
|
|
58
58
|
export function endpointToolNames(options: {
|
|
59
59
|
turnDescriptorPath: string;
|
|
60
60
|
sessionId: string;
|
|
61
|
-
|
|
61
|
+
/** Absent: every run gets the tools its own turn descriptor allows. */
|
|
62
|
+
toolEndpointIds?: string[];
|
|
62
63
|
}): string[] | null;
|
|
63
64
|
export function claudeInvocation(
|
|
64
65
|
request: ClaudeRunsRequest,
|
|
@@ -100,15 +100,17 @@ export function validateClaudeRunsRequest(body, models) {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
|
-
* A
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* descriptor
|
|
103
|
+
* A run's own allowed tools, read from the signed turn descriptor the runtime
|
|
104
|
+
* installed for its session before submitting. With a tool list, only runs on
|
|
105
|
+
* those endpoints get tools (and must have some); without one, every run gets
|
|
106
|
+
* exactly the tools its descriptor allows, and a run allowed none is tool-free
|
|
107
|
+
* (null). This only narrows: the context proxy verifies the descriptor itself
|
|
108
|
+
* before it lists or calls any tool.
|
|
107
109
|
*/
|
|
108
110
|
export function endpointToolNames({
|
|
109
111
|
turnDescriptorPath,
|
|
110
112
|
sessionId,
|
|
111
|
-
toolEndpointIds,
|
|
113
|
+
toolEndpointIds = undefined,
|
|
112
114
|
}) {
|
|
113
115
|
const path = endpointMcpDescriptorPath(turnDescriptorPath, sessionId);
|
|
114
116
|
if (!path) return null;
|
|
@@ -120,18 +122,19 @@ export function endpointToolNames({
|
|
|
120
122
|
throw error;
|
|
121
123
|
}
|
|
122
124
|
const body = JSON.parse(readFileSync(path, "utf8"))?.body;
|
|
123
|
-
if (!toolEndpointIds.includes(body?.endpointId))
|
|
124
|
-
|
|
125
|
+
if (toolEndpointIds && !toolEndpointIds.includes(body?.endpointId))
|
|
126
|
+
return null;
|
|
127
|
+
const names = body?.allowedToolNames;
|
|
125
128
|
if (
|
|
126
129
|
endpointHermesSessionId(body) !== sessionId ||
|
|
127
130
|
!Array.isArray(names) ||
|
|
128
|
-
!names.length ||
|
|
131
|
+
(toolEndpointIds && !names.length) ||
|
|
129
132
|
names.some(
|
|
130
133
|
(name) => typeof name !== "string" || !/^[A-Za-z0-9_-]{1,128}$/.test(name)
|
|
131
134
|
)
|
|
132
135
|
)
|
|
133
136
|
throw new Error("claude_runs_tool_descriptor_rejected");
|
|
134
|
-
return [...names];
|
|
137
|
+
return names.length ? [...names] : null;
|
|
135
138
|
}
|
|
136
139
|
|
|
137
140
|
export function claudeInvocation(
|
|
@@ -266,6 +269,7 @@ export function claudeAccountDirs(root) {
|
|
|
266
269
|
|
|
267
270
|
const MONTHS = "janfebmaraprmayjunjulaugsepoctnovdec";
|
|
268
271
|
const USAGE_LIMIT_RETRY_MS = 15 * 60_000;
|
|
272
|
+
const SIGN_IN_TRUST_MS = 5 * 60_000;
|
|
269
273
|
|
|
270
274
|
// Claude Code reports a used-up plan as an API 429 result, for example
|
|
271
275
|
// "You've hit your weekly limit · resets Oct 7, 10am (UTC)". Returns when that
|
|
@@ -476,6 +480,31 @@ export function createClaudeRunsApi({
|
|
|
476
480
|
const usageLimitedUntil = new Map();
|
|
477
481
|
const resting = (configDir) =>
|
|
478
482
|
(usageLimitedUntil.get(configDir) ?? 0) > now();
|
|
483
|
+
// `claude auth status` starts a whole CLI: on the 4-CPU Admin machine seven
|
|
484
|
+
// at once take longer than its 8s timeout. Runs that arrive together share
|
|
485
|
+
// one check, a good answer is trusted for five minutes, and only a definite
|
|
486
|
+
// SIGN_IN_REQUIRED keeps a run off an account; an unanswered check runs and
|
|
487
|
+
// lets the CLI itself fail the run if the sign-in is really gone.
|
|
488
|
+
const signedInAt = new Map();
|
|
489
|
+
const signInChecks = new Map();
|
|
490
|
+
const signInState = (configDir) => {
|
|
491
|
+
if (now() - (signedInAt.get(configDir) ?? -Infinity) < SIGN_IN_TRUST_MS)
|
|
492
|
+
return Promise.resolve("READY");
|
|
493
|
+
let check = signInChecks.get(configDir);
|
|
494
|
+
if (!check) {
|
|
495
|
+
check = Promise.resolve()
|
|
496
|
+
.then(() => checkAuthentication(configDir))
|
|
497
|
+
.catch(() => "UNAVAILABLE")
|
|
498
|
+
.then((state) => {
|
|
499
|
+
signInChecks.delete(configDir);
|
|
500
|
+
if (state === "READY") signedInAt.set(configDir, now());
|
|
501
|
+
else signedInAt.delete(configDir);
|
|
502
|
+
return state;
|
|
503
|
+
});
|
|
504
|
+
signInChecks.set(configDir, check);
|
|
505
|
+
}
|
|
506
|
+
return check;
|
|
507
|
+
};
|
|
479
508
|
const runOnAccounts = (request) => {
|
|
480
509
|
let activeRun;
|
|
481
510
|
let stopped = false;
|
|
@@ -487,13 +516,10 @@ export function createClaudeRunsApi({
|
|
|
487
516
|
failure = "claude_runs_usage_limited";
|
|
488
517
|
continue;
|
|
489
518
|
}
|
|
490
|
-
const state = await
|
|
519
|
+
const state = await signInState(configDir);
|
|
491
520
|
if (stopped) throw new Error("claude_runs_cancelled");
|
|
492
|
-
if (state
|
|
493
|
-
failure ??=
|
|
494
|
-
state === "SIGN_IN_REQUIRED"
|
|
495
|
-
? "claude_runs_sign_in_required"
|
|
496
|
-
: "claude_runs_auth_check_unavailable";
|
|
521
|
+
if (state === "SIGN_IN_REQUIRED") {
|
|
522
|
+
failure ??= "claude_runs_sign_in_required";
|
|
497
523
|
continue;
|
|
498
524
|
}
|
|
499
525
|
activeRun = startRun(request, {
|
|
@@ -503,8 +529,10 @@ export function createClaudeRunsApi({
|
|
|
503
529
|
try {
|
|
504
530
|
return await activeRun.promise;
|
|
505
531
|
} catch (error) {
|
|
506
|
-
if (stopped || error.message !== "claude_runs_usage_limited")
|
|
532
|
+
if (stopped || error.message !== "claude_runs_usage_limited") {
|
|
533
|
+
signedInAt.delete(configDir);
|
|
507
534
|
throw error;
|
|
535
|
+
}
|
|
508
536
|
usageLimitedUntil.set(configDir, error.retryAt);
|
|
509
537
|
failure = "claude_runs_usage_limited";
|
|
510
538
|
}
|
|
@@ -528,9 +556,7 @@ export function createClaudeRunsApi({
|
|
|
528
556
|
retryAts.push(usageLimitedUntil.get(configDir));
|
|
529
557
|
continue;
|
|
530
558
|
}
|
|
531
|
-
const state = await
|
|
532
|
-
() => "UNAVAILABLE"
|
|
533
|
-
);
|
|
559
|
+
const state = await signInState(configDir);
|
|
534
560
|
if (state === "READY") ready++;
|
|
535
561
|
if (state === "SIGN_IN_REQUIRED") signedOut++;
|
|
536
562
|
}
|
|
@@ -552,7 +578,7 @@ export function createClaudeRunsApi({
|
|
|
552
578
|
};
|
|
553
579
|
// The run's own tools and the profile's MCP server, or null for a tool-free run.
|
|
554
580
|
const resolveTools = (request) => {
|
|
555
|
-
if (!
|
|
581
|
+
if (!toolLanes) return null;
|
|
556
582
|
const names = endpointToolNames({
|
|
557
583
|
turnDescriptorPath: toolLanes.turnDescriptorPath,
|
|
558
584
|
sessionId: request.sessionId,
|
|
@@ -644,7 +670,7 @@ export function createClaudeRunsApi({
|
|
|
644
670
|
});
|
|
645
671
|
}
|
|
646
672
|
if (req.method === "POST" && req.url === "/v1/runs") {
|
|
647
|
-
if (full("plain") && (!
|
|
673
|
+
if (full("plain") && (!toolLanes || full("tools")))
|
|
648
674
|
return json(res, 429, { error: "claude_runs_busy" });
|
|
649
675
|
let request;
|
|
650
676
|
try {
|
|
@@ -126,7 +126,7 @@ const RUNTIME_GENERATION = Number(
|
|
|
126
126
|
const BOOT_SESSION_ID = randomUUID();
|
|
127
127
|
const HERMES_VERSION = process.env.SELLABLE_AGENT_HERMES_VERSION ?? "0.21.5";
|
|
128
128
|
const INSTALLER_PACKAGE =
|
|
129
|
-
process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ?? "@sellable/install@0.1.
|
|
129
|
+
process.env.SELLABLE_AGENT_INSTALLER_PACKAGE ?? "@sellable/install@0.1.800";
|
|
130
130
|
const MCP_PACKAGE =
|
|
131
131
|
process.env.SELLABLE_AGENT_MCP_PACKAGE ?? "@sellable/mcp@0.1.957";
|
|
132
132
|
export const ENDPOINT_MAX_CONCURRENT_RUNS = 10;
|
|
@@ -5,7 +5,8 @@ export type RunsApiConnection = Readonly<{
|
|
|
5
5
|
agentId: string;
|
|
6
6
|
baseUrl: string;
|
|
7
7
|
apiKeyFile: string;
|
|
8
|
-
|
|
8
|
+
/** Absent: serves every endpoint of its agent. */
|
|
9
|
+
endpointIds?: string[];
|
|
9
10
|
workKinds: Array<"STANDARD" | "OPENER" | "REPLY" | "FOLLOW_UP">;
|
|
10
11
|
models: Array<{
|
|
11
12
|
provider: string;
|
|
@@ -19,6 +20,10 @@ export type RunsApiConnection = Readonly<{
|
|
|
19
20
|
structuredOutputs?: boolean;
|
|
20
21
|
}>;
|
|
21
22
|
export function runsApiConnectionId(connection: RunsApiConnection): string;
|
|
23
|
+
export function runsApiConnectionServesEndpoint(
|
|
24
|
+
connection: RunsApiConnection,
|
|
25
|
+
endpointId: string
|
|
26
|
+
): boolean;
|
|
22
27
|
export function parseRunsApiConnections(raw: unknown): RunsApiConnection[];
|
|
23
28
|
export function runsApiConnectionsForRuntime(
|
|
24
29
|
raw: unknown,
|
|
@@ -76,10 +76,12 @@ export function parseRunsApiConnections(raw) {
|
|
|
76
76
|
entry.apiKeyFile
|
|
77
77
|
.split("/")
|
|
78
78
|
.some((part) => part === "." || part === "..") ||
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
// Absent: the connection serves every endpoint of its agent.
|
|
80
|
+
(entry.endpointIds !== undefined &&
|
|
81
|
+
(!Array.isArray(entry.endpointIds) ||
|
|
82
|
+
!entry.endpointIds.length ||
|
|
83
|
+
entry.endpointIds.length > 64 ||
|
|
84
|
+
!entry.endpointIds.every(id))) ||
|
|
83
85
|
!Array.isArray(entry.workKinds) ||
|
|
84
86
|
!entry.workKinds.length ||
|
|
85
87
|
!entry.workKinds.every((kind) =>
|
|
@@ -138,24 +140,29 @@ export function parseRunsApiConnections(raw) {
|
|
|
138
140
|
)
|
|
139
141
|
fail();
|
|
140
142
|
}
|
|
141
|
-
//
|
|
142
|
-
// service
|
|
143
|
+
// When present, only runs on these endpoints get their own allowed tools
|
|
144
|
+
// from the image-owned service. When absent, a run gets the tools its own
|
|
145
|
+
// signed turn descriptor allows, and a run allowed none stays tool-free.
|
|
143
146
|
if (
|
|
144
147
|
entry.toolEndpointIds !== undefined &&
|
|
145
148
|
(entry.localRoot === undefined ||
|
|
146
149
|
!Array.isArray(entry.toolEndpointIds) ||
|
|
147
150
|
!entry.toolEndpointIds.length ||
|
|
151
|
+
!entry.toolEndpointIds.every(id) ||
|
|
148
152
|
new Set(entry.toolEndpointIds).size !== entry.toolEndpointIds.length ||
|
|
149
|
-
entry.
|
|
150
|
-
|
|
151
|
-
|
|
153
|
+
(entry.endpointIds !== undefined &&
|
|
154
|
+
entry.toolEndpointIds.some(
|
|
155
|
+
(value) => !entry.endpointIds.includes(value)
|
|
156
|
+
)))
|
|
152
157
|
)
|
|
153
158
|
fail();
|
|
154
159
|
return Object.freeze({
|
|
155
160
|
...entry,
|
|
156
161
|
baseUrl,
|
|
157
162
|
models,
|
|
158
|
-
|
|
163
|
+
...(entry.endpointIds === undefined
|
|
164
|
+
? {}
|
|
165
|
+
: { endpointIds: [...entry.endpointIds] }),
|
|
159
166
|
workKinds: [...entry.workKinds],
|
|
160
167
|
...(entry.toolEndpointIds === undefined
|
|
161
168
|
? {}
|
|
@@ -164,6 +171,14 @@ export function parseRunsApiConnections(raw) {
|
|
|
164
171
|
});
|
|
165
172
|
}
|
|
166
173
|
|
|
174
|
+
/** Whether a trusted connection may serve runs of this endpoint. */
|
|
175
|
+
export function runsApiConnectionServesEndpoint(connection, endpointId) {
|
|
176
|
+
return (
|
|
177
|
+
connection.endpointIds === undefined ||
|
|
178
|
+
connection.endpointIds.includes(endpointId)
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
167
182
|
export function runsApiConnectionId(connection) {
|
|
168
183
|
return `runs_${createHash("sha256")
|
|
169
184
|
.update(
|
|
@@ -210,7 +225,7 @@ export function createConfiguredRunsClient({
|
|
|
210
225
|
if (
|
|
211
226
|
!connection ||
|
|
212
227
|
env.SELLABLE_RUNTIME_ID !== connection.runtimeId ||
|
|
213
|
-
!connection
|
|
228
|
+
!runsApiConnectionServesEndpoint(connection, claim.attempt.endpointId) ||
|
|
214
229
|
!connection.workKinds.includes(workKind) ||
|
|
215
230
|
!connection.models.some(
|
|
216
231
|
(allowed) =>
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
createConfiguredRunsClient,
|
|
8
8
|
RUNS_API_CONNECTIONS_ENV,
|
|
9
9
|
runsApiConnectionId,
|
|
10
|
+
runsApiConnectionServesEndpoint,
|
|
10
11
|
runsApiConnectionsForRuntime,
|
|
11
12
|
} from "./runs-api-connections.mjs";
|
|
12
13
|
|
|
@@ -35,7 +36,7 @@ export async function checkRunsApiConnection(
|
|
|
35
36
|
).find(
|
|
36
37
|
(candidate) =>
|
|
37
38
|
runsApiConnectionId(candidate) === request.connectionId &&
|
|
38
|
-
candidate
|
|
39
|
+
runsApiConnectionServesEndpoint(candidate, request.endpointId)
|
|
39
40
|
);
|
|
40
41
|
if (!connection) return result("NOT_CONFIGURED");
|
|
41
42
|
try {
|
|
@@ -47,10 +48,12 @@ export async function checkRunsApiConnection(
|
|
|
47
48
|
{
|
|
48
49
|
headers: {
|
|
49
50
|
authorization: `Bearer ${token}`,
|
|
50
|
-
...(connection.protocol?.startsWith("openai-")
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
...(connection.protocol?.startsWith("openai-")
|
|
52
|
+
? {}
|
|
53
|
+
: {
|
|
54
|
+
"x-sellable-workspace-id": connection.workspaceId,
|
|
55
|
+
"x-sellable-agent-id": connection.agentId,
|
|
56
|
+
}),
|
|
54
57
|
},
|
|
55
58
|
redirect: "error",
|
|
56
59
|
signal: AbortSignal.timeout(12_000),
|
|
@@ -141,7 +144,10 @@ export async function verifyRunsApiSelection(
|
|
|
141
144
|
runsApiConnectionId(item) === request.connectionId &&
|
|
142
145
|
item.baseUrl === selection.runsApiBaseUrl
|
|
143
146
|
);
|
|
144
|
-
if (
|
|
147
|
+
if (
|
|
148
|
+
!connection ||
|
|
149
|
+
!runsApiConnectionServesEndpoint(connection, request.endpointId)
|
|
150
|
+
)
|
|
145
151
|
return result("NOT_CONFIGURED");
|
|
146
152
|
verificationWorkKind = connection.workKinds.includes("STANDARD")
|
|
147
153
|
? "STANDARD"
|
|
@@ -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.800";
|
|
42
42
|
const MCP_PACKAGE = "@sellable/mcp@0.1.957";
|
|
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.
|
|
1549
|
+
pinned.installerPackage !== "@sellable/install@0.1.800" ||
|
|
1550
1550
|
pinned.mcpPackage !== "@sellable/mcp@0.1.957" ||
|
|
1551
1551
|
!Array.isArray(policy.toolInclude) ||
|
|
1552
1552
|
policy.toolInclude.length === 0 ||
|
|
@@ -312,7 +312,7 @@ function validateDesired(desired) {
|
|
|
312
312
|
desired.serviceCredentialGeneration < 1 ||
|
|
313
313
|
desired.hermesCli !== "hermes" ||
|
|
314
314
|
desired.hermesVersion !== "0.18.0" ||
|
|
315
|
-
desired.installerPackage !== "@sellable/install@0.1.
|
|
315
|
+
desired.installerPackage !== "@sellable/install@0.1.800" ||
|
|
316
316
|
desired.mcpPackage !== "@sellable/mcp@0.1.957" ||
|
|
317
317
|
!Array.isArray(desired.toolInclude) ||
|
|
318
318
|
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.
|
|
28
|
+
export const PINNED_INSTALL_PACKAGE = "@sellable/install@0.1.800";
|
|
29
29
|
export const PINNED_MCP_PACKAGE = "@sellable/mcp@0.1.957";
|
|
30
30
|
const PINNED_INSTALL_VERSION = PINNED_INSTALL_PACKAGE.slice(
|
|
31
31
|
PINNED_INSTALL_PACKAGE.lastIndexOf("@") + 1
|