@vellumai/cli 0.12.2 → 0.12.3-staging.1
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/node_modules/@vellumai/environments/src/shell.test.ts +21 -0
- package/node_modules/@vellumai/environments/src/shell.ts +24 -0
- package/node_modules/@vellumai/local-mode/node_modules/@vellumai/environments/src/shell.test.ts +21 -0
- package/node_modules/@vellumai/local-mode/node_modules/@vellumai/environments/src/shell.ts +24 -0
- package/node_modules/@vellumai/local-mode/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
- package/node_modules/@vellumai/local-mode/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
- package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +4 -1
- package/package.json +1 -1
- package/src/lib/__tests__/docker.test.ts +1 -0
- package/src/lib/__tests__/local-ces.test.ts +25 -2
- package/src/lib/local.ts +32 -21
- package/src/lib/platform-client.ts +0 -12
- package/src/lib/provider-secrets.ts +4 -0
- package/src/lib/statefulset.ts +1 -0
- package/src/shared/provider-env-vars.ts +1 -0
|
@@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test";
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
buildShellInvocation,
|
|
5
|
+
buildShellSpawnFlags,
|
|
5
6
|
pathListDelimiter,
|
|
6
7
|
prependUniquePathEntries,
|
|
7
8
|
} from "./shell.js";
|
|
@@ -38,6 +39,26 @@ describe("buildShellInvocation", () => {
|
|
|
38
39
|
});
|
|
39
40
|
});
|
|
40
41
|
|
|
42
|
+
describe("buildShellSpawnFlags", () => {
|
|
43
|
+
test("creates a POSIX process group and hides Windows consoles", () => {
|
|
44
|
+
expect(buildShellSpawnFlags("linux")).toEqual({
|
|
45
|
+
detached: true,
|
|
46
|
+
windowsHide: true,
|
|
47
|
+
});
|
|
48
|
+
expect(buildShellSpawnFlags("darwin")).toEqual({
|
|
49
|
+
detached: true,
|
|
50
|
+
windowsHide: true,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("does not detach Windows children that use piped stdio", () => {
|
|
55
|
+
expect(buildShellSpawnFlags("win32")).toEqual({
|
|
56
|
+
detached: false,
|
|
57
|
+
windowsHide: true,
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
41
62
|
describe("path list handling", () => {
|
|
42
63
|
test("uses the platform delimiter", () => {
|
|
43
64
|
expect(pathListDelimiter("win32")).toBe(";");
|
|
@@ -5,6 +5,11 @@ export interface ShellInvocation {
|
|
|
5
5
|
args: string[];
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
export interface ShellSpawnFlags {
|
|
9
|
+
detached: boolean;
|
|
10
|
+
windowsHide: true;
|
|
11
|
+
}
|
|
12
|
+
|
|
8
13
|
const WINDOWS_UTF8_PREAMBLE =
|
|
9
14
|
"try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch {}; " +
|
|
10
15
|
"$OutputEncoding = [System.Text.Encoding]::UTF8; " +
|
|
@@ -43,6 +48,25 @@ export function buildShellInvocation(
|
|
|
43
48
|
return { command: "bash", args: ["-c", "--", command] };
|
|
44
49
|
}
|
|
45
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Spawn flags for assistant-owned shell children (sandbox bash, local
|
|
53
|
+
* host_bash fallback, sanitized CLI bash, skill runners, scheduled scripts).
|
|
54
|
+
*
|
|
55
|
+
* POSIX uses a new process group so timeout/abort can SIGKILL the tree via
|
|
56
|
+
* `-pid`. Windows process trees are torn down with `taskkill /T`, which does
|
|
57
|
+
* not need a detached process. Combining `DETACHED_PROCESS`,
|
|
58
|
+
* `CREATE_NO_WINDOW`, and piped stdio on Windows can emit `close` with exit
|
|
59
|
+
* 0 and empty pipes without running the encoded command.
|
|
60
|
+
*/
|
|
61
|
+
export function buildShellSpawnFlags(
|
|
62
|
+
hostPlatform: NodeJS.Platform = process.platform,
|
|
63
|
+
): ShellSpawnFlags {
|
|
64
|
+
return {
|
|
65
|
+
detached: hostPlatform !== "win32",
|
|
66
|
+
windowsHide: true,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
46
70
|
export function pathListDelimiter(
|
|
47
71
|
hostPlatform: NodeJS.Platform = process.platform,
|
|
48
72
|
): string {
|
package/node_modules/@vellumai/local-mode/node_modules/@vellumai/environments/src/shell.test.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test";
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
buildShellInvocation,
|
|
5
|
+
buildShellSpawnFlags,
|
|
5
6
|
pathListDelimiter,
|
|
6
7
|
prependUniquePathEntries,
|
|
7
8
|
} from "./shell.js";
|
|
@@ -38,6 +39,26 @@ describe("buildShellInvocation", () => {
|
|
|
38
39
|
});
|
|
39
40
|
});
|
|
40
41
|
|
|
42
|
+
describe("buildShellSpawnFlags", () => {
|
|
43
|
+
test("creates a POSIX process group and hides Windows consoles", () => {
|
|
44
|
+
expect(buildShellSpawnFlags("linux")).toEqual({
|
|
45
|
+
detached: true,
|
|
46
|
+
windowsHide: true,
|
|
47
|
+
});
|
|
48
|
+
expect(buildShellSpawnFlags("darwin")).toEqual({
|
|
49
|
+
detached: true,
|
|
50
|
+
windowsHide: true,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("does not detach Windows children that use piped stdio", () => {
|
|
55
|
+
expect(buildShellSpawnFlags("win32")).toEqual({
|
|
56
|
+
detached: false,
|
|
57
|
+
windowsHide: true,
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
41
62
|
describe("path list handling", () => {
|
|
42
63
|
test("uses the platform delimiter", () => {
|
|
43
64
|
expect(pathListDelimiter("win32")).toBe(";");
|
|
@@ -5,6 +5,11 @@ export interface ShellInvocation {
|
|
|
5
5
|
args: string[];
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
export interface ShellSpawnFlags {
|
|
9
|
+
detached: boolean;
|
|
10
|
+
windowsHide: true;
|
|
11
|
+
}
|
|
12
|
+
|
|
8
13
|
const WINDOWS_UTF8_PREAMBLE =
|
|
9
14
|
"try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch {}; " +
|
|
10
15
|
"$OutputEncoding = [System.Text.Encoding]::UTF8; " +
|
|
@@ -43,6 +48,25 @@ export function buildShellInvocation(
|
|
|
43
48
|
return { command: "bash", args: ["-c", "--", command] };
|
|
44
49
|
}
|
|
45
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Spawn flags for assistant-owned shell children (sandbox bash, local
|
|
53
|
+
* host_bash fallback, sanitized CLI bash, skill runners, scheduled scripts).
|
|
54
|
+
*
|
|
55
|
+
* POSIX uses a new process group so timeout/abort can SIGKILL the tree via
|
|
56
|
+
* `-pid`. Windows process trees are torn down with `taskkill /T`, which does
|
|
57
|
+
* not need a detached process. Combining `DETACHED_PROCESS`,
|
|
58
|
+
* `CREATE_NO_WINDOW`, and piped stdio on Windows can emit `close` with exit
|
|
59
|
+
* 0 and empty pipes without running the encoded command.
|
|
60
|
+
*/
|
|
61
|
+
export function buildShellSpawnFlags(
|
|
62
|
+
hostPlatform: NodeJS.Platform = process.platform,
|
|
63
|
+
): ShellSpawnFlags {
|
|
64
|
+
return {
|
|
65
|
+
detached: hostPlatform !== "win32",
|
|
66
|
+
windowsHide: true,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
46
70
|
export function pathListDelimiter(
|
|
47
71
|
hostPlatform: NodeJS.Platform = process.platform,
|
|
48
72
|
): string {
|
|
@@ -63,6 +63,7 @@ const FIXTURES: Record<string, string> = {
|
|
|
63
63
|
"Perplexity API Key": `pplx-${filler(40)}`,
|
|
64
64
|
"Tavily API Key": `tvly-${filler(20)}`,
|
|
65
65
|
"Firecrawl API Key": `fc-${filler(20)}`,
|
|
66
|
+
"Resend API Key": `re_${filler(8)}_${filler(24)}`,
|
|
66
67
|
};
|
|
67
68
|
|
|
68
69
|
describe("subpath export", () => {
|
|
@@ -230,6 +230,9 @@ export const PREFIX_PATTERNS: SecretPrefixPattern[] = [
|
|
|
230
230
|
|
|
231
231
|
// -- Firecrawl --
|
|
232
232
|
{ label: "Firecrawl API Key", regex: /fc-[A-Za-z0-9]{20,}/ },
|
|
233
|
+
// Resend documents only the `re_` prefix; the segment shape is the observed
|
|
234
|
+
// key format. Strict on purpose: bare `re_` prefixes ordinary identifiers.
|
|
235
|
+
{ label: "Resend API Key", regex: /re_[A-Za-z0-9]{8}_[A-Za-z0-9]{24,}/ },
|
|
233
236
|
];
|
|
234
237
|
|
|
235
238
|
/**
|
|
@@ -362,7 +365,7 @@ export function isPlaceholderValue(value: string): boolean {
|
|
|
362
365
|
// Strip known prefixes to isolate the variable part
|
|
363
366
|
const variablePart = value
|
|
364
367
|
.replace(
|
|
365
|
-
/^(?:AKIA|gh[pousr]_|github_pat_|glpat-|sk_live_|rk_live_|xoxb-|xoxp-|xapp-|sk-ant-|sk-proj-|sk-or-v1-|AIza|GOCSPX-|SK|SG\.|npm_|pypi-|key-|lin_api_|ntn_|fw_|pplx
|
|
368
|
+
/^(?:AKIA|gh[pousr]_|github_pat_|glpat-|sk_live_|rk_live_|xoxb-|xoxp-|xapp-|sk-ant-|sk-proj-|sk-or-v1-|AIza|GOCSPX-|SK|SG\.|npm_|pypi-|key-|lin_api_|ntn_|fw_|pplx-|re_|-----BEGIN [A-Z ]*PRIVATE KEY-----)/,
|
|
366
369
|
"",
|
|
367
370
|
)
|
|
368
371
|
.replace(/[^A-Za-z0-9]/g, "");
|
|
@@ -63,6 +63,7 @@ const FIXTURES: Record<string, string> = {
|
|
|
63
63
|
"Perplexity API Key": `pplx-${filler(40)}`,
|
|
64
64
|
"Tavily API Key": `tvly-${filler(20)}`,
|
|
65
65
|
"Firecrawl API Key": `fc-${filler(20)}`,
|
|
66
|
+
"Resend API Key": `re_${filler(8)}_${filler(24)}`,
|
|
66
67
|
};
|
|
67
68
|
|
|
68
69
|
describe("subpath export", () => {
|
|
@@ -230,6 +230,9 @@ export const PREFIX_PATTERNS: SecretPrefixPattern[] = [
|
|
|
230
230
|
|
|
231
231
|
// -- Firecrawl --
|
|
232
232
|
{ label: "Firecrawl API Key", regex: /fc-[A-Za-z0-9]{20,}/ },
|
|
233
|
+
// Resend documents only the `re_` prefix; the segment shape is the observed
|
|
234
|
+
// key format. Strict on purpose: bare `re_` prefixes ordinary identifiers.
|
|
235
|
+
{ label: "Resend API Key", regex: /re_[A-Za-z0-9]{8}_[A-Za-z0-9]{24,}/ },
|
|
233
236
|
];
|
|
234
237
|
|
|
235
238
|
/**
|
|
@@ -362,7 +365,7 @@ export function isPlaceholderValue(value: string): boolean {
|
|
|
362
365
|
// Strip known prefixes to isolate the variable part
|
|
363
366
|
const variablePart = value
|
|
364
367
|
.replace(
|
|
365
|
-
/^(?:AKIA|gh[pousr]_|github_pat_|glpat-|sk_live_|rk_live_|xoxb-|xoxp-|xapp-|sk-ant-|sk-proj-|sk-or-v1-|AIza|GOCSPX-|SK|SG\.|npm_|pypi-|key-|lin_api_|ntn_|fw_|pplx
|
|
368
|
+
/^(?:AKIA|gh[pousr]_|github_pat_|glpat-|sk_live_|rk_live_|xoxb-|xoxp-|xapp-|sk-ant-|sk-proj-|sk-or-v1-|AIza|GOCSPX-|SK|SG\.|npm_|pypi-|key-|lin_api_|ntn_|fw_|pplx-|re_|-----BEGIN [A-Z ]*PRIVATE KEY-----)/,
|
|
366
369
|
"",
|
|
367
370
|
)
|
|
368
371
|
.replace(/[^A-Za-z0-9]/g, "");
|
package/package.json
CHANGED
|
@@ -83,6 +83,7 @@ describe("buildServiceRunArgs — assistant", () => {
|
|
|
83
83
|
const args = buildAssistantArgs();
|
|
84
84
|
expect(args).toContain("IS_CONTAINERIZED=true");
|
|
85
85
|
expect(args).toContain("VELLUM_WORKSPACE_DIR=/workspace");
|
|
86
|
+
expect(args).toContain("CES_BOOTSTRAP_SOCKET_DIR=/run/ces-bootstrap");
|
|
86
87
|
expect(args).toContain(`VELLUM_ASSISTANT_NAME=${instanceName}`);
|
|
87
88
|
});
|
|
88
89
|
|
|
@@ -9,6 +9,8 @@ import { tmpdir } from "node:os";
|
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
import { afterAll, beforeAll, describe, expect, mock, test } from "bun:test";
|
|
11
11
|
|
|
12
|
+
import { resolveIpcEndpoint } from "@vellumai/ipc-server-utils";
|
|
13
|
+
|
|
12
14
|
import { resolveCesSocketPath, startCes } from "../local.js";
|
|
13
15
|
|
|
14
16
|
// ---------------------------------------------------------------------------
|
|
@@ -106,7 +108,7 @@ describe("startCes", () => {
|
|
|
106
108
|
// startCes unlinks the stale socket, then polls for it. We create it with
|
|
107
109
|
// a slight delay so the poll catches it.
|
|
108
110
|
setTimeout(() => {
|
|
109
|
-
const socketDir = join(vellumDir, "
|
|
111
|
+
const socketDir = join(vellumDir, "protected", "credential-executor");
|
|
110
112
|
mkdirSync(socketDir, { recursive: true });
|
|
111
113
|
writeFileSync(join(socketDir, "ces.sock"), "");
|
|
112
114
|
}, 50);
|
|
@@ -126,7 +128,9 @@ describe("startCes", () => {
|
|
|
126
128
|
|
|
127
129
|
// Verify env vars
|
|
128
130
|
const env = lastSpawnCall!.options.env!;
|
|
129
|
-
expect(env["
|
|
131
|
+
expect(env["CES_BOOTSTRAP_SOCKET_DIR"]).toBe(
|
|
132
|
+
join(tempDir, ".vellum", "protected", "credential-executor"),
|
|
133
|
+
);
|
|
130
134
|
expect(env["CREDENTIAL_SECURITY_DIR"]).toBeDefined();
|
|
131
135
|
expect(env["VELLUM_WORKSPACE_DIR"]).toBeDefined();
|
|
132
136
|
|
|
@@ -143,4 +147,23 @@ describe("startCes", () => {
|
|
|
143
147
|
expect(socketPath.startsWith("\\\\.\\pipe\\vellum-ces-")).toBe(true);
|
|
144
148
|
expect(socketPath).not.toContain("Example");
|
|
145
149
|
});
|
|
150
|
+
|
|
151
|
+
test("POSIX local CES seam matches resolveIpcEndpoint", () => {
|
|
152
|
+
const resources = {
|
|
153
|
+
instanceDir: "/tmp/assistant-123",
|
|
154
|
+
} as Parameters<typeof resolveCesSocketPath>[0];
|
|
155
|
+
|
|
156
|
+
const socketPath = resolveCesSocketPath(resources, "linux");
|
|
157
|
+
expect(socketPath).toBe(
|
|
158
|
+
resolveIpcEndpoint("ces", {
|
|
159
|
+
workspaceDir: join(
|
|
160
|
+
"/tmp/assistant-123",
|
|
161
|
+
".vellum",
|
|
162
|
+
"protected",
|
|
163
|
+
"credential-executor",
|
|
164
|
+
),
|
|
165
|
+
platform: "linux",
|
|
166
|
+
}).path,
|
|
167
|
+
);
|
|
168
|
+
});
|
|
146
169
|
});
|
package/src/lib/local.ts
CHANGED
|
@@ -606,6 +606,24 @@ type DaemonStartOptions = {
|
|
|
606
606
|
signingKey?: string;
|
|
607
607
|
};
|
|
608
608
|
|
|
609
|
+
/**
|
|
610
|
+
* Directory that holds the local CES Unix socket (`ces.sock`).
|
|
611
|
+
*
|
|
612
|
+
* Matches CES's local data root: `{CREDENTIAL_SECURITY_DIR}/credential-executor`.
|
|
613
|
+
* Local CLI and managed sidecars share `CES_BOOTSTRAP_SOCKET_DIR`; this is the
|
|
614
|
+
* writable per-instance directory used outside containers.
|
|
615
|
+
*/
|
|
616
|
+
function resolveCesBootstrapSocketDir(
|
|
617
|
+
resources?: LocalInstanceResources,
|
|
618
|
+
env?: Record<string, string | undefined>,
|
|
619
|
+
): string {
|
|
620
|
+
const securityDir = resources
|
|
621
|
+
? join(resources.instanceDir, ".vellum", "protected")
|
|
622
|
+
: env?.CREDENTIAL_SECURITY_DIR?.trim() ||
|
|
623
|
+
join(homedir(), ".vellum", "protected");
|
|
624
|
+
return join(securityDir, "credential-executor");
|
|
625
|
+
}
|
|
626
|
+
|
|
609
627
|
/**
|
|
610
628
|
* Apply per-instance resource overrides and shared daemon options to an
|
|
611
629
|
* environment object. Called from all daemon spawn paths (source, watch,
|
|
@@ -644,11 +662,10 @@ function applyDaemonEnvOverrides(
|
|
|
644
662
|
env.VELLUM_DEFAULT_WORKSPACE_CONFIG_PATH =
|
|
645
663
|
options.defaultWorkspaceConfigPath;
|
|
646
664
|
}
|
|
647
|
-
//
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
env.CES_LOCAL_SOCKET = resolveCesSocketPath(resources);
|
|
665
|
+
// CES and the assistant resolve the socket from CES_BOOTSTRAP_SOCKET_DIR.
|
|
666
|
+
const bootstrapDir = resolveCesBootstrapSocketDir(resources, env);
|
|
667
|
+
env.CES_BOOTSTRAP_SOCKET_DIR = bootstrapDir;
|
|
668
|
+
mkdirSync(bootstrapDir, { recursive: true });
|
|
652
669
|
applyIpcSocketDirOverride(env);
|
|
653
670
|
}
|
|
654
671
|
|
|
@@ -1022,26 +1039,18 @@ function resolveCesDir(resources?: LocalInstanceResources): string {
|
|
|
1022
1039
|
|
|
1023
1040
|
/**
|
|
1024
1041
|
* Resolve the local IPC endpoint shared by the CLI-launched CES sibling and
|
|
1025
|
-
* assistant.
|
|
1026
|
-
*
|
|
1042
|
+
* assistant. CES binds this path from `CES_BOOTSTRAP_SOCKET_DIR` via the same
|
|
1043
|
+
* `resolveIpcEndpoint("ces")` helper. Windows uses a named pipe. POSIX uses
|
|
1044
|
+
* a Unix socket, including the shared macOS AF_UNIX fallback.
|
|
1027
1045
|
*/
|
|
1028
1046
|
export function resolveCesSocketPath(
|
|
1029
1047
|
resources?: LocalInstanceResources,
|
|
1030
1048
|
hostPlatform: NodeJS.Platform = platform(),
|
|
1031
1049
|
): string {
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
:
|
|
1035
|
-
|
|
1036
|
-
return resolveIpcEndpoint("ces", {
|
|
1037
|
-
workspaceDir,
|
|
1038
|
-
platform: hostPlatform,
|
|
1039
|
-
}).path;
|
|
1040
|
-
}
|
|
1041
|
-
const override = computeIpcSocketDirOverride(workspaceDir);
|
|
1042
|
-
const socketDir = override ?? workspaceDir;
|
|
1043
|
-
mkdirSync(socketDir, { recursive: true });
|
|
1044
|
-
return join(socketDir, "ces.sock");
|
|
1050
|
+
return resolveIpcEndpoint("ces", {
|
|
1051
|
+
workspaceDir: resolveCesBootstrapSocketDir(resources),
|
|
1052
|
+
platform: hostPlatform,
|
|
1053
|
+
}).path;
|
|
1045
1054
|
}
|
|
1046
1055
|
|
|
1047
1056
|
async function isIpcEndpointReady(endpointPath: string): Promise<boolean> {
|
|
@@ -1101,13 +1110,15 @@ export async function startCes(
|
|
|
1101
1110
|
const workspaceDir = resources
|
|
1102
1111
|
? join(resources.instanceDir, ".vellum", "workspace")
|
|
1103
1112
|
: join(homedir(), ".vellum", "workspace");
|
|
1113
|
+
const bootstrapDir = resolveCesBootstrapSocketDir(resources);
|
|
1104
1114
|
mkdirSync(securityDir, { recursive: true });
|
|
1115
|
+
mkdirSync(bootstrapDir, { recursive: true });
|
|
1105
1116
|
|
|
1106
1117
|
const cesEnv: Record<string, string | undefined> = {
|
|
1107
1118
|
...process.env,
|
|
1108
|
-
CES_LOCAL_SOCKET: socketPath,
|
|
1109
1119
|
CREDENTIAL_SECURITY_DIR: securityDir,
|
|
1110
1120
|
VELLUM_WORKSPACE_DIR: workspaceDir,
|
|
1121
|
+
CES_BOOTSTRAP_SOCKET_DIR: bootstrapDir,
|
|
1111
1122
|
};
|
|
1112
1123
|
|
|
1113
1124
|
let ces;
|
|
@@ -528,20 +528,8 @@ export async function injectCredentialsIntoAssistant(
|
|
|
528
528
|
promises.push(inject("vellum:assistant_api_key", params.assistantApiKey));
|
|
529
529
|
}
|
|
530
530
|
|
|
531
|
-
promises.push(
|
|
532
|
-
inject("vellum:platform_assistant_id", params.platformAssistantId),
|
|
533
|
-
);
|
|
534
|
-
|
|
535
531
|
promises.push(inject("vellum:platform_base_url", params.platformBaseUrl));
|
|
536
532
|
|
|
537
|
-
promises.push(
|
|
538
|
-
inject("vellum:platform_organization_id", params.organizationId),
|
|
539
|
-
);
|
|
540
|
-
|
|
541
|
-
if (params.userId) {
|
|
542
|
-
promises.push(inject("vellum:platform_user_id", params.userId));
|
|
543
|
-
}
|
|
544
|
-
|
|
545
533
|
if (params.webhookSecret) {
|
|
546
534
|
promises.push(inject("vellum:webhook_secret", params.webhookSecret));
|
|
547
535
|
}
|
|
@@ -77,6 +77,7 @@ const PROVIDER_LABELS: Record<LlmProviderId, string> = {
|
|
|
77
77
|
opencode: "OpenCode",
|
|
78
78
|
baseten: "Baseten",
|
|
79
79
|
poolside: "Poolside",
|
|
80
|
+
jev: "Jev",
|
|
80
81
|
};
|
|
81
82
|
|
|
82
83
|
// litellm and opencode are deliberately excluded: they have no fixed default
|
|
@@ -246,6 +247,9 @@ export function inferProviderFromModel(model: string): string | undefined {
|
|
|
246
247
|
if (model.startsWith("poolside/")) {
|
|
247
248
|
return "poolside";
|
|
248
249
|
}
|
|
250
|
+
if (model === "jev-latest" || model.startsWith("jev-")) {
|
|
251
|
+
return "jev";
|
|
252
|
+
}
|
|
249
253
|
if (model === "qwen/qwen3-8b") {
|
|
250
254
|
// The only qwen/* ID the Vellum hosted provider carries; the rest are
|
|
251
255
|
// OpenRouter's.
|
package/src/lib/statefulset.ts
CHANGED
|
@@ -187,6 +187,7 @@ export const DOCKER_STATEFUL_SET_SPEC: DockerStatefulSetSpec = {
|
|
|
187
187
|
{ kind: "static", name: "VELLUM_BACKUP_DIR", value: "/workspace/.backups" },
|
|
188
188
|
{ kind: "static", name: "VELLUM_BACKUP_KEY_PATH", value: "/workspace/.backup.key" },
|
|
189
189
|
{ kind: "static", name: "CES_CREDENTIAL_URL", value: "http://localhost:8090" },
|
|
190
|
+
{ kind: "static", name: "CES_BOOTSTRAP_SOCKET_DIR", value: "/run/ces-bootstrap" },
|
|
190
191
|
{ kind: "static", name: "GATEWAY_IPC_SOCKET_DIR", value: "/run/gateway-ipc" },
|
|
191
192
|
{ kind: "static", name: "ASSISTANT_IPC_SOCKET_DIR", value: "/run/assistant-ipc" },
|
|
192
193
|
{ kind: "secret", name: "CES_SERVICE_TOKEN", secret: "cesServiceToken" },
|
|
@@ -34,6 +34,7 @@ export const LLM_PROVIDER_ENV_VAR_NAMES: Record<string, string> = {
|
|
|
34
34
|
opencode: "OPENCODE_API_KEY",
|
|
35
35
|
baseten: "BASETEN_API_KEY",
|
|
36
36
|
poolside: "POOLSIDE_API_KEY",
|
|
37
|
+
jev: "TYPESAFE_API_KEY",
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
/** Search-provider env var names. Mirrors `SEARCH_PROVIDER_CATALOG` BYOK entries. */
|