traicebox 0.1.12 → 0.1.14
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/README.md +6 -5
- package/dist/{compose-bfc4a606.yml → compose-r1mahfqb.yml} +1 -1
- package/dist/index.js +90 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
## Prerequisites
|
|
19
19
|
|
|
20
|
-
Traicebox requires [Docker](https://www.docker.com/)
|
|
20
|
+
Traicebox requires either [Docker](https://www.docker.com/) with Docker Compose or [Podman](https://podman.io/) with Podman Compose to be installed and running on your system.
|
|
21
21
|
|
|
22
22
|
## Installation
|
|
23
23
|
|
|
@@ -219,10 +219,11 @@ By default, it is located at:
|
|
|
219
219
|
|
|
220
220
|
You can customize the stack behavior by creating or editing `${TRAICEBOX_HOME}/traicebox.yaml`.
|
|
221
221
|
|
|
222
|
-
| Option
|
|
223
|
-
|
|
|
224
|
-
| `host`
|
|
225
|
-
| `port`
|
|
222
|
+
| Option | Type | Default | Description |
|
|
223
|
+
| :-------- | :------- | :---------- | :------------------------------------------------------------------------------- |
|
|
224
|
+
| `host` | `string` | `127.0.0.1` | The host address that Traicebox services will bind to. |
|
|
225
|
+
| `port` | `number` | `5483` | The port that Traicebox services will be accessible through. |
|
|
226
|
+
| `runtime` | `string` | auto-detect | Optional. Force Traicebox to use `docker` or `podman` instead of auto-detecting. |
|
|
226
227
|
|
|
227
228
|
Example:
|
|
228
229
|
|
|
@@ -137,7 +137,7 @@ services:
|
|
|
137
137
|
LANGFUSE_INIT_USER_NAME: ${LANGFUSE_INIT_USER_NAME}
|
|
138
138
|
LANGFUSE_INIT_USER_PASSWORD: ${LANGFUSE_INIT_USER_PASSWORD}
|
|
139
139
|
healthcheck:
|
|
140
|
-
test: ["CMD", "node", "-e", "const
|
|
140
|
+
test: ["CMD", "node", "-e", "const { hostname } = require('node:os'); fetch('http://' + hostname() + ':3000/api/auth/csrf').then(async (r) => { const ok = r.ok && (await r.text()).includes('csrfToken'); process.exit(ok ? 0 : 1); }).catch(() => process.exit(1))"]
|
|
141
141
|
interval: 5s
|
|
142
142
|
timeout: 5s
|
|
143
143
|
retries: 24
|
package/dist/index.js
CHANGED
|
@@ -12894,32 +12894,73 @@ var LANGFUSE_HOST = "langfuse.localhost";
|
|
|
12894
12894
|
|
|
12895
12895
|
// cli/lib/docker.ts
|
|
12896
12896
|
import { spawn } from "node:child_process";
|
|
12897
|
-
|
|
12898
|
-
|
|
12899
|
-
|
|
12900
|
-
|
|
12901
|
-
|
|
12902
|
-
|
|
12903
|
-
|
|
12904
|
-
|
|
12905
|
-
|
|
12906
|
-
|
|
12907
|
-
|
|
12908
|
-
|
|
12909
|
-
|
|
12910
|
-
|
|
12897
|
+
var SUPPORTED_CONTAINER_RUNTIME_COMMANDS = [
|
|
12898
|
+
"docker",
|
|
12899
|
+
"podman"
|
|
12900
|
+
];
|
|
12901
|
+
var SUPPORTED_RUNTIMES = [
|
|
12902
|
+
{ command: "docker" },
|
|
12903
|
+
{ command: "podman" }
|
|
12904
|
+
];
|
|
12905
|
+
async function ensureDockerReady(executor = executeCommand, preferredRuntime) {
|
|
12906
|
+
if (preferredRuntime) {
|
|
12907
|
+
return ensurePreferredRuntimeReady(preferredRuntime, executor);
|
|
12908
|
+
}
|
|
12909
|
+
let sawInstalledRuntime = false;
|
|
12910
|
+
let sawComposeCommand = false;
|
|
12911
|
+
for (const runtime of SUPPORTED_RUNTIMES) {
|
|
12912
|
+
const composeResult = await executor([
|
|
12913
|
+
runtime.command,
|
|
12914
|
+
"compose",
|
|
12915
|
+
"version"
|
|
12916
|
+
]);
|
|
12917
|
+
if (composeResult.errorCode === "ENOENT") {
|
|
12918
|
+
continue;
|
|
12919
|
+
}
|
|
12920
|
+
sawInstalledRuntime = true;
|
|
12921
|
+
if (composeResult.exitCode !== 0) {
|
|
12922
|
+
continue;
|
|
12923
|
+
}
|
|
12924
|
+
sawComposeCommand = true;
|
|
12925
|
+
const engineResult = await executor(getEngineProbeCommand(runtime.command));
|
|
12926
|
+
if (engineResult.exitCode === 0) {
|
|
12927
|
+
return runtime;
|
|
12928
|
+
}
|
|
12911
12929
|
}
|
|
12912
|
-
if (
|
|
12913
|
-
throw new Error("Docker
|
|
12930
|
+
if (!sawInstalledRuntime) {
|
|
12931
|
+
throw new Error("Neither Docker nor Podman CLI is available. Install one and try again.");
|
|
12914
12932
|
}
|
|
12933
|
+
if (!sawComposeCommand) {
|
|
12934
|
+
throw new Error("Neither Docker Compose nor Podman Compose is available. Check your installation and try again.");
|
|
12935
|
+
}
|
|
12936
|
+
throw new Error("Docker or Podman is installed but the engine is not reachable. Start it and try again.");
|
|
12915
12937
|
}
|
|
12916
|
-
function
|
|
12917
|
-
|
|
12918
|
-
|
|
12938
|
+
async function ensurePreferredRuntimeReady(preferredRuntime, executor) {
|
|
12939
|
+
const composeResult = await executor([
|
|
12940
|
+
preferredRuntime,
|
|
12941
|
+
"compose",
|
|
12942
|
+
"version"
|
|
12943
|
+
]);
|
|
12944
|
+
if (composeResult.errorCode === "ENOENT") {
|
|
12945
|
+
throw new Error(`${displayRuntimeName(preferredRuntime)} CLI is not available. Install ${displayRuntimeName(preferredRuntime)} and try again.`);
|
|
12946
|
+
}
|
|
12947
|
+
if (composeResult.exitCode !== 0) {
|
|
12948
|
+
throw new Error(`${displayRuntimeName(preferredRuntime)} Compose is not available. Check your ${displayRuntimeName(preferredRuntime)} installation and try again.`);
|
|
12919
12949
|
}
|
|
12920
|
-
|
|
12921
|
-
|
|
12950
|
+
const engineResult = await executor(getEngineProbeCommand(preferredRuntime));
|
|
12951
|
+
if (engineResult.errorCode === "ENOENT") {
|
|
12952
|
+
throw new Error(`${displayRuntimeName(preferredRuntime)} CLI is not available. Install ${displayRuntimeName(preferredRuntime)} and try again.`);
|
|
12922
12953
|
}
|
|
12954
|
+
if (engineResult.exitCode !== 0) {
|
|
12955
|
+
throw new Error(`${displayRuntimeName(preferredRuntime)} is installed but the engine is not reachable. Start ${displayRuntimeName(preferredRuntime)} and try again.`);
|
|
12956
|
+
}
|
|
12957
|
+
return { command: preferredRuntime };
|
|
12958
|
+
}
|
|
12959
|
+
function displayRuntimeName(runtime) {
|
|
12960
|
+
return runtime === "docker" ? "Docker" : "Podman";
|
|
12961
|
+
}
|
|
12962
|
+
function getEngineProbeCommand(runtime) {
|
|
12963
|
+
return runtime === "docker" ? [runtime, "info", "--format", "{{.ServerVersion}}"] : [runtime, "info"];
|
|
12923
12964
|
}
|
|
12924
12965
|
async function executeCommand(command2) {
|
|
12925
12966
|
try {
|
|
@@ -13053,6 +13094,7 @@ function initializeRuntime() {
|
|
|
13053
13094
|
xdgConfigHome: env2.XDG_CONFIG_HOME
|
|
13054
13095
|
});
|
|
13055
13096
|
const configPath = join2(resolvedHome.home, "traicebox.yaml");
|
|
13097
|
+
let containerRuntime;
|
|
13056
13098
|
if (existsSync2(configPath)) {
|
|
13057
13099
|
try {
|
|
13058
13100
|
const configObj = import_yaml2.default.parse(readFileSync4(configPath, "utf-8"));
|
|
@@ -13063,6 +13105,7 @@ function initializeRuntime() {
|
|
|
13063
13105
|
if (!env2.TRAICEBOX_PORT && (typeof configObj.port === "string" || typeof configObj.port === "number")) {
|
|
13064
13106
|
env2.TRAICEBOX_PORT = String(configObj.port);
|
|
13065
13107
|
}
|
|
13108
|
+
containerRuntime = resolveConfiguredContainerRuntime(configObj.runtime);
|
|
13066
13109
|
}
|
|
13067
13110
|
} catch {
|
|
13068
13111
|
fail(`Failed to parse config file: ${configPath}`);
|
|
@@ -13071,7 +13114,8 @@ function initializeRuntime() {
|
|
|
13071
13114
|
runtimeContext = {
|
|
13072
13115
|
home: resolvedHome.home,
|
|
13073
13116
|
dev: resolvedHome.dev,
|
|
13074
|
-
stackEnv: resolveStackEnv(env2)
|
|
13117
|
+
stackEnv: resolveStackEnv(env2),
|
|
13118
|
+
containerRuntime
|
|
13075
13119
|
};
|
|
13076
13120
|
return runtimeContext;
|
|
13077
13121
|
}
|
|
@@ -13130,6 +13174,15 @@ function isTruthy(value) {
|
|
|
13130
13174
|
function toAbsolutePath(cwd, value) {
|
|
13131
13175
|
return isAbsolute(value) ? value : join2(cwd, value);
|
|
13132
13176
|
}
|
|
13177
|
+
function resolveConfiguredContainerRuntime(value) {
|
|
13178
|
+
if (value == null) {
|
|
13179
|
+
return;
|
|
13180
|
+
}
|
|
13181
|
+
if (typeof value === "string" && SUPPORTED_CONTAINER_RUNTIME_COMMANDS.includes(value)) {
|
|
13182
|
+
return value;
|
|
13183
|
+
}
|
|
13184
|
+
throw new Error("Invalid runtime in traicebox.yaml. Expected 'docker' or 'podman'.");
|
|
13185
|
+
}
|
|
13133
13186
|
|
|
13134
13187
|
// cli/handlers/docker-lifecycle.ts
|
|
13135
13188
|
var TMPDIR = process.env.TMPDIR ?? "/tmp";
|
|
@@ -13218,7 +13271,7 @@ function cleanupOpenAICompatibleApiKeySecretMaterialSync() {
|
|
|
13218
13271
|
activeSecretDirectory = null;
|
|
13219
13272
|
}
|
|
13220
13273
|
}
|
|
13221
|
-
async function
|
|
13274
|
+
async function runDockerComposeWithRuntime(containerRuntime, args, logs) {
|
|
13222
13275
|
const runtime = getRuntime();
|
|
13223
13276
|
const env2 = {
|
|
13224
13277
|
...process.env,
|
|
@@ -13226,7 +13279,7 @@ async function runDockerCompose(args, logs) {
|
|
|
13226
13279
|
[SECRET_FILE_ENV]: prepareOpenAICompatibleApiKeySecretFile()
|
|
13227
13280
|
};
|
|
13228
13281
|
try {
|
|
13229
|
-
const proc = spawn2(
|
|
13282
|
+
const proc = spawn2(containerRuntime.command, ["compose", ...args], {
|
|
13230
13283
|
cwd: runtime.home,
|
|
13231
13284
|
env: env2,
|
|
13232
13285
|
stdio: [
|
|
@@ -13258,7 +13311,7 @@ async function runDockerCompose(args, logs) {
|
|
|
13258
13311
|
if (stderr.trim()) {
|
|
13259
13312
|
process.stderr.write(stderr);
|
|
13260
13313
|
}
|
|
13261
|
-
fail(
|
|
13314
|
+
fail(`${containerRuntime.command} compose ${args.join(" ")} failed with exit code ${exitCode}`);
|
|
13262
13315
|
}
|
|
13263
13316
|
} finally {
|
|
13264
13317
|
activeDockerComposeProcess = null;
|
|
@@ -13299,7 +13352,8 @@ function installDockerLifecycleSignalHandlers() {
|
|
|
13299
13352
|
}
|
|
13300
13353
|
async function runStackCommand(command2, logs) {
|
|
13301
13354
|
ensureActiveHomeExists();
|
|
13302
|
-
|
|
13355
|
+
const runtime = getRuntime();
|
|
13356
|
+
const containerRuntime = await ensureDockerReady(undefined, runtime.containerRuntime).catch((error) => {
|
|
13303
13357
|
fail(error instanceof Error ? error.message : String(error));
|
|
13304
13358
|
});
|
|
13305
13359
|
if (command2 === "start" || command2 === "restart") {
|
|
@@ -13318,17 +13372,17 @@ async function runStackCommand(command2, logs) {
|
|
|
13318
13372
|
...LONG_RUNNING_SERVICES
|
|
13319
13373
|
] : ["up", "-d", "--remove-orphans", "--wait", ...LONG_RUNNING_SERVICES];
|
|
13320
13374
|
await runStep("Starting stack", logs, async () => {
|
|
13321
|
-
await
|
|
13375
|
+
await runDockerComposeWithRuntime(containerRuntime, upArgs, logs);
|
|
13322
13376
|
});
|
|
13323
13377
|
await runStep("Bootstrapping LiteLLM", logs, async () => {
|
|
13324
|
-
await
|
|
13378
|
+
await runDockerComposeWithRuntime(containerRuntime, ["run", "--rm", "--no-deps", "litellm-bootstrap"], logs);
|
|
13325
13379
|
});
|
|
13326
13380
|
printAccessInfo(command2);
|
|
13327
13381
|
return;
|
|
13328
13382
|
}
|
|
13329
13383
|
const downArgs = command2 === "stop" ? ["stop"] : ["down", "--remove-orphans", "--volumes"];
|
|
13330
13384
|
await runStep(command2 === "stop" ? "Stopping stack" : "Destroying stack", logs, async () => {
|
|
13331
|
-
await
|
|
13385
|
+
await runDockerComposeWithRuntime(containerRuntime, downArgs, logs);
|
|
13332
13386
|
});
|
|
13333
13387
|
}
|
|
13334
13388
|
|
|
@@ -13464,7 +13518,7 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
|
13464
13518
|
var Caddyfile_default = "./Caddyfile-at2nzhxs.";
|
|
13465
13519
|
|
|
13466
13520
|
// template/compose.yml
|
|
13467
|
-
var compose_default = "./compose-
|
|
13521
|
+
var compose_default = "./compose-r1mahfqb.yml";
|
|
13468
13522
|
|
|
13469
13523
|
// template/langfuse-proxy/Dockerfile
|
|
13470
13524
|
var Dockerfile_default = "./Dockerfile-bzexf8bh.";
|
|
@@ -13565,10 +13619,10 @@ async function writeDevelopmentDotenv(home, stackEnv) {
|
|
|
13565
13619
|
|
|
13566
13620
|
// cli/handlers/setup.ts
|
|
13567
13621
|
async function runSetup(force = false) {
|
|
13568
|
-
|
|
13622
|
+
const runtime = getRuntime();
|
|
13623
|
+
await ensureDockerReady(undefined, runtime.containerRuntime).catch((error) => {
|
|
13569
13624
|
fail(error instanceof Error ? error.message : String(error));
|
|
13570
13625
|
});
|
|
13571
|
-
const runtime = getRuntime();
|
|
13572
13626
|
if (force) {
|
|
13573
13627
|
rmSync2(runtime.home, { recursive: true, force: true });
|
|
13574
13628
|
}
|
|
@@ -13603,28 +13657,28 @@ await yargs_default(hideBin(process.argv)).scriptName("traicebox").command("setu
|
|
|
13603
13657
|
alias: "l",
|
|
13604
13658
|
type: "boolean",
|
|
13605
13659
|
default: false,
|
|
13606
|
-
describe: "Show
|
|
13660
|
+
describe: "Show compose output while starting"
|
|
13607
13661
|
}), async (argv) => {
|
|
13608
13662
|
await runStackCommand("start", argv.logs);
|
|
13609
13663
|
}).command("stop", "Stop the stack", (cmd) => cmd.option("logs", {
|
|
13610
13664
|
alias: "l",
|
|
13611
13665
|
type: "boolean",
|
|
13612
13666
|
default: false,
|
|
13613
|
-
describe: "Show
|
|
13667
|
+
describe: "Show compose output while stopping"
|
|
13614
13668
|
}), async (argv) => {
|
|
13615
13669
|
await runStackCommand("stop", argv.logs);
|
|
13616
13670
|
}).command("restart", "Recreate the stack and wait until it is ready", (cmd) => cmd.option("logs", {
|
|
13617
13671
|
alias: "l",
|
|
13618
13672
|
type: "boolean",
|
|
13619
13673
|
default: false,
|
|
13620
|
-
describe: "Show
|
|
13674
|
+
describe: "Show compose output while restarting"
|
|
13621
13675
|
}), async (argv) => {
|
|
13622
13676
|
await runStackCommand("restart", argv.logs);
|
|
13623
13677
|
}).command("destroy", "Remove the stack and local data volumes", (cmd) => cmd.option("logs", {
|
|
13624
13678
|
alias: "l",
|
|
13625
13679
|
type: "boolean",
|
|
13626
13680
|
default: false,
|
|
13627
|
-
describe: "Show
|
|
13681
|
+
describe: "Show compose output while destroying"
|
|
13628
13682
|
}), async (argv) => {
|
|
13629
13683
|
await runStackCommand("destroy", argv.logs);
|
|
13630
13684
|
}).command("models <command>", "Manage imported LiteLLM models", (cmd) => cmd.command("import-from-openai-api", "Import models from an OpenAI-compatible endpoint into LiteLLM config", (subcmd) => subcmd.option("endpoint", {
|
package/package.json
CHANGED