@tuned-tensor/cli 0.13.1-beta.7 → 0.14.0
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 +46 -19
- package/dist/{chunk-AKJ5WZ2S.js → chunk-VRDDO2FP.js} +2407 -2387
- package/dist/chunk-VRDDO2FP.js.map +1 -0
- package/dist/index.js +766 -301
- package/dist/index.js.map +1 -1
- package/dist/local-runtime.js +120 -25
- package/dist/local-runtime.js.map +1 -1
- package/docs/local-runtime/architecture.md +2 -2
- package/docs/local-runtime/serving.md +168 -0
- package/docs/local-runtime/spark.md +1 -1
- package/package.json +3 -1
- package/training/adapter/src/serve.py +133 -267
- package/training/serving/pyproject.toml +9 -0
- package/training/serving/uv.lock +2785 -0
- package/dist/chunk-AKJ5WZ2S.js.map +0 -1
package/dist/local-runtime.js
CHANGED
|
@@ -55,7 +55,10 @@ import {
|
|
|
55
55
|
localStorePaths,
|
|
56
56
|
minimalMachineLearningEnvironment,
|
|
57
57
|
normalizeChatJsonlForRelocation,
|
|
58
|
+
parseLocalRunInput,
|
|
59
|
+
parseLocalRunnerConfig,
|
|
58
60
|
prefetchBaseModel,
|
|
61
|
+
pythonEnvironmentPath,
|
|
59
62
|
reportInBackground,
|
|
60
63
|
resolveLocalRunInputPaths,
|
|
61
64
|
resolveModelLoader,
|
|
@@ -78,13 +81,13 @@ import {
|
|
|
78
81
|
withHuggingFaceCacheEnvironment,
|
|
79
82
|
withOfflineHuggingFaceCacheEnvironment,
|
|
80
83
|
writePrivateJsonAtomic
|
|
81
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-VRDDO2FP.js";
|
|
82
85
|
|
|
83
86
|
// src/local-runtime/index.ts
|
|
84
|
-
import { readFileSync, realpathSync } from "fs";
|
|
85
|
-
import { createHash } from "crypto";
|
|
87
|
+
import { readFileSync as readFileSync2, realpathSync } from "fs";
|
|
88
|
+
import { createHash as createHash2 } from "crypto";
|
|
86
89
|
import { readFile as readFile2, stat } from "fs/promises";
|
|
87
|
-
import { basename, dirname, join as
|
|
90
|
+
import { basename, dirname, join as join4, resolve as resolve3 } from "path";
|
|
88
91
|
import { cwd } from "process";
|
|
89
92
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
90
93
|
|
|
@@ -503,6 +506,39 @@ async function runDoctor(config, request, foundationSpec) {
|
|
|
503
506
|
import { spawn as spawn2 } from "child_process";
|
|
504
507
|
import { resolve as resolve2 } from "path";
|
|
505
508
|
import { fileURLToPath } from "url";
|
|
509
|
+
|
|
510
|
+
// src/local-runtime/serving-runtime.ts
|
|
511
|
+
import { createHash } from "crypto";
|
|
512
|
+
import { readFileSync } from "fs";
|
|
513
|
+
import { join as join2 } from "path";
|
|
514
|
+
var root = localRuntimePackageRoot(import.meta.url);
|
|
515
|
+
var project = join2(root, "training/serving");
|
|
516
|
+
var hash = createHash("sha256");
|
|
517
|
+
for (const name of ["pyproject.toml", "uv.lock"]) hash.update(readFileSync(join2(project, name)));
|
|
518
|
+
var SERVING_PYTHON_ENVIRONMENT = pythonEnvironmentPath("uv-serving", hash.digest("hex").slice(0, 20));
|
|
519
|
+
function buildServingPythonCommand() {
|
|
520
|
+
const commandArgs = [
|
|
521
|
+
"run",
|
|
522
|
+
"--frozen",
|
|
523
|
+
"--quiet",
|
|
524
|
+
"--project",
|
|
525
|
+
project,
|
|
526
|
+
"python",
|
|
527
|
+
join2(root, "training/adapter/src/serve.py")
|
|
528
|
+
];
|
|
529
|
+
return { command: "uv", commandArgs, displayCommand: ["uv", ...commandArgs] };
|
|
530
|
+
}
|
|
531
|
+
function withServingPythonEnvironment(env) {
|
|
532
|
+
return {
|
|
533
|
+
...env,
|
|
534
|
+
UV_PROJECT_ENVIRONMENT: SERVING_PYTHON_ENVIRONMENT,
|
|
535
|
+
VLLM_NO_USAGE_STATS: "1",
|
|
536
|
+
DO_NOT_TRACK: "1",
|
|
537
|
+
VLLM_ALLOW_RUNTIME_LORA_UPDATING: "0"
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// src/local-runtime/model-server.ts
|
|
506
542
|
function localArtifactPath(uri) {
|
|
507
543
|
if (uri.startsWith("file://")) return fileURLToPath(uri);
|
|
508
544
|
if (/^[a-z][a-z0-9+.-]*:/i.test(uri)) {
|
|
@@ -524,6 +560,10 @@ function httpHost(host) {
|
|
|
524
560
|
}
|
|
525
561
|
function buildModelServerLaunch(args) {
|
|
526
562
|
const options = args.options ?? {};
|
|
563
|
+
const device = options.device ?? args.config.evaluation.inference.device;
|
|
564
|
+
if (device !== "cuda") throw new Error("The pinned vLLM serving runtime requires CUDA; CPU serving is not supported.");
|
|
565
|
+
const contextLength = boundedNumber("contextLength", options.contextLength ?? 16384, 512, 131072, true);
|
|
566
|
+
const gpuMemoryUtilization = boundedNumber("gpuMemoryUtilization", options.gpuMemoryUtilization ?? 0.8, 0.05, 0.95);
|
|
527
567
|
const host = options.host ?? "127.0.0.1";
|
|
528
568
|
const remote = !isLoopbackHost(host);
|
|
529
569
|
if (remote && !options.allowRemote) {
|
|
@@ -559,8 +599,8 @@ function buildModelServerLaunch(args) {
|
|
|
559
599
|
options.baseModelRevision
|
|
560
600
|
);
|
|
561
601
|
const baseModelRevision = localBaseModelPath ? defaultBaseModelRevision(args.baseModel) : requestedBaseModelRevision;
|
|
562
|
-
const entrypoint =
|
|
563
|
-
const env =
|
|
602
|
+
const entrypoint = buildServingPythonCommand();
|
|
603
|
+
const env = withServingPythonEnvironment(
|
|
564
604
|
withOfflineHuggingFaceCacheEnvironment({
|
|
565
605
|
...minimalMachineLearningEnvironment(process.env),
|
|
566
606
|
...artifactPath ? { TT_MODEL_ARTIFACT: artifactPath } : {},
|
|
@@ -568,10 +608,12 @@ function buildModelServerLaunch(args) {
|
|
|
568
608
|
...localBaseModelPath ? { TT_MODEL_SOURCE: localBaseModelPath } : {},
|
|
569
609
|
...baseModelRevision ? { TT_BASE_MODEL_REVISION: baseModelRevision } : {},
|
|
570
610
|
TT_MODEL_NAME: args.modelName,
|
|
611
|
+
TT_CONTEXT_LENGTH: String(contextLength),
|
|
612
|
+
TT_GPU_MEMORY_UTILIZATION: String(gpuMemoryUtilization),
|
|
571
613
|
TT_MODEL_LOADER: resolveModelLoader(args.baseModel),
|
|
572
614
|
TT_HOST: host,
|
|
573
615
|
TT_PORT: String(port),
|
|
574
|
-
TT_DEVICE:
|
|
616
|
+
TT_DEVICE: device,
|
|
575
617
|
TT_MAX_TOKENS: String(maxTokens),
|
|
576
618
|
TT_TEMPERATURE: String(temperature),
|
|
577
619
|
TT_TOP_P: String(topP),
|
|
@@ -616,6 +658,7 @@ async function verifyLocalModelServerLaunch(launch) {
|
|
|
616
658
|
}
|
|
617
659
|
}
|
|
618
660
|
async function serveLocalModel(launch) {
|
|
661
|
+
if (process.platform !== "linux") throw new Error("Local vLLM serving requires Linux and an NVIDIA CUDA GPU.");
|
|
619
662
|
await verifyLocalModelServerLaunch(launch);
|
|
620
663
|
await new Promise((resolveServer, reject) => {
|
|
621
664
|
const child = spawn2(launch.command, launch.commandArgs, {
|
|
@@ -671,12 +714,12 @@ async function serveLocalModel(launch) {
|
|
|
671
714
|
// src/local-runtime/active-model.ts
|
|
672
715
|
import { randomUUID } from "crypto";
|
|
673
716
|
import { appendFile, chmod, readFile, rename, writeFile as writeFile2 } from "fs/promises";
|
|
674
|
-
import { join as
|
|
717
|
+
import { join as join3 } from "path";
|
|
675
718
|
function pointerPath(store) {
|
|
676
|
-
return
|
|
719
|
+
return join3(store.root, "active-model.json");
|
|
677
720
|
}
|
|
678
721
|
function historyPath(store) {
|
|
679
|
-
return
|
|
722
|
+
return join3(store.root, "activation-history.jsonl");
|
|
680
723
|
}
|
|
681
724
|
async function readPointer(store) {
|
|
682
725
|
if (!await hardenExistingLocalStore(store.root)) return null;
|
|
@@ -716,7 +759,7 @@ async function assertModelCanActivate(store, modelId) {
|
|
|
716
759
|
throw new Error(`Model ${model.id} belongs to run ${run.id}, which is not completed.`);
|
|
717
760
|
}
|
|
718
761
|
const report = runReportSchema.parse(
|
|
719
|
-
JSON.parse(await readFile(
|
|
762
|
+
JSON.parse(await readFile(join3(model.artifact_dir, "run-report.json"), "utf8"))
|
|
720
763
|
);
|
|
721
764
|
if (!report.general_regression) {
|
|
722
765
|
throw new Error(`Model ${model.id} has no general regression evaluation.`);
|
|
@@ -773,7 +816,7 @@ async function rollbackActiveModel(store) {
|
|
|
773
816
|
function packageVersion() {
|
|
774
817
|
try {
|
|
775
818
|
const packageJson = JSON.parse(
|
|
776
|
-
|
|
819
|
+
readFileSync2(resolve3(localRuntimePackageRoot(import.meta.url), "package.json"), "utf8")
|
|
777
820
|
);
|
|
778
821
|
return typeof packageJson.version === "string" ? packageJson.version : "unknown";
|
|
779
822
|
} catch {
|
|
@@ -828,16 +871,19 @@ var MODEL_SERVE_OPTIONS = [
|
|
|
828
871
|
CONFIG_OPTION,
|
|
829
872
|
{ name: "--host", value: "host", description: "Bind host (localhost by default)" },
|
|
830
873
|
{ name: "--port", value: "port", description: "Bind port" },
|
|
831
|
-
{ name: "--device", value: "device", description: "cuda
|
|
874
|
+
{ name: "--device", value: "device", description: "cuda (pinned vLLM runtime)" },
|
|
832
875
|
{ name: "--max-tokens", value: "count", description: "Default response token limit" },
|
|
833
876
|
{ name: "--temperature", value: "number", description: "Default sampling temperature" },
|
|
834
877
|
{ name: "--top-p", value: "number", description: "Default nucleus sampling threshold" },
|
|
835
|
-
{ name: "--max-concurrent-requests", value: "count", description: "
|
|
878
|
+
{ name: "--max-concurrent-requests", value: "count", description: "Maximum sequences in an upstream generation batch" },
|
|
879
|
+
{ name: "--context-length", value: "count", description: "Total context token budget (default 16384)" },
|
|
880
|
+
{ name: "--gpu-memory-utilization", value: "fraction", description: "vLLM GPU memory budget fraction (default 0.8)" },
|
|
836
881
|
{ name: "--spec", value: "path", description: "Behavior spec whose instructions are enforced" },
|
|
837
882
|
{ name: "--no-spec-prompt", description: "Do not enforce the stored behavior-spec prompt" },
|
|
838
883
|
{ name: "--allow-remote", description: "Allow a non-loopback bind" },
|
|
839
884
|
{ name: "--api-key-env", value: "name", description: "Environment variable containing a bearer token" },
|
|
840
|
-
{ name: "--print-command", description: "Validate and print the launch plan without starting" }
|
|
885
|
+
{ name: "--print-command", description: "Validate and print the launch plan without starting" },
|
|
886
|
+
{ name: "--print-client-config", value: "client", description: "Print Pi models.json; does not start serving" }
|
|
841
887
|
];
|
|
842
888
|
var COMMAND_DEFINITIONS = {
|
|
843
889
|
info: {
|
|
@@ -1100,7 +1146,7 @@ function readNumberOption(argv, name) {
|
|
|
1100
1146
|
async function selectedConfigPath(argv, adjacentTo) {
|
|
1101
1147
|
const explicitPath = readOption(argv, "--config");
|
|
1102
1148
|
if (explicitPath) return resolve3(explicitPath);
|
|
1103
|
-
const candidate =
|
|
1149
|
+
const candidate = join4(adjacentTo ? dirname(resolve3(adjacentTo)) : cwd(), "local-runner.json");
|
|
1104
1150
|
const metadata = await stat(candidate).catch(() => null);
|
|
1105
1151
|
return metadata?.isFile() ? candidate : void 0;
|
|
1106
1152
|
}
|
|
@@ -1120,7 +1166,7 @@ async function loadCliBehaviorSpec(inputPath, runId) {
|
|
|
1120
1166
|
});
|
|
1121
1167
|
if (input.kind === "foundation-spec") {
|
|
1122
1168
|
throw new Error(
|
|
1123
|
-
`This spec uses engine "foundation". Use \`tt pipeline run --spec ${input.path}
|
|
1169
|
+
`This spec uses engine "foundation". Use \`tt pipeline run --spec ${input.path}\`; the legacy adapter runner cannot execute foundation specs.`
|
|
1124
1170
|
);
|
|
1125
1171
|
}
|
|
1126
1172
|
if (input.kind !== "spec") {
|
|
@@ -1165,7 +1211,7 @@ function createConsoleReporter(options) {
|
|
|
1165
1211
|
};
|
|
1166
1212
|
}
|
|
1167
1213
|
async function verifyStoredModel(model, config) {
|
|
1168
|
-
const manifestPath =
|
|
1214
|
+
const manifestPath = join4(model.artifact_dir, "artifact-manifest.json");
|
|
1169
1215
|
const integrity = await assertArtifactManifest(manifestPath, {
|
|
1170
1216
|
requiredPaths: ["stage-metadata.json", "training-report.json"],
|
|
1171
1217
|
scopeToRequired: true,
|
|
@@ -1200,8 +1246,8 @@ async function verifyStoredModel(model, config) {
|
|
|
1200
1246
|
};
|
|
1201
1247
|
}
|
|
1202
1248
|
async function verifyActivationEvidence(model) {
|
|
1203
|
-
const generalBaseline =
|
|
1204
|
-
const generalCandidate =
|
|
1249
|
+
const generalBaseline = join4(model.artifact_dir, "general-baseline-eval.json");
|
|
1250
|
+
const generalCandidate = join4(model.artifact_dir, "general-candidate-eval.json");
|
|
1205
1251
|
const [hasBaseline, hasCandidate] = await Promise.all([
|
|
1206
1252
|
stat(generalBaseline).then((metadata) => metadata.isFile(), () => false),
|
|
1207
1253
|
stat(generalCandidate).then((metadata) => metadata.isFile(), () => false)
|
|
@@ -1211,7 +1257,7 @@ async function verifyActivationEvidence(model) {
|
|
|
1211
1257
|
"This model cannot be activated because the run did not include a general-regression suite. Add evaluation.generalRegression to local-runner.json with a held-out dataset, re-run training, then activate. Until then, serve the adapter with `tt serve local-<run-id>`."
|
|
1212
1258
|
);
|
|
1213
1259
|
}
|
|
1214
|
-
await assertArtifactManifest(
|
|
1260
|
+
await assertArtifactManifest(join4(model.artifact_dir, "artifact-manifest.json"), {
|
|
1215
1261
|
requiredPaths: [
|
|
1216
1262
|
"run-report.json",
|
|
1217
1263
|
"general-baseline-eval.json",
|
|
@@ -1237,7 +1283,7 @@ async function verifyModelArtifactPath(input, config) {
|
|
|
1237
1283
|
if (!metadata) throw new Error(`Model not found and artifact path does not exist: ${input}`);
|
|
1238
1284
|
let current = metadata.isDirectory() ? inputPath : dirname(inputPath);
|
|
1239
1285
|
for (let depth = 0; depth < 8; depth += 1) {
|
|
1240
|
-
const candidate =
|
|
1286
|
+
const candidate = join4(current, "artifact-manifest.json");
|
|
1241
1287
|
const raw = await readFile2(candidate, "utf8").catch(() => null);
|
|
1242
1288
|
if (raw) {
|
|
1243
1289
|
const parsed = JSON.parse(raw);
|
|
@@ -1295,7 +1341,7 @@ async function modelSystemPrompt(args) {
|
|
|
1295
1341
|
}
|
|
1296
1342
|
spec = local.data;
|
|
1297
1343
|
} else {
|
|
1298
|
-
const runRequestPath =
|
|
1344
|
+
const runRequestPath = join4(args.store.paths.runsDir, args.model.run_id, "request.json");
|
|
1299
1345
|
let persistedRequest = null;
|
|
1300
1346
|
try {
|
|
1301
1347
|
persistedRequest = fineTuneRunRequestSchema.parse(JSON.parse(await readFile2(runRequestPath, "utf8")));
|
|
@@ -1311,9 +1357,9 @@ async function modelSystemPrompt(args) {
|
|
|
1311
1357
|
}
|
|
1312
1358
|
const prompt = buildSystemMessage(spec);
|
|
1313
1359
|
const metadata = JSON.parse(
|
|
1314
|
-
await readFile2(
|
|
1360
|
+
await readFile2(join4(args.model.artifact_dir, "stage-metadata.json"), "utf8")
|
|
1315
1361
|
);
|
|
1316
|
-
const promptHash =
|
|
1362
|
+
const promptHash = createHash2("sha256").update(prompt).digest("hex");
|
|
1317
1363
|
if (metadata.system_prompt_sha256 !== promptHash) {
|
|
1318
1364
|
throw new Error(
|
|
1319
1365
|
"Behavior spec instructions do not match the prompt fingerprint used for this trained model. Pass the original --spec, or use --no-spec-prompt only when this change is intentional."
|
|
@@ -1328,6 +1374,47 @@ function modelServeDevice(argv) {
|
|
|
1328
1374
|
}
|
|
1329
1375
|
throw new Error(`--device must be cuda or cpu; got: ${value}`);
|
|
1330
1376
|
}
|
|
1377
|
+
function printServeClientConfig(argv, launch) {
|
|
1378
|
+
const client = readOption(argv, "--print-client-config");
|
|
1379
|
+
if (client === void 0) return false;
|
|
1380
|
+
if (client !== "pi") throw new Error("--print-client-config must be pi.");
|
|
1381
|
+
if (hasFlag(argv, "--print-command")) throw new Error("Use only one of --print-command or --print-client-config.");
|
|
1382
|
+
const apiKeyEnv = readOption(argv, "--api-key-env");
|
|
1383
|
+
if (apiKeyEnv && !/^[A-Za-z_][A-Za-z0-9_]*$/.test(apiKeyEnv)) {
|
|
1384
|
+
throw new Error("--api-key-env must be a plain environment variable name for Pi config.");
|
|
1385
|
+
}
|
|
1386
|
+
const url = new URL(launch.url);
|
|
1387
|
+
if (url.hostname === "0.0.0.0") url.hostname = "127.0.0.1";
|
|
1388
|
+
if (url.hostname === "[::]") url.hostname = "[::1]";
|
|
1389
|
+
url.pathname = "/v1";
|
|
1390
|
+
printJson({
|
|
1391
|
+
providers: {
|
|
1392
|
+
"tt-local": {
|
|
1393
|
+
baseUrl: url.toString(),
|
|
1394
|
+
api: "openai-completions",
|
|
1395
|
+
apiKey: apiKeyEnv ? "${" + apiKeyEnv + "}" : "tt-local",
|
|
1396
|
+
compat: {
|
|
1397
|
+
supportsStore: false,
|
|
1398
|
+
supportsDeveloperRole: false,
|
|
1399
|
+
supportsReasoningEffort: false,
|
|
1400
|
+
supportsUsageInStreaming: true,
|
|
1401
|
+
maxTokensField: "max_tokens"
|
|
1402
|
+
},
|
|
1403
|
+
models: [.../* @__PURE__ */ new Set([launch.modelName, `base:${launch.env.TT_BASE_MODEL}`])].map((id) => ({
|
|
1404
|
+
id,
|
|
1405
|
+
name: id,
|
|
1406
|
+
// This endpoint exports ordinary text/tool calls, not reasoning-effort controls.
|
|
1407
|
+
reasoning: false,
|
|
1408
|
+
input: ["text"],
|
|
1409
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
1410
|
+
contextWindow: Number(launch.env.TT_CONTEXT_LENGTH),
|
|
1411
|
+
maxTokens: Number(launch.env.TT_MAX_TOKENS)
|
|
1412
|
+
}))
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
});
|
|
1416
|
+
return true;
|
|
1417
|
+
}
|
|
1331
1418
|
async function serveStoredModelFromCli(args) {
|
|
1332
1419
|
const store = createLocalStore(args.config.storeRoot);
|
|
1333
1420
|
const model = await store.getModel(args.modelId);
|
|
@@ -1343,6 +1430,8 @@ async function serveStoredModelFromCli(args) {
|
|
|
1343
1430
|
temperature: readNumberOption(args.argv, "--temperature"),
|
|
1344
1431
|
topP: readNumberOption(args.argv, "--top-p"),
|
|
1345
1432
|
maxConcurrentRequests: readNumberOption(args.argv, "--max-concurrent-requests"),
|
|
1433
|
+
contextLength: readNumberOption(args.argv, "--context-length"),
|
|
1434
|
+
gpuMemoryUtilization: readNumberOption(args.argv, "--gpu-memory-utilization"),
|
|
1346
1435
|
systemPrompt: await modelSystemPrompt({ argv: args.argv, model, store }),
|
|
1347
1436
|
allowRemote: hasFlag(args.argv, "--allow-remote"),
|
|
1348
1437
|
apiKeyEnv: readOption(args.argv, "--api-key-env"),
|
|
@@ -1356,6 +1445,7 @@ async function serveStoredModelFromCli(args) {
|
|
|
1356
1445
|
})()
|
|
1357
1446
|
}
|
|
1358
1447
|
});
|
|
1448
|
+
if (printServeClientConfig(args.argv, launch)) return;
|
|
1359
1449
|
if (hasFlag(args.argv, "--print-command")) {
|
|
1360
1450
|
printJson({
|
|
1361
1451
|
ok: true,
|
|
@@ -1381,6 +1471,8 @@ function serveOptionsFromArgv(argv) {
|
|
|
1381
1471
|
temperature: readNumberOption(argv, "--temperature"),
|
|
1382
1472
|
topP: readNumberOption(argv, "--top-p"),
|
|
1383
1473
|
maxConcurrentRequests: readNumberOption(argv, "--max-concurrent-requests"),
|
|
1474
|
+
contextLength: readNumberOption(argv, "--context-length"),
|
|
1475
|
+
gpuMemoryUtilization: readNumberOption(argv, "--gpu-memory-utilization"),
|
|
1384
1476
|
allowRemote: hasFlag(argv, "--allow-remote"),
|
|
1385
1477
|
apiKeyEnv: readOption(argv, "--api-key-env")
|
|
1386
1478
|
};
|
|
@@ -1419,6 +1511,7 @@ async function serveBaseModelFromCli(args) {
|
|
|
1419
1511
|
baseModelRevision: spec?.hyperparameters?.base_model_revision ?? defaultBaseModelRevision(baseModel)
|
|
1420
1512
|
}
|
|
1421
1513
|
});
|
|
1514
|
+
if (printServeClientConfig(args.argv, launch)) return;
|
|
1422
1515
|
if (hasFlag(args.argv, "--print-command")) {
|
|
1423
1516
|
printJson({
|
|
1424
1517
|
ok: true,
|
|
@@ -1856,6 +1949,8 @@ export {
|
|
|
1856
1949
|
localRunnerConfigSchema,
|
|
1857
1950
|
localStorePaths,
|
|
1858
1951
|
normalizeChatJsonlForRelocation,
|
|
1952
|
+
parseLocalRunInput,
|
|
1953
|
+
parseLocalRunnerConfig,
|
|
1859
1954
|
prefetchBaseModel,
|
|
1860
1955
|
reportInBackground,
|
|
1861
1956
|
resolveLocalRunInputPaths,
|