@infersec/conduit 1.100.0 → 1.102.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/dist/cli.sea.cjs CHANGED
@@ -42,10 +42,10 @@ var require$$1$8 = require('node:async_hooks');
42
42
  var require$$1$9 = require('node:console');
43
43
  var require$$0$m = require('node:fs/promises');
44
44
  var require$$2$5 = require('node:timers');
45
- var node_string_decoder = require('node:string_decoder');
46
- var promises = require('node:stream/promises');
47
45
  require('fs/promises');
48
46
  require('stream/promises');
47
+ var node_string_decoder = require('node:string_decoder');
48
+ var promises = require('node:stream/promises');
49
49
  var os = require('node:os');
50
50
  var tty = require('node:tty');
51
51
  var require$$3$9 = require('child_process');
@@ -4360,35 +4360,6 @@ function ulid$2(seedTime, prng) {
4360
4360
  return encodeTime(seed, TIME_LEN) + encodeRandom(RANDOM_LEN, currentPRNG);
4361
4361
  }
4362
4362
 
4363
- function getEffectiveContextLength({ contextLength, engineConfig, engineType }) {
4364
- if (contextLength === null || contextLength <= 0) {
4365
- return null;
4366
- }
4367
- if (!engineConfig) {
4368
- return contextLength;
4369
- }
4370
- switch (engineType) {
4371
- case "llama.cpp": {
4372
- const parallelism = engineConfig.parallelism;
4373
- if (typeof parallelism === "number" && parallelism > 0) {
4374
- return contextLength / parallelism;
4375
- }
4376
- return contextLength;
4377
- }
4378
- case "sglang":
4379
- case "tensorrt-llm":
4380
- case "vllm": {
4381
- const tensorParallelSize = engineConfig.tensorParallelSize;
4382
- if (typeof tensorParallelSize === "number" && tensorParallelSize > 0) {
4383
- return contextLength / tensorParallelSize;
4384
- }
4385
- return contextLength;
4386
- }
4387
- default:
4388
- return contextLength;
4389
- }
4390
- }
4391
-
4392
4363
  function asError(error) {
4393
4364
  if (error instanceof Error) {
4394
4365
  return error;
@@ -19929,58 +19900,10 @@ const LLMEngineSchema = _enum$1([
19929
19900
  "tensorrt-llm",
19930
19901
  "vllm"
19931
19902
  ]);
19932
- const LlamacppEngineConfigSchema = object$1({
19933
- batchSize: number$1().int().positive().nullable().optional(),
19934
- cacheTypeK: string$2().nullable().optional(),
19935
- cacheTypeV: string$2().nullable().optional(),
19936
- extraArgs: array(string$2()).optional(),
19937
- flashAttn: boolean$1().optional(),
19938
- gpuLayers: number$1().int().min(0).optional(),
19939
- mainGpu: number$1().int().min(0).nullable().optional(),
19940
- parallelism: number$1().int().positive().optional(),
19941
- tensorSplit: string$2().nullable().optional(),
19942
- ubatchSize: number$1().int().positive().nullable().optional()
19943
- });
19944
- const VLLMEngineConfigSchema = object$1({
19945
- device: string$2().optional(),
19946
- dtype: string$2().optional(),
19947
- extraArgs: array(string$2()).optional(),
19948
- tensorParallelSize: number$1().int().positive().optional()
19949
- });
19950
- const SGLangEngineConfigSchema = object$1({
19951
- device: string$2().optional(),
19952
- dtype: string$2().optional(),
19953
- extraArgs: array(string$2()).optional(),
19954
- tensorParallelSize: number$1().int().positive().optional()
19955
- });
19956
- const TensorRTLLMEngineConfigSchema = object$1({
19957
- backend: _enum$1(["_autodeploy", "pytorch", "tensorrt"]).optional(),
19958
- dtype: string$2().optional(),
19959
- extraArgs: array(string$2()).optional(),
19960
- tensorParallelSize: number$1().int().positive().optional()
19961
- });
19962
- const Exllamav3EngineConfigSchema = object$1({
19963
- cacheMode: _enum$1(["fp16", "q4", "q6", "q8"]).optional(),
19964
- extraArgs: array(string$2()).optional(),
19965
- gpuSplit: string$2().optional(),
19966
- maxSeqLen: number$1().int().positive().optional()
19967
- });
19968
- const MLXLMEngineConfigSchema = object$1({
19969
- extraArgs: array(string$2()).optional(),
19970
- maxKvSize: number$1().int().positive().optional(),
19971
- trustRemoteCode: boolean$1().optional()
19903
+ const EngineConfigSchema = object$1({
19904
+ extraArgs: array(string$2()),
19905
+ type: LLMEngineSchema
19972
19906
  });
19973
- const EngineConfigSchema = discriminatedUnion("type", [
19974
- object$1({ config: Exllamav3EngineConfigSchema, type: literal("exllamav3") }),
19975
- object$1({ config: LlamacppEngineConfigSchema, type: literal("llama.cpp") }),
19976
- object$1({ config: MLXLMEngineConfigSchema, type: literal("mlx-lm") }),
19977
- object$1({ config: SGLangEngineConfigSchema, type: literal("sglang") }),
19978
- object$1({
19979
- config: TensorRTLLMEngineConfigSchema,
19980
- type: literal("tensorrt-llm")
19981
- }),
19982
- object$1({ config: VLLMEngineConfigSchema, type: literal("vllm") })
19983
- ]);
19984
19907
  const LLMModelFormatSchema = _enum$1([
19985
19908
  // VLLM / SGLang / TensorRT-LLM
19986
19909
  "safetensors",
@@ -20001,7 +19924,39 @@ object$1({
20001
19924
  supportsVision: boolean$1()
20002
19925
  });
20003
19926
  const LLMModelTaskTypeSchema = _enum$1(["text-generation", "embeddings"]);
19927
+ const ReasoningEffortSchema = _enum$1(["none", "minimal", "low", "medium", "high", "xhigh"]);
19928
+ const CHAT_TEMPLATE_DEFAULT_FILE_PATH = "chat_template.jinja";
19929
+ const CHAT_TEMPLATE_LOCAL_FILE_NAME = "infersec-chat-template.jinja";
19930
+ const ChatTemplateOverrideSchema = discriminatedUnion("type", [
19931
+ object$1({
19932
+ filePath: string$2().min(1).default(CHAT_TEMPLATE_DEFAULT_FILE_PATH),
19933
+ repo: string$2().min(1),
19934
+ type: literal("huggingface")
19935
+ }),
19936
+ object$1({
19937
+ content: string$2().min(1),
19938
+ type: literal("inline")
19939
+ })
19940
+ ]);
19941
+ const ThinkingConfigSchema = object$1({
19942
+ enabled: boolean$1().optional(),
19943
+ effort: ReasoningEffortSchema.optional()
19944
+ });
19945
+ const ANTHROPIC_THINKING_BUDGET_EFFORT_TIERS = [
19946
+ { effort: "low", maxBudgetTokens: 2048 },
19947
+ { effort: "medium", maxBudgetTokens: 8192 },
19948
+ { effort: "high", maxBudgetTokens: Number.POSITIVE_INFINITY }
19949
+ ];
19950
+ function reasoningEffortForAnthropicBudget(budgetTokens) {
19951
+ for (const tier of ANTHROPIC_THINKING_BUDGET_EFFORT_TIERS) {
19952
+ if (budgetTokens <= tier.maxBudgetTokens) {
19953
+ return tier.effort;
19954
+ }
19955
+ }
19956
+ return "high";
19957
+ }
20004
19958
  const LLMModelSchema = object$1({
19959
+ chatTemplate: ChatTemplateOverrideSchema.nullable().optional(),
20005
19960
  format: LLMModelFormatSchema,
20006
19961
  id: string$2().min(1),
20007
19962
  multimodalEnabled: boolean$1(),
@@ -20016,7 +19971,8 @@ const LLMModelSchema = object$1({
20016
19971
  type: literal("huggingface")
20017
19972
  })
20018
19973
  ]),
20019
- taskType: LLMModelTaskTypeSchema
19974
+ taskType: LLMModelTaskTypeSchema,
19975
+ thinkingConfig: ThinkingConfigSchema.nullable().optional()
20020
19976
  });
20021
19977
  object$1({
20022
19978
  filePath: string$2().min(1),
@@ -20135,7 +20091,8 @@ const ConduitStateSchema = z
20135
20091
  ])
20136
20092
  .and(z.object({
20137
20093
  activeRequestCount: z.number().int().nonnegative().optional(),
20138
- timestamp: z.string().datetime()
20094
+ timestamp: z.string().datetime(),
20095
+ warnings: z.array(z.string()).optional()
20139
20096
  }));
20140
20097
  const ConduitState = z.preprocess(value => {
20141
20098
  if (value === null) {
@@ -20674,6 +20631,10 @@ const ChatCompletionMessageSchema = object$1({
20674
20631
  const ChatCompletionCreateParamsSchema = object$1({
20675
20632
  messages: array(ChatCompletionMessageParamSchema),
20676
20633
  model: string$2(),
20634
+ chat_template_kwargs: record(string$2(), unknown())
20635
+ .nullable()
20636
+ .optional()
20637
+ .describe("Additional chat template variables passed to the model's chat template at render time (e.g. reasoning_effort)"),
20677
20638
  frequency_penalty: number$1().min(-2).max(2).nullable().optional(),
20678
20639
  function_call: union([literal("none"), literal("auto"), object$1({ name: string$2() })])
20679
20640
  .optional(),
@@ -20689,6 +20650,9 @@ const ChatCompletionCreateParamsSchema = object$1({
20689
20650
  max_tokens: number$1().positive().nullable().optional(),
20690
20651
  n: number$1().positive().nullable().optional(),
20691
20652
  presence_penalty: number$1().min(-2).max(2).nullable().optional(),
20653
+ reasoning_effort: ReasoningEffortSchema.nullable()
20654
+ .optional()
20655
+ .describe("Reasoning effort hint for thinking models. Forwarded to the chat template when one is configured"),
20692
20656
  response_format: object$1({
20693
20657
  type: _enum$1(["text", "json_object"])
20694
20658
  })
@@ -20970,6 +20934,7 @@ RoutingMethod.FirstAvailable;
20970
20934
  });
20971
20935
 
20972
20936
  object$1({
20937
+ chatTemplate: ChatTemplateOverrideSchema.nullable().optional(),
20973
20938
  format: LLMModelFormatSchema,
20974
20939
  multimodalEnabled: boolean$1().optional(),
20975
20940
  name: ResourceNameSchema,
@@ -20979,7 +20944,8 @@ object$1({
20979
20944
  .refine(value => value.includes("/"), {
20980
20945
  message: "Slug must be fully qualified (owner/repo)"
20981
20946
  }),
20982
- taskType: LLMModelTaskTypeSchema.optional()
20947
+ taskType: LLMModelTaskTypeSchema.optional(),
20948
+ thinkingConfig: ThinkingConfigSchema.nullable().optional()
20983
20949
  });
20984
20950
  object$1({
20985
20951
  results: array(object$1({
@@ -20995,6 +20961,7 @@ object$1({
20995
20961
  }))
20996
20962
  });
20997
20963
  object$1({
20964
+ chatTemplate: ChatTemplateOverrideSchema.nullable(),
20998
20965
  created: string$2(),
20999
20966
  id: ULIDSchema,
21000
20967
  modelFormat: LLMModelFormatSchema,
@@ -21012,12 +20979,15 @@ object$1({
21012
20979
  updated: string$2()
21013
20980
  })),
21014
20981
  taskType: LLMModelTaskTypeSchema,
20982
+ thinkingConfig: ThinkingConfigSchema.nullable(),
21015
20983
  updated: string$2()
21016
20984
  });
21017
20985
  object$1({
20986
+ chatTemplate: ChatTemplateOverrideSchema.nullable().optional(),
21018
20987
  multimodalEnabled: boolean$1().optional(),
21019
20988
  name: ResourceNameSchema.optional(),
21020
- taskType: LLMModelTaskTypeSchema.optional()
20989
+ taskType: LLMModelTaskTypeSchema.optional(),
20990
+ thinkingConfig: ThinkingConfigSchema.nullable().optional()
21021
20991
  });
21022
20992
  object$1({
21023
20993
  success: literal(true)
@@ -21129,105 +21099,21 @@ object$1({
21129
21099
  });
21130
21100
  const EngineOutputSchema = object$1({
21131
21101
  created: string$2(),
21132
- exllamav3CacheMode: string$2().nullable(),
21133
- exllamav3ExtraArgs: array(string$2()),
21134
- exllamav3GpuSplit: string$2().nullable(),
21135
- exllamav3MaxSeqLen: number$1().nullable(),
21102
+ extraArgs: array(string$2()),
21136
21103
  id: ULIDSchema,
21137
- llamacppBatchSize: number$1().nullable(),
21138
- llamacppCacheTypeK: string$2().nullable(),
21139
- llamacppCacheTypeV: string$2().nullable(),
21140
- llamacppExtraArgs: array(string$2()),
21141
- llamacppFlashAttn: boolean$1(),
21142
- llamacppGpuLayers: number$1(),
21143
- llamacppMainGpu: number$1().nullable(),
21144
- llamacppParallelism: number$1(),
21145
- llamacppTensorSplit: string$2().nullable(),
21146
- llamacppUbatchSize: number$1().nullable(),
21147
- mlxlmExtraArgs: array(string$2()),
21148
- mlxlmMaxKvSize: number$1().nullable(),
21149
- mlxlmTrustRemoteCode: boolean$1(),
21150
21104
  name: string$2(),
21151
- sglangDevice: string$2().nullable(),
21152
- sglangDtype: string$2().nullable(),
21153
- sglangExtraArgs: array(string$2()),
21154
- sglangTensorParallelSize: number$1(),
21155
- trtllmBackend: string$2().nullable(),
21156
- trtllmDtype: string$2().nullable(),
21157
- trtllmExtraArgs: array(string$2()),
21158
- trtllmTensorParallelSize: number$1(),
21159
21105
  type: LLMEngineSchema,
21160
- updated: string$2(),
21161
- vllmDevice: string$2().nullable(),
21162
- vllmDtype: string$2().nullable(),
21163
- vllmExtraArgs: array(string$2()),
21164
- vllmTensorParallelSize: number$1()
21106
+ updated: string$2()
21165
21107
  });
21166
21108
  object$1({
21167
- exllamav3CacheMode: string$2().nullable().optional(),
21168
- exllamav3ExtraArgs: array(string$2()).optional(),
21169
- exllamav3GpuSplit: string$2().nullable().optional(),
21170
- exllamav3MaxSeqLen: number$1().int().positive().nullable().optional(),
21171
- llamacppBatchSize: number$1().int().positive().nullable().optional(),
21172
- llamacppCacheTypeK: string$2().nullable().optional(),
21173
- llamacppCacheTypeV: string$2().nullable().optional(),
21174
- llamacppExtraArgs: array(string$2()).optional(),
21175
- llamacppFlashAttn: boolean$1().optional(),
21176
- llamacppGpuLayers: number$1().int().min(0).optional(),
21177
- llamacppMainGpu: number$1().int().min(0).nullable().optional(),
21178
- llamacppParallelism: number$1().int().positive().optional(),
21179
- llamacppTensorSplit: string$2().nullable().optional(),
21180
- llamacppUbatchSize: number$1().int().positive().nullable().optional(),
21181
- mlxlmExtraArgs: array(string$2()).optional(),
21182
- mlxlmMaxKvSize: number$1().int().positive().nullable().optional(),
21183
- mlxlmTrustRemoteCode: boolean$1().optional(),
21109
+ extraArgs: array(string$2()).optional(),
21184
21110
  name: ResourceNameSchema,
21185
- sglangDevice: string$2().nullable().optional(),
21186
- sglangDtype: string$2().nullable().optional(),
21187
- sglangExtraArgs: array(string$2()).optional(),
21188
- sglangTensorParallelSize: number$1().int().positive().optional(),
21189
- trtllmBackend: string$2().nullable().optional(),
21190
- trtllmDtype: string$2().nullable().optional(),
21191
- trtllmExtraArgs: array(string$2()).optional(),
21192
- trtllmTensorParallelSize: number$1().int().positive().optional(),
21193
- type: LLMEngineSchema,
21194
- vllmDevice: string$2().nullable().optional(),
21195
- vllmDtype: string$2().nullable().optional(),
21196
- vllmExtraArgs: array(string$2()).optional(),
21197
- vllmTensorParallelSize: number$1().int().positive().optional()
21111
+ type: LLMEngineSchema
21198
21112
  });
21199
21113
  object$1({
21200
- exllamav3CacheMode: string$2().nullable().optional(),
21201
- exllamav3ExtraArgs: array(string$2()).optional(),
21202
- exllamav3GpuSplit: string$2().nullable().optional(),
21203
- exllamav3MaxSeqLen: number$1().int().positive().nullable().optional(),
21204
- llamacppBatchSize: number$1().int().positive().nullable().optional(),
21205
- llamacppCacheTypeK: string$2().nullable().optional(),
21206
- llamacppCacheTypeV: string$2().nullable().optional(),
21207
- llamacppExtraArgs: array(string$2()).optional(),
21208
- llamacppFlashAttn: boolean$1().optional(),
21209
- llamacppGpuLayers: number$1().int().min(0).optional(),
21210
- llamacppMainGpu: number$1().int().min(0).nullable().optional(),
21211
- llamacppParallelism: number$1().int().positive().optional(),
21212
- llamacppTensorSplit: string$2().nullable().optional(),
21213
- llamacppUbatchSize: number$1().int().positive().nullable().optional(),
21214
- mlxlmExtraArgs: array(string$2()).optional(),
21215
- mlxlmMaxKvSize: number$1().int().positive().nullable().optional(),
21216
- mlxlmTrustRemoteCode: boolean$1().optional(),
21114
+ extraArgs: array(string$2()).optional(),
21217
21115
  name: ResourceNameSchema.optional(),
21218
- sglangDevice: string$2().nullable().optional(),
21219
- sglangDtype: string$2().nullable().optional(),
21220
- sglangExtraArgs: array(string$2()).optional(),
21221
- sglangTensorParallelSize: number$1().int().positive().optional(),
21222
- trtllmBackend: string$2().nullable().optional(),
21223
- trtllmDtype: string$2().nullable().optional(),
21224
- trtllmExtraArgs: array(string$2()).optional(),
21225
- trtllmTensorParallelSize: number$1().int().positive().optional(),
21226
- type: LLMEngineSchema.optional(),
21227
- vllmDevice: string$2().nullable().optional(),
21228
- vllmDtype: string$2().nullable().optional(),
21229
- vllmExtraArgs: array(string$2()).optional(),
21230
- vllmTensorParallelSize: number$1().int().positive().optional()
21116
+ type: LLMEngineSchema.optional()
21231
21117
  });
21232
21118
  object$1({
21233
21119
  results: array(EngineOutputSchema)
@@ -21304,6 +21190,12 @@ object$1({
21304
21190
  }
21305
21191
  });
21306
21192
 
21193
+ object$1({
21194
+ config: EngineConfigSchema,
21195
+ description: string$2().optional(),
21196
+ name: ResourceNameSchema
21197
+ });
21198
+
21307
21199
  const ENGINE_API_COMPATIBILITY = {
21308
21200
  exllamav3: {
21309
21201
  nativeAnthropicMessages: false,
@@ -21722,6 +21614,105 @@ discriminatedUnion("chargeName", [
21722
21614
  ToolServiceCallMetaSchema
21723
21615
  ]);
21724
21616
 
21617
+ function parseExtraArgs(extraArgs) {
21618
+ if (!Array.isArray(extraArgs) ||
21619
+ !extraArgs.every((value) => typeof value === "string")) {
21620
+ return [];
21621
+ }
21622
+ return extraArgs.flatMap(tokenizeShellLine);
21623
+ }
21624
+ function findArgValue(args, flag) {
21625
+ let found = null;
21626
+ for (let index = 0; index < args.length; index += 1) {
21627
+ const token = args[index];
21628
+ if (token === flag) {
21629
+ const value = args[index + 1];
21630
+ if (value !== undefined && !value.startsWith("--")) {
21631
+ found = value;
21632
+ }
21633
+ else {
21634
+ found = null;
21635
+ }
21636
+ }
21637
+ else if (token.startsWith(`${flag}=`)) {
21638
+ found = token.slice(flag.length + 1);
21639
+ }
21640
+ }
21641
+ return found;
21642
+ }
21643
+ function tokenizeShellLine(input) {
21644
+ const tokens = [];
21645
+ let buffer = "";
21646
+ let inQuote = null;
21647
+ let hasBuffer = false;
21648
+ for (let index = 0; index < input.length; index += 1) {
21649
+ const char = input[index];
21650
+ if (inQuote) {
21651
+ if (char === inQuote) {
21652
+ inQuote = null;
21653
+ }
21654
+ else {
21655
+ buffer += char;
21656
+ }
21657
+ hasBuffer = true;
21658
+ }
21659
+ else if (char === '"' || char === "'") {
21660
+ inQuote = char;
21661
+ hasBuffer = true;
21662
+ }
21663
+ else if (char === " " || char === "\t") {
21664
+ if (hasBuffer) {
21665
+ tokens.push(buffer);
21666
+ buffer = "";
21667
+ hasBuffer = false;
21668
+ }
21669
+ }
21670
+ else {
21671
+ buffer += char;
21672
+ hasBuffer = true;
21673
+ }
21674
+ }
21675
+ if (hasBuffer) {
21676
+ tokens.push(buffer);
21677
+ }
21678
+ return tokens;
21679
+ }
21680
+
21681
+ function getEffectiveContextLength({ contextLength, engineConfig, engineType }) {
21682
+ if (contextLength === null || contextLength <= 0) {
21683
+ return null;
21684
+ }
21685
+ if (!engineConfig) {
21686
+ return contextLength;
21687
+ }
21688
+ let divisorFlag = null;
21689
+ switch (engineType) {
21690
+ case "llama.cpp":
21691
+ divisorFlag = "--parallel";
21692
+ break;
21693
+ case "sglang":
21694
+ case "tensorrt-llm":
21695
+ divisorFlag = "--tp-size";
21696
+ break;
21697
+ case "vllm":
21698
+ divisorFlag = "--tensor-parallel-size";
21699
+ break;
21700
+ }
21701
+ if (!divisorFlag) {
21702
+ return contextLength;
21703
+ }
21704
+ const tokens = parseExtraArgs(engineConfig.extraArgs);
21705
+ const rawValue = findArgValue(tokens, divisorFlag);
21706
+ if (rawValue === null) {
21707
+ return contextLength;
21708
+ }
21709
+ const divisor = Number(rawValue);
21710
+ if (Number.isSafeInteger(divisor) && divisor > 0) {
21711
+ return contextLength / divisor;
21712
+ }
21713
+ return contextLength;
21714
+ }
21715
+
21725
21716
  const ENV_BOOL_TRUE = ["true", "1", "yes"];
21726
21717
  const ENV_BOOL_FALSE = ["false", "0", "no"];
21727
21718
  function readEnvBoolean(name) {
@@ -22205,41 +22196,6 @@ class ProcessManager extends EventEmitter {
22205
22196
  }
22206
22197
  }
22207
22198
 
22208
- function watchStreamProgress(emitIntervalBytes) {
22209
- let bytesProcessed = 0;
22210
- let lastEmittedAt = 0;
22211
- const emitter = new EventEmitter();
22212
- const stream = new require$$0$8.Transform({
22213
- transform(chunk, _encoding, callback) {
22214
- bytesProcessed += chunk.length;
22215
- // Emit progress updates at intervals
22216
- if (bytesProcessed - lastEmittedAt >= emitIntervalBytes) {
22217
- emitter.emit("progress", bytesProcessed);
22218
- lastEmittedAt = bytesProcessed;
22219
- }
22220
- // Pass chunk through unchanged
22221
- callback(null, chunk);
22222
- },
22223
- flush(callback) {
22224
- emitter.emit("progress", bytesProcessed);
22225
- callback();
22226
- }
22227
- });
22228
- stream.progress = emitter;
22229
- return stream;
22230
- }
22231
-
22232
- function joinURL(...parts) {
22233
- return parts
22234
- .join("/")
22235
- .replace(/[\/]+/g, "/")
22236
- .replace(/^(.+):\//, "$1://")
22237
- .replace(/^file:/, "file:/")
22238
- .replace(/\/(\?|&|#[^!])/g, "$1")
22239
- .replace(/\?/g, "&")
22240
- .replace("&", "?");
22241
- }
22242
-
22243
22199
  function isTerminatedError(error) {
22244
22200
  return error instanceof Error && error.message === "terminated" && error.name === "TypeError";
22245
22201
  }
@@ -22323,6 +22279,41 @@ function parseSSEEvent(rawEvent) {
22323
22279
  };
22324
22280
  }
22325
22281
 
22282
+ function watchStreamProgress(emitIntervalBytes) {
22283
+ let bytesProcessed = 0;
22284
+ let lastEmittedAt = 0;
22285
+ const emitter = new EventEmitter();
22286
+ const stream = new require$$0$8.Transform({
22287
+ transform(chunk, _encoding, callback) {
22288
+ bytesProcessed += chunk.length;
22289
+ // Emit progress updates at intervals
22290
+ if (bytesProcessed - lastEmittedAt >= emitIntervalBytes) {
22291
+ emitter.emit("progress", bytesProcessed);
22292
+ lastEmittedAt = bytesProcessed;
22293
+ }
22294
+ // Pass chunk through unchanged
22295
+ callback(null, chunk);
22296
+ },
22297
+ flush(callback) {
22298
+ emitter.emit("progress", bytesProcessed);
22299
+ callback();
22300
+ }
22301
+ });
22302
+ stream.progress = emitter;
22303
+ return stream;
22304
+ }
22305
+
22306
+ function joinURL(...parts) {
22307
+ return parts
22308
+ .join("/")
22309
+ .replace(/[\/]+/g, "/")
22310
+ .replace(/^(.+):\//, "$1://")
22311
+ .replace(/^file:/, "file:/")
22312
+ .replace(/\/(\?|&|#[^!])/g, "$1")
22313
+ .replace(/\?/g, "&")
22314
+ .replace("&", "?");
22315
+ }
22316
+
22326
22317
  function buildConfigurationOverrides(options) {
22327
22318
  const configurationOverrides = {};
22328
22319
  if (options.apiUrl) {
@@ -112947,458 +112938,1618 @@ var createRouter = /*@__PURE__*/getDefaultExportFromCjs(expressPromiseRouterExpo
112947
112938
 
112948
112939
  const SERVED_MODEL_NAME = "default";
112949
112940
 
112950
- const SECRET_FLAGS = new Set([
112951
- "api-key",
112952
- "auth-token",
112953
- "hf-token",
112954
- "key",
112955
- "password",
112956
- "secret",
112957
- "token"
112958
- ]);
112959
- function redactSecretArgs(args) {
112960
- return args.map((arg, index) => {
112961
- const equalsIndex = arg.indexOf("=");
112962
- if (arg.startsWith("--") && equalsIndex > 0) {
112963
- const flag = arg.slice(2, equalsIndex);
112964
- if (SECRET_FLAGS.has(flag)) {
112965
- return `${arg.slice(0, equalsIndex + 1)}***`;
112966
- }
112967
- }
112968
- const previous = args[index - 1];
112969
- if (previous &&
112970
- previous.startsWith("--") &&
112971
- !previous.includes("=") &&
112972
- SECRET_FLAGS.has(previous.slice(2))) {
112973
- return "***";
112974
- }
112975
- return arg;
112976
- });
112977
- }
112978
- async function createEngineProcess({ args, bin, logger }) {
112979
- logger.info("Starting engine process", {
112980
- command: { args: redactSecretArgs(args), bin }
112981
- });
112982
- const processManager = new ProcessManager({ args, command: bin });
112983
- await processManager.start();
112984
- return processManager;
112985
- }
112941
+ // src/lib/cache-management.ts
112986
112942
 
112987
- function parseExtraArgs(extraArgs) {
112988
- if (!Array.isArray(extraArgs) ||
112989
- !extraArgs.every((value) => typeof value === "string")) {
112990
- return [];
112943
+ // src/consts.ts
112944
+ var HUB_URL = "https://huggingface.co";
112945
+
112946
+ // src/error.ts
112947
+ async function createApiError(response, opts) {
112948
+ const error = new HubApiError(response.url, response.status, response.headers.get("X-Request-Id") ?? opts?.requestId);
112949
+ error.message = `Api error with status ${error.statusCode}${""}`;
112950
+ const trailer = [`URL: ${error.url}`, error.requestId ? `Request ID: ${error.requestId}` : void 0].filter(Boolean).join(". ");
112951
+ if (response.headers.get("Content-Type")?.startsWith("application/json")) {
112952
+ const json = await response.json();
112953
+ error.message = json.error || json.message || error.message;
112954
+ if (json.error_description) {
112955
+ error.message = error.message ? error.message + `: ${json.error_description}` : json.error_description;
112991
112956
  }
112992
- return extraArgs.flatMap(tokenizeShellLine);
112957
+ error.data = json;
112958
+ } else {
112959
+ error.data = { message: await response.text() };
112960
+ }
112961
+ error.message += `. ${trailer}`;
112962
+ throw error;
112993
112963
  }
112994
- function tokenizeShellLine(input) {
112995
- const tokens = [];
112996
- let buffer = "";
112997
- let inQuote = null;
112998
- let hasBuffer = false;
112999
- for (let index = 0; index < input.length; index += 1) {
113000
- const char = input[index];
113001
- if (inQuote) {
113002
- if (char === inQuote) {
113003
- inQuote = null;
113004
- }
113005
- else {
113006
- buffer += char;
113007
- }
113008
- hasBuffer = true;
113009
- }
113010
- else if (char === '"' || char === "'") {
113011
- inQuote = char;
113012
- hasBuffer = true;
113013
- }
113014
- else if (char === " " || char === "\t") {
113015
- if (hasBuffer) {
113016
- tokens.push(buffer);
113017
- buffer = "";
113018
- hasBuffer = false;
113019
- }
113020
- }
113021
- else {
113022
- buffer += char;
113023
- hasBuffer = true;
113024
- }
112964
+ var HubApiError = class extends Error {
112965
+ statusCode;
112966
+ url;
112967
+ requestId;
112968
+ data;
112969
+ constructor(url, statusCode, requestId, message) {
112970
+ super(message);
112971
+ this.statusCode = statusCode;
112972
+ this.requestId = requestId;
112973
+ this.url = url;
112974
+ }
112975
+ };
112976
+ var InvalidApiResponseFormatError = class extends Error {
112977
+ };
112978
+
112979
+ // src/utils/checkCredentials.ts
112980
+ function checkAccessToken(accessToken) {
112981
+ if (!accessToken.startsWith("hf_")) {
112982
+ throw new TypeError("Your access token must start with 'hf_'");
112983
+ }
112984
+ }
112985
+ function checkCredentials(params) {
112986
+ if (params.accessToken) {
112987
+ checkAccessToken(params.accessToken);
112988
+ return params.accessToken;
112989
+ }
112990
+ if (params.credentials?.accessToken) {
112991
+ checkAccessToken(params.credentials.accessToken);
112992
+ return params.credentials.accessToken;
112993
+ }
112994
+ }
112995
+
112996
+ // src/utils/toRepoId.ts
112997
+ function toRepoId(repo) {
112998
+ if (typeof repo !== "string") {
112999
+ return repo;
113000
+ }
113001
+ if (repo.startsWith("model/") || repo.startsWith("models/")) {
113002
+ throw new TypeError(
113003
+ "A repo designation for a model should not start with 'models/', directly specify the model namespace / name"
113004
+ );
113005
+ }
113006
+ if (repo.startsWith("space/")) {
113007
+ throw new TypeError("Spaces should start with 'spaces/', plural, not 'space/'");
113008
+ }
113009
+ if (repo.startsWith("dataset/")) {
113010
+ throw new TypeError("Datasets should start with 'dataset/', plural, not 'dataset/'");
113011
+ }
113012
+ const slashes = repo.split("/").length - 1;
113013
+ if (repo.startsWith("spaces/")) {
113014
+ if (slashes !== 2) {
113015
+ throw new TypeError("Space Id must include namespace and name of the space");
113025
113016
  }
113026
- if (hasBuffer) {
113027
- tokens.push(buffer);
113017
+ return {
113018
+ type: "space",
113019
+ name: repo.slice("spaces/".length)
113020
+ };
113021
+ }
113022
+ if (repo.startsWith("datasets/")) {
113023
+ if (slashes > 2) {
113024
+ throw new TypeError("Too many slashes in repo designation: " + repo);
113028
113025
  }
113029
- return tokens;
113026
+ return {
113027
+ type: "dataset",
113028
+ name: repo.slice("datasets/".length)
113029
+ };
113030
+ }
113031
+ if (slashes > 1) {
113032
+ throw new TypeError("Too many slashes in repo designation: " + repo);
113033
+ }
113034
+ return {
113035
+ type: "model",
113036
+ name: repo
113037
+ };
113030
113038
  }
113039
+ new Promise((r) => {
113040
+ });
113031
113041
 
113032
- const balanced = (a, b, str) => {
113033
- const ma = a instanceof RegExp ? maybeMatch(a, str) : a;
113034
- const mb = b instanceof RegExp ? maybeMatch(b, str) : b;
113035
- const r = ma !== null && mb != null && range(ma, mb, str);
113036
- return (r && {
113037
- start: r[0],
113038
- end: r[1],
113039
- pre: str.slice(0, r[0]),
113040
- body: str.slice(r[0] + ma.length, r[1]),
113041
- post: str.slice(r[1] + mb.length),
113042
- });
113043
- };
113044
- const maybeMatch = (reg, str) => {
113045
- const m = str.match(reg);
113046
- return m ? m[0] : null;
113042
+ // src/utils/combineUint8Arrays.ts
113043
+ function combineUint8Arrays(a, b) {
113044
+ const aLength = a.length;
113045
+ const combinedBytes = new Uint8Array(aLength + b.length);
113046
+ combinedBytes.set(a);
113047
+ combinedBytes.set(b, aLength);
113048
+ return combinedBytes;
113049
+ }
113050
+ function readU64(b, n) {
113051
+ let x = 0;
113052
+ x |= b[n++] << 0;
113053
+ x |= b[n++] << 8;
113054
+ x |= b[n++] << 16;
113055
+ x |= b[n++] << 24;
113056
+ x |= b[n++] << 32;
113057
+ x |= b[n++] << 40;
113058
+ x |= b[n++] << 48;
113059
+ x |= b[n++] << 56;
113060
+ return x;
113061
+ }
113062
+ function readU32(b, n) {
113063
+ let x = 0;
113064
+ x |= b[n++] << 0;
113065
+ x |= b[n++] << 8;
113066
+ x |= b[n++] << 16;
113067
+ x |= b[n++] << 24;
113068
+ return x;
113069
+ }
113070
+
113071
+ // src/vendor/lz4js/index.ts
113072
+ var minMatch = 4;
113073
+ var hashSize = 1 << 16;
113074
+ makeHashTable();
113075
+ var magicNum = 407708164;
113076
+ var fdContentChksum = 4;
113077
+ var fdContentSize = 8;
113078
+ var fdBlockChksum = 16;
113079
+ var fdVersion = 64;
113080
+ var fdVersionMask = 192;
113081
+ var bsUncompressed = 2147483648;
113082
+ var bsShift = 4;
113083
+ var bsMask = 7;
113084
+ var bsMap = {
113085
+ 4: 65536,
113086
+ 5: 262144,
113087
+ 6: 1048576,
113088
+ 7: 4194304
113047
113089
  };
113048
- const range = (a, b, str) => {
113049
- let begs, beg, left, right = undefined, result;
113050
- let ai = str.indexOf(a);
113051
- let bi = str.indexOf(b, ai + 1);
113052
- let i = ai;
113053
- if (ai >= 0 && bi > 0) {
113054
- if (a === b) {
113055
- return [ai, bi];
113056
- }
113057
- begs = [];
113058
- left = str.length;
113059
- while (i >= 0 && !result) {
113060
- if (i === ai) {
113061
- begs.push(i);
113062
- ai = str.indexOf(a, i + 1);
113063
- }
113064
- else if (begs.length === 1) {
113065
- const r = begs.pop();
113066
- if (r !== undefined)
113067
- result = [r, bi];
113068
- }
113069
- else {
113070
- beg = begs.pop();
113071
- if (beg !== undefined && beg < left) {
113072
- left = beg;
113073
- right = bi;
113074
- }
113075
- bi = str.indexOf(b, i + 1);
113076
- }
113077
- i = ai < bi && ai >= 0 ? ai : bi;
113078
- }
113079
- if (begs.length && right !== undefined) {
113080
- result = [left, right];
113081
- }
113090
+ function makeHashTable() {
113091
+ try {
113092
+ return new Uint32Array(hashSize);
113093
+ } catch (error) {
113094
+ const hashTable2 = new Array(hashSize);
113095
+ for (let i = 0; i < hashSize; i++) {
113096
+ hashTable2[i] = 0;
113082
113097
  }
113083
- return result;
113084
- };
113085
-
113086
- const escSlash = '\0SLASH' + Math.random() + '\0';
113087
- const escOpen = '\0OPEN' + Math.random() + '\0';
113088
- const escClose = '\0CLOSE' + Math.random() + '\0';
113089
- const escComma = '\0COMMA' + Math.random() + '\0';
113090
- const escPeriod = '\0PERIOD' + Math.random() + '\0';
113091
- const escSlashPattern = new RegExp(escSlash, 'g');
113092
- const escOpenPattern = new RegExp(escOpen, 'g');
113093
- const escClosePattern = new RegExp(escClose, 'g');
113094
- const escCommaPattern = new RegExp(escComma, 'g');
113095
- const escPeriodPattern = new RegExp(escPeriod, 'g');
113096
- const slashPattern = /\\\\/g;
113097
- const openPattern = /\\{/g;
113098
- const closePattern = /\\}/g;
113099
- const commaPattern = /\\,/g;
113100
- const periodPattern = /\\\./g;
113101
- const EXPANSION_MAX = 100_000;
113102
- // `EXPANSION_MAX` caps the *number* of expansions, but not their length. An
113103
- // input like `'{a,b}'.repeat(1500)` stays under that count - its output is
113104
- // truncated to 100k results - while making every result ~1500 characters
113105
- // long. The result set, and the intermediate arrays built while combining
113106
- // brace sets, then grow large enough to exhaust memory and crash the process
113107
- // (CVE-2026-14257). `EXPANSION_MAX_LENGTH` bounds the total number of
113108
- // characters the accumulator may hold at any point, so memory stays flat no
113109
- // matter how many brace groups are chained. The limit sits well above any
113110
- // realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M
113111
- // characters) so legitimate input is unaffected.
113112
- const EXPANSION_MAX_LENGTH = 4_000_000;
113113
- function numeric(str) {
113114
- return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
113098
+ return hashTable2;
113099
+ }
113115
113100
  }
113116
- function escapeBraces(str) {
113117
- return str
113118
- .replace(slashPattern, escSlash)
113119
- .replace(openPattern, escOpen)
113120
- .replace(closePattern, escClose)
113121
- .replace(commaPattern, escComma)
113122
- .replace(periodPattern, escPeriod);
113101
+ function makeBuffer(size) {
113102
+ return new Uint8Array(size);
113123
113103
  }
113124
- function unescapeBraces(str) {
113125
- return str
113126
- .replace(escSlashPattern, '\\')
113127
- .replace(escOpenPattern, '{')
113128
- .replace(escClosePattern, '}')
113129
- .replace(escCommaPattern, ',')
113130
- .replace(escPeriodPattern, '.');
113104
+ function sliceArray(array, start, end) {
113105
+ return array.slice(start, end);
113131
113106
  }
113132
- /**
113133
- * Basically just str.split(","), but handling cases
113134
- * where we have nested braced sections, which should be
113135
- * treated as individual members, like {a,{b,c},d}
113136
- */
113137
- function parseCommaParts(str) {
113138
- if (!str) {
113139
- return [''];
113107
+ function decompressBound(src) {
113108
+ let sIndex = 0;
113109
+ if (readU32(src, sIndex) !== magicNum) {
113110
+ throw new Error("invalid magic number");
113111
+ }
113112
+ sIndex += 4;
113113
+ const descriptor = src[sIndex++];
113114
+ if ((descriptor & fdVersionMask) !== fdVersion) {
113115
+ throw new Error("incompatible descriptor version " + (descriptor & fdVersionMask));
113116
+ }
113117
+ const useBlockSum = (descriptor & fdBlockChksum) !== 0;
113118
+ const useContentSize = (descriptor & fdContentSize) !== 0;
113119
+ const bsIdx = src[sIndex++] >> bsShift & bsMask;
113120
+ if (bsMap[bsIdx] === void 0) {
113121
+ throw new Error("invalid block size " + bsIdx);
113122
+ }
113123
+ const maxBlockSize = bsMap[bsIdx];
113124
+ if (useContentSize) {
113125
+ return readU64(src, sIndex);
113126
+ }
113127
+ sIndex++;
113128
+ let maxSize = 0;
113129
+ while (true) {
113130
+ let blockSize = readU32(src, sIndex);
113131
+ sIndex += 4;
113132
+ if (blockSize & bsUncompressed) {
113133
+ blockSize &= ~bsUncompressed;
113134
+ maxSize += blockSize;
113135
+ } else if (blockSize > 0) {
113136
+ maxSize += maxBlockSize;
113140
113137
  }
113141
- const parts = [];
113142
- const m = balanced('{', '}', str);
113143
- if (!m) {
113144
- return str.split(',');
113138
+ if (blockSize === 0) {
113139
+ return maxSize;
113145
113140
  }
113146
- const { pre, body, post } = m;
113147
- const p = pre.split(',');
113148
- p[p.length - 1] += '{' + body + '}';
113149
- const postParts = parseCommaParts(post);
113150
- if (post.length) {
113151
- p[p.length - 1] += postParts.shift();
113152
- p.push.apply(p, postParts);
113141
+ if (useBlockSum) {
113142
+ sIndex += 4;
113153
113143
  }
113154
- parts.push.apply(parts, p);
113155
- return parts;
113144
+ sIndex += blockSize;
113145
+ }
113156
113146
  }
113157
- function expand(str, options = {}) {
113158
- if (!str) {
113159
- return [];
113147
+ function decompressBlock(src, dst, sIndex, sLength, dIndex) {
113148
+ let mLength, mOffset, sEnd, n, i;
113149
+ const hasCopyWithin = dst.copyWithin !== void 0 && dst.fill !== void 0;
113150
+ sEnd = sIndex + sLength;
113151
+ while (sIndex < sEnd) {
113152
+ const token = src[sIndex++];
113153
+ let literalCount = token >> 4;
113154
+ if (literalCount > 0) {
113155
+ if (literalCount === 15) {
113156
+ while (true) {
113157
+ literalCount += src[sIndex];
113158
+ if (src[sIndex++] !== 255) {
113159
+ break;
113160
+ }
113161
+ }
113162
+ }
113163
+ for (n = sIndex + literalCount; sIndex < n; ) {
113164
+ dst[dIndex++] = src[sIndex++];
113165
+ }
113160
113166
  }
113161
- const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH } = options;
113162
- // I don't know why Bash 4.3 does this, but it does.
113163
- // Anything starting with {} will have the first two bytes preserved
113164
- // but *only* at the top level, so {},a}b will not expand to anything,
113165
- // but a{},b}c will be expanded to [a}c,abc].
113166
- // One could argue that this is a bug in Bash, but since the goal of
113167
- // this module is to match Bash's rules, we escape a leading {}
113168
- if (str.slice(0, 2) === '{}') {
113169
- str = '\\{\\}' + str.slice(2);
113167
+ if (sIndex >= sEnd) {
113168
+ break;
113170
113169
  }
113171
- return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
113172
- }
113173
- function embrace(str) {
113174
- return '{' + str + '}';
113175
- }
113176
- function isPadded(el) {
113177
- return /^-?0\d/.test(el);
113178
- }
113179
- function lte(i, y) {
113180
- return i <= y;
113181
- }
113182
- function gte(i, y) {
113183
- return i >= y;
113184
- }
113185
- // Build `{ acc[a] + pre + values[v] }` for every combination, capping the
113186
- // number of results at `max` and the total number of characters at `maxLength`.
113187
- // This is the one place output grows, so bounding it here keeps the single
113188
- // accumulator - and therefore memory - flat regardless of how many brace groups
113189
- // are combined (CVE-2026-14257).
113190
- function combine(acc, pre, values, max, maxLength, dropEmpties) {
113191
- const out = [];
113192
- let length = 0;
113193
- for (let a = 0; a < acc.length; a++) {
113194
- for (let v = 0; v < values.length; v++) {
113195
- if (out.length >= max)
113196
- return out;
113197
- const expansion = acc[a] + pre + values[v];
113198
- // Bash drops empty results at the top level. Skip them before they count
113199
- // against `max`, so `max` bounds the number of *kept* results.
113200
- if (dropEmpties && !expansion)
113201
- continue;
113202
- if (length + expansion.length > maxLength)
113203
- return out;
113204
- out.push(expansion);
113205
- length += expansion.length;
113170
+ mLength = token & 15;
113171
+ mOffset = src[sIndex++] | src[sIndex++] << 8;
113172
+ if (mLength === 15) {
113173
+ while (true) {
113174
+ mLength += src[sIndex];
113175
+ if (src[sIndex++] !== 255) {
113176
+ break;
113206
113177
  }
113178
+ }
113207
113179
  }
113208
- return out;
113180
+ mLength += minMatch;
113181
+ if (hasCopyWithin && mOffset === 1) {
113182
+ dst.fill(dst[dIndex - 1] | 0, dIndex, dIndex + mLength);
113183
+ dIndex += mLength;
113184
+ } else if (hasCopyWithin && mOffset > mLength && mLength > 31) {
113185
+ dst.copyWithin(dIndex, dIndex - mOffset, dIndex - mOffset + mLength);
113186
+ dIndex += mLength;
113187
+ } else {
113188
+ for (i = dIndex - mOffset, n = i + mLength; i < n; ) {
113189
+ dst[dIndex++] = dst[i++] | 0;
113190
+ }
113191
+ }
113192
+ }
113193
+ return dIndex;
113209
113194
  }
113210
- // The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)
113211
- // sequence body.
113212
- function expandSequence(body, isAlphaSequence, max, maxLength) {
113213
- const n = body.split(/\.\./);
113214
- const N = [];
113215
- // A sequence body always splits into two or three parts, but the compiler
113216
- // can't know that.
113217
- /* c8 ignore start */
113218
- if (n[0] === undefined || n[1] === undefined) {
113219
- return N;
113195
+ function decompressFrame(src, dst) {
113196
+ let useBlockSum, useContentSum, useContentSize, descriptor;
113197
+ let sIndex = 0;
113198
+ let dIndex = 0;
113199
+ if (readU32(src, sIndex) !== magicNum) {
113200
+ throw new Error("invalid magic number");
113201
+ }
113202
+ sIndex += 4;
113203
+ descriptor = src[sIndex++];
113204
+ if ((descriptor & fdVersionMask) !== fdVersion) {
113205
+ throw new Error("incompatible descriptor version");
113206
+ }
113207
+ useBlockSum = (descriptor & fdBlockChksum) !== 0;
113208
+ useContentSum = (descriptor & fdContentChksum) !== 0;
113209
+ useContentSize = (descriptor & fdContentSize) !== 0;
113210
+ const bsIdx = src[sIndex++] >> bsShift & bsMask;
113211
+ if (bsMap[bsIdx] === void 0) {
113212
+ throw new Error("invalid block size");
113213
+ }
113214
+ if (useContentSize) {
113215
+ sIndex += 8;
113216
+ }
113217
+ sIndex++;
113218
+ while (true) {
113219
+ var compSize;
113220
+ compSize = readU32(src, sIndex);
113221
+ sIndex += 4;
113222
+ if (compSize === 0) {
113223
+ break;
113220
113224
  }
113221
- /* c8 ignore stop */
113222
- const x = numeric(n[0]);
113223
- const y = numeric(n[1]);
113224
- const width = Math.max(n[0].length, n[1].length);
113225
- let incr = n.length === 3 && n[2] !== undefined ?
113226
- Math.max(Math.abs(numeric(n[2])), 1)
113227
- : 1;
113228
- let test = lte;
113229
- const reverse = y < x;
113230
- if (reverse) {
113231
- incr *= -1;
113232
- test = gte;
113225
+ if (useBlockSum) {
113226
+ sIndex += 4;
113233
113227
  }
113234
- const pad = n.some(isPadded);
113235
- let length = 0;
113236
- for (let i = x; test(i, y) && N.length < max; i += incr) {
113237
- let c;
113238
- if (isAlphaSequence) {
113239
- c = String.fromCharCode(i);
113240
- if (c === '\\') {
113241
- c = '';
113242
- }
113243
- }
113244
- else {
113245
- c = String(i);
113246
- if (pad) {
113247
- const need = width - c.length;
113248
- if (need > 0) {
113249
- const z = new Array(need + 1).join('0');
113250
- if (i < 0) {
113251
- c = '-' + z + c.slice(1);
113252
- }
113253
- else {
113254
- c = z + c;
113255
- }
113256
- }
113257
- }
113258
- }
113259
- if (length + c.length > maxLength)
113260
- break;
113261
- N.push(c);
113262
- length += c.length;
113228
+ if ((compSize & bsUncompressed) !== 0) {
113229
+ compSize &= ~bsUncompressed;
113230
+ for (let j = 0; j < compSize; j++) {
113231
+ dst[dIndex++] = src[sIndex++];
113232
+ }
113233
+ } else {
113234
+ dIndex = decompressBlock(src, dst, sIndex, compSize, dIndex);
113235
+ sIndex += compSize;
113263
113236
  }
113264
- return N;
113237
+ }
113238
+ if (useContentSum) {
113239
+ sIndex += 4;
113240
+ }
113241
+ return dIndex;
113265
113242
  }
113266
- function expand_(str, max, maxLength, isTop) {
113267
- // Consume the string's top-level brace groups left to right, threading a
113268
- // running set of combined prefixes (`acc`). Expanding the tail iteratively -
113269
- // rather than recursing on `m.post` once per group - keeps the native stack
113270
- // depth constant, so deeply chained input (`'{a,b}'.repeat(3000)`) can no
113271
- // longer overflow the stack, and leaves a single accumulator whose size
113272
- // `maxLength` bounds directly (CVE-2026-14257).
113273
- let acc = [''];
113274
- // Bash drops empty results, but only when the *first* top-level group is a
113275
- // comma set - a sequence like `{a..\}` may legitimately yield ''. The drop
113276
- // is on the final strings, so it is applied to whichever `combine` produces
113277
- // them (the one with no brace set left in the tail).
113278
- let dropEmpties = false;
113279
- let firstGroup = true;
113280
- for (;;) {
113281
- const m = balanced('{', '}', str);
113282
- // No brace set left: the rest of the string is literal.
113283
- if (!m) {
113284
- return combine(acc, str, [''], max, maxLength, dropEmpties);
113285
- }
113286
- // no need to expand pre, since it is guaranteed to be free of brace-sets
113287
- const pre = m.pre;
113288
- if (/\$$/.test(pre)) {
113289
- acc = combine(acc, pre + '{' + m.body + '}', [''], max, maxLength, dropEmpties && !m.post.length);
113290
- firstGroup = false;
113291
- if (!m.post.length)
113292
- break;
113293
- str = m.post;
113294
- continue;
113295
- }
113296
- const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
113297
- const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
113298
- const isSequence = isNumericSequence || isAlphaSequence;
113299
- const isOptions = m.body.indexOf(',') >= 0;
113300
- if (!isSequence && !isOptions) {
113301
- // {a},b}
113302
- if (m.post.match(/,(?!,).*\}/)) {
113303
- str = m.pre + '{' + m.body + escClose + m.post;
113304
- isTop = true;
113305
- continue;
113306
- }
113307
- // Nothing here expands, so the whole remaining string is literal.
113308
- return combine(acc, pre + '{' + m.body + '}' + m.post, [''], max, maxLength, dropEmpties);
113309
- }
113310
- if (firstGroup) {
113311
- dropEmpties = isTop && !isSequence;
113312
- firstGroup = false;
113313
- }
113314
- let values;
113315
- if (isSequence) {
113316
- values = expandSequence(m.body, isAlphaSequence, max, maxLength);
113317
- }
113318
- else {
113319
- let n = parseCommaParts(m.body);
113320
- if (n.length === 1 && n[0] !== undefined) {
113321
- // x{{a,b}}y ==> x{a}y x{b}y
113322
- n = expand_(n[0], max, maxLength, false).map(embrace);
113323
- //XXX is this necessary? Can't seem to hit it in tests.
113324
- /* c8 ignore start */
113325
- if (n.length === 1) {
113326
- acc = combine(acc, pre + n[0], [''], max, maxLength, dropEmpties && !m.post.length);
113327
- if (!m.post.length)
113328
- break;
113329
- str = m.post;
113330
- continue;
113331
- }
113332
- /* c8 ignore stop */
113333
- }
113334
- // Values that `combine` is going to drop as empty produce no result, so
113335
- // they must not count against `max` - otherwise `{a,,b}` with `max: 2`
113336
- // would stop at `['a', '']` and yield one result instead of two. Skipping
113337
- // them outright keeps `values` bounded while leaving `max` a bound on
113338
- // *kept* results.
113339
- let dropsEmpties = dropEmpties && !m.post.length && !pre;
113340
- for (let d = 0; dropsEmpties && d < acc.length; d++) {
113341
- if (acc[d]) {
113342
- dropsEmpties = false;
113343
- }
113344
- }
113345
- values = [];
113346
- let valuesLength = 0;
113347
- outer: for (let j = 0; j < n.length; j++) {
113348
- const expanded = expand_(n[j], max, maxLength, false);
113349
- for (let k = 0; k < expanded.length; k++) {
113350
- const v = expanded[k];
113351
- if (dropsEmpties && !v)
113352
- continue;
113353
- if (values.length >= max || valuesLength + v.length > maxLength) {
113354
- break outer;
113355
- }
113356
- values.push(v);
113357
- valuesLength += v.length;
113358
- }
113359
- }
113360
- }
113361
- acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length);
113362
- if (!m.post.length)
113363
- break;
113364
- str = m.post;
113365
- }
113366
- return acc;
113243
+ function decompress(src, maxSize) {
113244
+ let dst, size;
113245
+ if (maxSize === void 0) {
113246
+ maxSize = decompressBound(src);
113247
+ }
113248
+ dst = makeBuffer(maxSize);
113249
+ size = decompressFrame(src, dst);
113250
+ if (size !== maxSize) {
113251
+ dst = sliceArray(dst, 0, size);
113252
+ }
113253
+ return dst;
113367
113254
  }
113368
113255
 
113369
- const MAX_PATTERN_LENGTH = 1024 * 64;
113370
- const assertValidPattern = (pattern) => {
113371
- if (typeof pattern !== 'string') {
113372
- throw new TypeError('invalid pattern');
113256
+ // src/utils/RangeList.ts
113257
+ var RangeList = class {
113258
+ ranges = [];
113259
+ /**
113260
+ * Add a range to the list. If it overlaps with existing ranges,
113261
+ * it will split them and increment reference counts accordingly.
113262
+ */
113263
+ add(start, end) {
113264
+ if (end <= start) {
113265
+ throw new TypeError("End must be greater than start");
113373
113266
  }
113374
- if (pattern.length > MAX_PATTERN_LENGTH) {
113375
- throw new TypeError('pattern is too long');
113267
+ const overlappingRanges = [];
113268
+ for (let i = 0; i < this.ranges.length; i++) {
113269
+ const range2 = this.ranges[i];
113270
+ if (start < range2.end && end > range2.start) {
113271
+ overlappingRanges.push({ index: i, range: range2 });
113272
+ }
113273
+ if (range2.data !== null) {
113274
+ throw new Error("Overlapping range already has data");
113275
+ }
113276
+ }
113277
+ if (overlappingRanges.length === 0) {
113278
+ this.ranges.push({ start, end, refCount: 1, data: null });
113279
+ this.ranges.sort((a, b) => a.start - b.start);
113280
+ return;
113281
+ }
113282
+ const newRanges = [];
113283
+ let currentPos = start;
113284
+ for (let i = 0; i < overlappingRanges.length; i++) {
113285
+ const { range: range2 } = overlappingRanges[i];
113286
+ if (currentPos < range2.start) {
113287
+ newRanges.push({
113288
+ start: currentPos,
113289
+ end: range2.start,
113290
+ refCount: 1,
113291
+ data: null
113292
+ });
113293
+ } else if (range2.start < currentPos) {
113294
+ newRanges.push({
113295
+ start: range2.start,
113296
+ end: currentPos,
113297
+ refCount: range2.refCount,
113298
+ data: null
113299
+ });
113300
+ }
113301
+ newRanges.push({
113302
+ start: Math.max(currentPos, range2.start),
113303
+ end: Math.min(end, range2.end),
113304
+ refCount: range2.refCount + 1,
113305
+ data: null
113306
+ });
113307
+ if (range2.end > end) {
113308
+ newRanges.push({
113309
+ start: end,
113310
+ end: range2.end,
113311
+ refCount: range2.refCount,
113312
+ data: null
113313
+ });
113314
+ }
113315
+ currentPos = Math.max(currentPos, range2.end);
113316
+ }
113317
+ if (currentPos < end) {
113318
+ newRanges.push({
113319
+ start: currentPos,
113320
+ end,
113321
+ refCount: 1,
113322
+ data: null
113323
+ });
113324
+ }
113325
+ const firstIndex = overlappingRanges[0].index;
113326
+ const lastIndex = overlappingRanges[overlappingRanges.length - 1].index;
113327
+ this.ranges.splice(firstIndex, lastIndex - firstIndex + 1, ...newRanges);
113328
+ this.ranges.sort((a, b) => a.start - b.start);
113329
+ }
113330
+ /**
113331
+ * Remove a range from the list. The range must start and end at existing boundaries.
113332
+ */
113333
+ remove(start, end) {
113334
+ if (end <= start) {
113335
+ throw new TypeError("End must be greater than start");
113336
+ }
113337
+ const affectedRanges = [];
113338
+ for (let i = 0; i < this.ranges.length; i++) {
113339
+ const range2 = this.ranges[i];
113340
+ if (start < range2.end && end > range2.start) {
113341
+ affectedRanges.push({ index: i, range: range2 });
113342
+ }
113343
+ }
113344
+ if (affectedRanges.length === 0) {
113345
+ throw new Error("No ranges found to remove");
113346
+ }
113347
+ if (start !== affectedRanges[0].range.start || end !== affectedRanges[affectedRanges.length - 1].range.end) {
113348
+ throw new Error("Range boundaries must match existing boundaries");
113349
+ }
113350
+ for (let i = 0; i < affectedRanges.length; i++) {
113351
+ const { range: range2 } = affectedRanges[i];
113352
+ range2.refCount--;
113353
+ }
113354
+ this.ranges = this.ranges.filter((range2) => range2.refCount > 0);
113355
+ }
113356
+ /**
113357
+ * Get all ranges within the specified boundaries.
113358
+ */
113359
+ getRanges(start, end) {
113360
+ if (end <= start) {
113361
+ throw new TypeError("End must be greater than start");
113376
113362
  }
113363
+ return this.ranges.filter((range2) => start < range2.end && end > range2.start);
113364
+ }
113365
+ /**
113366
+ * Get all ranges in the list
113367
+ */
113368
+ getAllRanges() {
113369
+ return [...this.ranges];
113370
+ }
113377
113371
  };
113378
113372
 
113379
- // translate the various posix character classes into unicode properties
113380
- // this works across all unicode locales
113381
- // { <posix class>: [<translation>, /u flag required, negated]
113382
- const posixClasses = {
113383
- '[:alnum:]': ['\\p{L}\\p{Nl}\\p{Nd}', true],
113384
- '[:alpha:]': ['\\p{L}\\p{Nl}', true],
113385
- '[:ascii:]': ['\\x' + '00-\\x' + '7f', false],
113386
- '[:blank:]': ['\\p{Zs}\\t', true],
113387
- '[:cntrl:]': ['\\p{Cc}', true],
113388
- '[:digit:]': ['\\p{Nd}', true],
113389
- '[:graph:]': ['\\p{Z}\\p{C}', true, true],
113390
- '[:lower:]': ['\\p{Ll}', true],
113391
- '[:print:]': ['\\p{C}', true],
113392
- '[:punct:]': ['\\p{P}', true],
113393
- '[:space:]': ['\\p{Z}\\t\\r\\n\\v\\f', true],
113394
- '[:upper:]': ['\\p{Lu}', true],
113395
- '[:word:]': ['\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}', true],
113396
- '[:xdigit:]': ['A-Fa-f0-9', false],
113397
- };
113398
- // only need to escape a few things inside of brace expressions
113399
- // escapes: [ \ ] -
113400
- const braceEscape = (s) => s.replace(/[[\]\\-]/g, '\\$&');
113401
- // escape all regexp magic characters
113373
+ // src/utils/XetBlob.ts
113374
+ var JWT_SAFETY_PERIOD = 6e4;
113375
+ var JWT_CACHE_SIZE = 1e3;
113376
+ var compressionSchemeLabels = {
113377
+ [0 /* None */]: "None",
113378
+ [1 /* LZ4 */]: "LZ4",
113379
+ [2 /* ByteGroupingLZ4 */]: "ByteGroupingLZ4"
113380
+ };
113381
+ var XET_CHUNK_HEADER_BYTES = 8;
113382
+ var XetBlob = class extends Blob {
113383
+ fetch;
113384
+ accessToken;
113385
+ refreshUrl;
113386
+ reconstructionUrl;
113387
+ hash;
113388
+ start = 0;
113389
+ end = 0;
113390
+ internalLogging = false;
113391
+ reconstructionInfo;
113392
+ listener;
113393
+ constructor(params) {
113394
+ super([]);
113395
+ this.fetch = params.fetch ?? fetch.bind(globalThis);
113396
+ this.accessToken = checkCredentials(params);
113397
+ this.refreshUrl = params.refreshUrl;
113398
+ this.end = params.size;
113399
+ this.reconstructionUrl = params.reconstructionUrl;
113400
+ this.hash = params.hash;
113401
+ this.listener = params.listener;
113402
+ this.internalLogging = params.internalLogging ?? false;
113403
+ this.refreshUrl;
113404
+ }
113405
+ get size() {
113406
+ return this.end - this.start;
113407
+ }
113408
+ #clone() {
113409
+ const blob = new XetBlob({
113410
+ fetch: this.fetch,
113411
+ hash: this.hash,
113412
+ refreshUrl: this.refreshUrl,
113413
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
113414
+ reconstructionUrl: this.reconstructionUrl,
113415
+ size: this.size
113416
+ });
113417
+ blob.accessToken = this.accessToken;
113418
+ blob.start = this.start;
113419
+ blob.end = this.end;
113420
+ blob.reconstructionInfo = this.reconstructionInfo;
113421
+ blob.listener = this.listener;
113422
+ blob.internalLogging = this.internalLogging;
113423
+ return blob;
113424
+ }
113425
+ slice(start = 0, end = this.size) {
113426
+ const slice = this.#clone();
113427
+ slice.start = this.start + start;
113428
+ slice.end = Math.min(this.start + end, this.end);
113429
+ if (slice.start !== this.start || slice.end !== this.end) {
113430
+ slice.reconstructionInfo = void 0;
113431
+ }
113432
+ return slice;
113433
+ }
113434
+ #reconstructionInfoPromise;
113435
+ #loadReconstructionInfo() {
113436
+ if (this.#reconstructionInfoPromise) {
113437
+ return this.#reconstructionInfoPromise;
113438
+ }
113439
+ this.#reconstructionInfoPromise = (async () => {
113440
+ const connParams = await getAccessToken(this.accessToken, this.fetch, this.refreshUrl);
113441
+ const resp = await this.fetch(this.reconstructionUrl ?? `${connParams.casUrl}/v1/reconstructions/${this.hash}`, {
113442
+ headers: {
113443
+ Authorization: `Bearer ${connParams.accessToken}`,
113444
+ Range: `bytes=${this.start}-${this.end - 1}`
113445
+ }
113446
+ });
113447
+ if (!resp.ok) {
113448
+ throw await createApiError(resp);
113449
+ }
113450
+ this.reconstructionInfo = await resp.json();
113451
+ return this.reconstructionInfo;
113452
+ })().finally(() => this.#reconstructionInfoPromise = void 0);
113453
+ return this.#reconstructionInfoPromise;
113454
+ }
113455
+ async #fetch() {
113456
+ if (!this.reconstructionInfo) {
113457
+ await this.#loadReconstructionInfo();
113458
+ }
113459
+ const rangeLists = /* @__PURE__ */ new Map();
113460
+ if (!this.reconstructionInfo) {
113461
+ throw new Error("Failed to load reconstruction info");
113462
+ }
113463
+ for (const term of this.reconstructionInfo.terms) {
113464
+ let rangeList = rangeLists.get(term.hash);
113465
+ if (!rangeList) {
113466
+ rangeList = new RangeList();
113467
+ rangeLists.set(term.hash, rangeList);
113468
+ }
113469
+ rangeList.add(term.range.start, term.range.end);
113470
+ }
113471
+ const listener = this.listener;
113472
+ const log = this.internalLogging ? (...args) => console.log(...args) : () => {
113473
+ };
113474
+ async function* readData(reconstructionInfo, customFetch, maxBytes, reloadReconstructionInfo) {
113475
+ let totalBytesRead = 0;
113476
+ let readBytesToSkip = reconstructionInfo.offset_into_first_range;
113477
+ for (const term of reconstructionInfo.terms) {
113478
+ if (totalBytesRead >= maxBytes) {
113479
+ break;
113480
+ }
113481
+ const rangeList = rangeLists.get(term.hash);
113482
+ if (!rangeList) {
113483
+ throw new Error(`Failed to find range list for term ${term.hash}`);
113484
+ }
113485
+ {
113486
+ const termRanges = rangeList.getRanges(term.range.start, term.range.end);
113487
+ if (termRanges.every((range2) => range2.data)) {
113488
+ log("all data available for term", term.hash, readBytesToSkip);
113489
+ rangeLoop:
113490
+ for (const range2 of termRanges) {
113491
+ for (let chunk2 of range2.data) {
113492
+ if (readBytesToSkip) {
113493
+ const skipped = Math.min(readBytesToSkip, chunk2.byteLength);
113494
+ chunk2 = chunk2.slice(skipped);
113495
+ readBytesToSkip -= skipped;
113496
+ if (!chunk2.byteLength) {
113497
+ continue;
113498
+ }
113499
+ }
113500
+ if (chunk2.byteLength > maxBytes - totalBytesRead) {
113501
+ chunk2 = chunk2.slice(0, maxBytes - totalBytesRead);
113502
+ }
113503
+ totalBytesRead += chunk2.byteLength;
113504
+ yield range2.refCount > 1 ? chunk2.slice() : chunk2;
113505
+ listener?.({ event: "progress", progress: { read: totalBytesRead, total: maxBytes } });
113506
+ if (totalBytesRead >= maxBytes) {
113507
+ break rangeLoop;
113508
+ }
113509
+ }
113510
+ }
113511
+ rangeList.remove(term.range.start, term.range.end);
113512
+ continue;
113513
+ }
113514
+ }
113515
+ const fetchInfo = reconstructionInfo.fetch_info[term.hash].find(
113516
+ (info) => info.range.start <= term.range.start && info.range.end >= term.range.end
113517
+ );
113518
+ if (!fetchInfo) {
113519
+ throw new Error(
113520
+ `Failed to find fetch info for term ${term.hash} and range ${term.range.start}-${term.range.end}`
113521
+ );
113522
+ }
113523
+ log("term", term);
113524
+ log("fetchinfo", fetchInfo);
113525
+ log("readBytesToSkip", readBytesToSkip);
113526
+ let resp = await customFetch(fetchInfo.url, {
113527
+ headers: {
113528
+ Range: `bytes=${fetchInfo.url_range.start}-${fetchInfo.url_range.end}`
113529
+ }
113530
+ });
113531
+ if (resp.status === 403) {
113532
+ reconstructionInfo = await reloadReconstructionInfo();
113533
+ resp = await customFetch(fetchInfo.url, {
113534
+ headers: {
113535
+ Range: `bytes=${fetchInfo.url_range.start}-${fetchInfo.url_range.end}`
113536
+ }
113537
+ });
113538
+ }
113539
+ if (!resp.ok) {
113540
+ throw await createApiError(resp);
113541
+ }
113542
+ log(
113543
+ "expected content length",
113544
+ resp.headers.get("content-length"),
113545
+ "range",
113546
+ fetchInfo.url_range,
113547
+ resp.headers.get("content-range")
113548
+ );
113549
+ const reader = resp.body?.getReader();
113550
+ if (!reader) {
113551
+ throw new Error("Failed to get reader from response body");
113552
+ }
113553
+ let done = false;
113554
+ let chunkIndex = fetchInfo.range.start;
113555
+ const ranges = rangeList.getRanges(fetchInfo.range.start, fetchInfo.range.end);
113556
+ let leftoverBytes = void 0;
113557
+ let totalFetchBytes = 0;
113558
+ fetchData:
113559
+ while (!done && totalBytesRead < maxBytes) {
113560
+ const result = await reader.read();
113561
+ listener?.({ event: "read" });
113562
+ done = result.done;
113563
+ log("read", result.value?.byteLength, "bytes", "total read", totalBytesRead, "toSkip", readBytesToSkip);
113564
+ if (!result.value) {
113565
+ log("no data in result, cancelled", result);
113566
+ continue;
113567
+ }
113568
+ totalFetchBytes += result.value.byteLength;
113569
+ if (leftoverBytes) {
113570
+ result.value = combineUint8Arrays(leftoverBytes, result.value);
113571
+ leftoverBytes = void 0;
113572
+ }
113573
+ while (totalBytesRead < maxBytes && result.value?.byteLength) {
113574
+ if (result.value.byteLength < 8) {
113575
+ leftoverBytes = result.value;
113576
+ continue fetchData;
113577
+ }
113578
+ const header = new DataView(result.value.buffer, result.value.byteOffset, XET_CHUNK_HEADER_BYTES);
113579
+ const chunkHeader = {
113580
+ version: header.getUint8(0),
113581
+ compressed_length: header.getUint8(1) | header.getUint8(2) << 8 | header.getUint8(3) << 16,
113582
+ compression_scheme: header.getUint8(4),
113583
+ uncompressed_length: header.getUint8(5) | header.getUint8(6) << 8 | header.getUint8(7) << 16
113584
+ };
113585
+ log("chunk header", chunkHeader, "to skip", readBytesToSkip);
113586
+ if (chunkHeader.version !== 0) {
113587
+ throw new Error(`Unsupported chunk version ${chunkHeader.version}`);
113588
+ }
113589
+ if (chunkHeader.compression_scheme !== 0 /* None */ && chunkHeader.compression_scheme !== 1 /* LZ4 */ && chunkHeader.compression_scheme !== 2 /* ByteGroupingLZ4 */) {
113590
+ throw new Error(
113591
+ `Unsupported compression scheme ${compressionSchemeLabels[chunkHeader.compression_scheme] ?? chunkHeader.compression_scheme}`
113592
+ );
113593
+ }
113594
+ if (result.value.byteLength < chunkHeader.compressed_length + XET_CHUNK_HEADER_BYTES) {
113595
+ leftoverBytes = result.value;
113596
+ continue fetchData;
113597
+ }
113598
+ result.value = result.value.slice(XET_CHUNK_HEADER_BYTES);
113599
+ let uncompressed = chunkHeader.compression_scheme === 1 /* LZ4 */ ? decompress(result.value.slice(0, chunkHeader.compressed_length), chunkHeader.uncompressed_length) : chunkHeader.compression_scheme === 2 /* ByteGroupingLZ4 */ ? bg4_regroup_bytes(
113600
+ decompress(
113601
+ result.value.slice(0, chunkHeader.compressed_length),
113602
+ chunkHeader.uncompressed_length
113603
+ )
113604
+ ) : result.value.slice(0, chunkHeader.compressed_length);
113605
+ const range2 = ranges.find((range3) => chunkIndex >= range3.start && chunkIndex < range3.end);
113606
+ const shouldYield = chunkIndex >= term.range.start && chunkIndex < term.range.end;
113607
+ const minRefCountToStore = shouldYield ? 2 : 1;
113608
+ let stored = false;
113609
+ if (range2 && range2.refCount >= minRefCountToStore) {
113610
+ range2.data ??= [];
113611
+ range2.data.push(uncompressed);
113612
+ stored = true;
113613
+ }
113614
+ if (shouldYield) {
113615
+ if (readBytesToSkip) {
113616
+ const skipped = Math.min(readBytesToSkip, uncompressed.byteLength);
113617
+ uncompressed = uncompressed.slice(readBytesToSkip);
113618
+ readBytesToSkip -= skipped;
113619
+ }
113620
+ if (uncompressed.byteLength > maxBytes - totalBytesRead) {
113621
+ uncompressed = uncompressed.slice(0, maxBytes - totalBytesRead);
113622
+ }
113623
+ if (uncompressed.byteLength) {
113624
+ log(
113625
+ "yield",
113626
+ uncompressed.byteLength,
113627
+ "bytes",
113628
+ result.value.byteLength,
113629
+ "total read",
113630
+ totalBytesRead,
113631
+ stored
113632
+ );
113633
+ totalBytesRead += uncompressed.byteLength;
113634
+ yield stored ? uncompressed.slice() : uncompressed;
113635
+ listener?.({ event: "progress", progress: { read: totalBytesRead, total: maxBytes } });
113636
+ }
113637
+ }
113638
+ chunkIndex++;
113639
+ result.value = result.value.slice(chunkHeader.compressed_length);
113640
+ }
113641
+ }
113642
+ if (done && totalBytesRead < maxBytes && totalFetchBytes < fetchInfo.url_range.end - fetchInfo.url_range.start + 1) {
113643
+ log("done", done, "total read", totalBytesRead, maxBytes, totalFetchBytes);
113644
+ log("failed to fetch all data for term", term.hash);
113645
+ throw new Error(
113646
+ `Failed to fetch all data for term ${term.hash}, fetched ${totalFetchBytes} bytes out of ${fetchInfo.url_range.end - fetchInfo.url_range.start + 1}`
113647
+ );
113648
+ }
113649
+ log("done", done, "total read", totalBytesRead, maxBytes, totalFetchBytes);
113650
+ log("cancel reader");
113651
+ await reader.cancel();
113652
+ }
113653
+ }
113654
+ const iterator = readData(
113655
+ this.reconstructionInfo,
113656
+ this.fetch,
113657
+ this.end - this.start,
113658
+ this.#loadReconstructionInfo.bind(this)
113659
+ );
113660
+ return new ReadableStream(
113661
+ {
113662
+ // todo: when Safari supports it, type controller as ReadableByteStreamController
113663
+ async pull(controller) {
113664
+ const result = await iterator.next();
113665
+ if (result.value) {
113666
+ controller.enqueue(result.value);
113667
+ }
113668
+ if (result.done) {
113669
+ controller.close();
113670
+ }
113671
+ },
113672
+ type: "bytes"
113673
+ // todo: when Safari supports it, add autoAllocateChunkSize param
113674
+ },
113675
+ // todo : use ByteLengthQueuingStrategy when there's good support for it, currently in Node.js it fails due to size being a function
113676
+ {
113677
+ highWaterMark: 1e3
113678
+ // 1_000 chunks for ~1MB of RAM
113679
+ }
113680
+ );
113681
+ }
113682
+ async arrayBuffer() {
113683
+ const result = await this.#fetch();
113684
+ return new Response(result).arrayBuffer();
113685
+ }
113686
+ async text() {
113687
+ const result = await this.#fetch();
113688
+ return new Response(result).text();
113689
+ }
113690
+ async response() {
113691
+ const result = await this.#fetch();
113692
+ return new Response(result);
113693
+ }
113694
+ stream() {
113695
+ const stream = new TransformStream();
113696
+ this.#fetch().then((response) => response.pipeThrough(stream)).catch((error) => stream.writable.abort(error.message));
113697
+ return stream.readable;
113698
+ }
113699
+ };
113700
+ var jwtPromises = /* @__PURE__ */ new Map();
113701
+ var jwts = /* @__PURE__ */ new Map();
113702
+ function cacheKey(params) {
113703
+ return JSON.stringify([params.refreshUrl, params.initialAccessToken]);
113704
+ }
113705
+ function bg4_regroup_bytes(bytes) {
113706
+ const split = Math.floor(bytes.byteLength / 4);
113707
+ const rem = bytes.byteLength % 4;
113708
+ const g1_pos = split + (rem >= 1 ? 1 : 0);
113709
+ const g2_pos = g1_pos + split + (rem >= 2 ? 1 : 0);
113710
+ const g3_pos = g2_pos + split + (rem == 3 ? 1 : 0);
113711
+ const ret = new Uint8Array(bytes.byteLength);
113712
+ for (let i = 0, j = 0; i < bytes.byteLength; i += 4, j++) {
113713
+ ret[i] = bytes[j];
113714
+ }
113715
+ for (let i = 1, j = g1_pos; i < bytes.byteLength; i += 4, j++) {
113716
+ ret[i] = bytes[j];
113717
+ }
113718
+ for (let i = 2, j = g2_pos; i < bytes.byteLength; i += 4, j++) {
113719
+ ret[i] = bytes[j];
113720
+ }
113721
+ for (let i = 3, j = g3_pos; i < bytes.byteLength; i += 4, j++) {
113722
+ ret[i] = bytes[j];
113723
+ }
113724
+ return ret;
113725
+ }
113726
+ async function getAccessToken(initialAccessToken, customFetch, refreshUrl) {
113727
+ const key = cacheKey({ refreshUrl, initialAccessToken });
113728
+ const jwt = jwts.get(key);
113729
+ if (jwt && jwt.expiresAt > new Date(Date.now() + JWT_SAFETY_PERIOD)) {
113730
+ return { accessToken: jwt.accessToken, casUrl: jwt.casUrl };
113731
+ }
113732
+ const existingPromise = jwtPromises.get(key);
113733
+ if (existingPromise) {
113734
+ return existingPromise;
113735
+ }
113736
+ const promise = (async () => {
113737
+ const resp = await customFetch(refreshUrl, {
113738
+ headers: {
113739
+ ...initialAccessToken ? {
113740
+ Authorization: `Bearer ${initialAccessToken}`
113741
+ } : {}
113742
+ }
113743
+ });
113744
+ if (!resp.ok) {
113745
+ throw new Error(`Failed to get JWT token: ${resp.status} ${await resp.text()}`);
113746
+ }
113747
+ const json = await resp.json();
113748
+ const jwt2 = {
113749
+ accessToken: json.accessToken,
113750
+ expiresAt: new Date(json.exp * 1e3),
113751
+ casUrl: json.casUrl
113752
+ };
113753
+ jwtPromises.delete(key);
113754
+ for (const [key2, value] of jwts.entries()) {
113755
+ if (value.expiresAt < new Date(Date.now() + JWT_SAFETY_PERIOD)) {
113756
+ jwts.delete(key2);
113757
+ } else {
113758
+ break;
113759
+ }
113760
+ }
113761
+ if (jwts.size >= JWT_CACHE_SIZE) {
113762
+ const keyToDelete = jwts.keys().next().value;
113763
+ if (keyToDelete) {
113764
+ jwts.delete(keyToDelete);
113765
+ }
113766
+ }
113767
+ jwts.set(key, jwt2);
113768
+ return {
113769
+ accessToken: json.accessToken,
113770
+ casUrl: json.casUrl
113771
+ };
113772
+ })();
113773
+ jwtPromises.set(key, promise);
113774
+ return promise;
113775
+ }
113776
+
113777
+ // src/utils/WebBlob.ts
113778
+ var WebBlob = class extends Blob {
113779
+ static async create(url, opts) {
113780
+ const customFetch = opts?.fetch ?? fetch;
113781
+ const response = await customFetch(url, {
113782
+ method: "HEAD",
113783
+ ...opts?.accessToken && {
113784
+ headers: {
113785
+ Authorization: `Bearer ${opts.accessToken}`
113786
+ }
113787
+ }
113788
+ });
113789
+ const size = Number(response.headers.get("content-length"));
113790
+ const contentType = response.headers.get("content-type") || "";
113791
+ const supportRange = response.headers.get("accept-ranges") === "bytes";
113792
+ if (!supportRange || size < (opts?.cacheBelow ?? 1e6)) {
113793
+ return await (await customFetch(url)).blob();
113794
+ }
113795
+ return new WebBlob(url, 0, size, contentType, true, customFetch, opts?.accessToken);
113796
+ }
113797
+ url;
113798
+ start;
113799
+ end;
113800
+ contentType;
113801
+ full;
113802
+ fetch;
113803
+ accessToken;
113804
+ constructor(url, start, end, contentType, full, customFetch, accessToken) {
113805
+ super([]);
113806
+ this.url = url;
113807
+ this.start = start;
113808
+ this.end = end;
113809
+ this.contentType = contentType;
113810
+ this.full = full;
113811
+ this.fetch = customFetch;
113812
+ this.accessToken = accessToken;
113813
+ }
113814
+ get size() {
113815
+ return this.end - this.start;
113816
+ }
113817
+ get type() {
113818
+ return this.contentType;
113819
+ }
113820
+ slice(start = 0, end = this.size) {
113821
+ const slice = new WebBlob(
113822
+ this.url,
113823
+ this.start + start,
113824
+ Math.min(this.start + end, this.end),
113825
+ this.contentType,
113826
+ start === 0 && end === this.size ? this.full : false,
113827
+ this.fetch,
113828
+ this.accessToken
113829
+ );
113830
+ return slice;
113831
+ }
113832
+ async arrayBuffer() {
113833
+ const result = await this.fetchRange();
113834
+ return result.arrayBuffer();
113835
+ }
113836
+ async text() {
113837
+ const result = await this.fetchRange();
113838
+ return result.text();
113839
+ }
113840
+ stream() {
113841
+ const stream = new TransformStream();
113842
+ this.fetchRange().then((response) => response.body?.pipeThrough(stream)).catch((error) => stream.writable.abort(error.message));
113843
+ return stream.readable;
113844
+ }
113845
+ fetchRange() {
113846
+ const fetch2 = this.fetch;
113847
+ if (this.full) {
113848
+ return fetch2(this.url, {
113849
+ ...this.accessToken && {
113850
+ headers: {
113851
+ Authorization: `Bearer ${this.accessToken}`
113852
+ }
113853
+ }
113854
+ }).then((resp) => resp.ok ? resp : createApiError(resp));
113855
+ }
113856
+ return fetch2(this.url, {
113857
+ headers: {
113858
+ Range: `bytes=${this.start}-${this.end - 1}`,
113859
+ ...this.accessToken && { Authorization: `Bearer ${this.accessToken}` }
113860
+ }
113861
+ }).then((resp) => resp.ok ? resp : createApiError(resp));
113862
+ }
113863
+ };
113864
+
113865
+ // src/utils/parseLinkHeader.ts
113866
+ function parseLinkHeader(header) {
113867
+ const regex = /<(https?:[/][/][^>]+)>;\s+rel="([^"]+)"/g;
113868
+ return Object.fromEntries([...header.matchAll(regex)].map(([, url, rel]) => [rel, url]));
113869
+ }
113870
+
113871
+ // src/lib/file-download-info.ts
113872
+ async function fileDownloadInfo(params) {
113873
+ const accessToken = checkCredentials(params);
113874
+ const repoId = toRepoId(params.repo);
113875
+ const hubUrl = params.hubUrl ?? HUB_URL;
113876
+ const url = `${hubUrl}/${repoId.type === "model" ? "" : `${repoId.type}s/`}${repoId.name}/${params.raw ? "raw" : "resolve"}/${encodeURIComponent(params.revision ?? "main")}/${params.path}` + (params.noContentDisposition ? "?noContentDisposition=1" : "");
113877
+ const resp = await (params.fetch ?? fetch)(url, {
113878
+ method: "GET",
113879
+ headers: {
113880
+ ...accessToken && {
113881
+ Authorization: `Bearer ${accessToken}`
113882
+ },
113883
+ Range: "bytes=0-0",
113884
+ Accept: "application/vnd.xet-fileinfo+json, */*"
113885
+ }
113886
+ });
113887
+ if (resp.status === 404 && resp.headers.get("X-Error-Code") === "EntryNotFound") {
113888
+ return null;
113889
+ }
113890
+ if (!resp.ok) {
113891
+ throw await createApiError(resp);
113892
+ }
113893
+ let size;
113894
+ let xetInfo;
113895
+ if (resp.headers.get("Content-Type")?.includes("application/vnd.xet-fileinfo+json")) {
113896
+ size = parseInt(resp.headers.get("X-Linked-Size") ?? "invalid");
113897
+ if (isNaN(size)) {
113898
+ throw new InvalidApiResponseFormatError("Invalid file size received in X-Linked-Size header");
113899
+ }
113900
+ const hash2 = resp.headers.get("X-Xet-Hash");
113901
+ const links = parseLinkHeader(resp.headers.get("Link") ?? "");
113902
+ const reconstructionUrl = (() => {
113903
+ try {
113904
+ return new URL(links["xet-reconstruction-info"]);
113905
+ } catch {
113906
+ return null;
113907
+ }
113908
+ })();
113909
+ const refreshUrl = (() => {
113910
+ try {
113911
+ return new URL(links["xet-auth"]);
113912
+ } catch {
113913
+ return null;
113914
+ }
113915
+ })();
113916
+ if (!hash2) {
113917
+ throw new InvalidApiResponseFormatError("No hash received in X-Xet-Hash header");
113918
+ }
113919
+ if (!reconstructionUrl || !refreshUrl) {
113920
+ throw new InvalidApiResponseFormatError("No xet-reconstruction-info or xet-auth link header");
113921
+ }
113922
+ xetInfo = {
113923
+ hash: hash2,
113924
+ refreshUrl,
113925
+ reconstructionUrl
113926
+ };
113927
+ }
113928
+ if (size === void 0 || isNaN(size)) {
113929
+ const contentRangeHeader = resp.headers.get("content-range");
113930
+ if (!contentRangeHeader) {
113931
+ throw new InvalidApiResponseFormatError("Expected size information");
113932
+ }
113933
+ const [, parsedSize] = contentRangeHeader.split("/");
113934
+ size = parseInt(parsedSize);
113935
+ if (isNaN(size)) {
113936
+ throw new InvalidApiResponseFormatError("Invalid file size received");
113937
+ }
113938
+ }
113939
+ const etag = resp.headers.get("X-Linked-ETag") ?? resp.headers.get("ETag") ?? void 0;
113940
+ if (!etag) {
113941
+ throw new InvalidApiResponseFormatError("Expected ETag");
113942
+ }
113943
+ return {
113944
+ etag,
113945
+ size,
113946
+ xet: xetInfo,
113947
+ // Cannot use resp.url in case it's a S3 url and the user adds an Authorization header to it.
113948
+ url: resp.url && (new URL(resp.url).origin === new URL(hubUrl).origin || resp.headers.get("X-Cache")?.endsWith(" cloudfront")) ? resp.url : url
113949
+ };
113950
+ }
113951
+
113952
+ // src/lib/download-file.ts
113953
+ async function downloadFile(params) {
113954
+ const accessToken = checkCredentials(params);
113955
+ const info = params.downloadInfo ?? await fileDownloadInfo({
113956
+ accessToken,
113957
+ repo: params.repo,
113958
+ path: params.path,
113959
+ revision: params.revision,
113960
+ hubUrl: params.hubUrl,
113961
+ fetch: params.fetch,
113962
+ raw: params.raw
113963
+ });
113964
+ if (!info) {
113965
+ return null;
113966
+ }
113967
+ if (info.xet && params.xet) {
113968
+ return new XetBlob({
113969
+ refreshUrl: info.xet.refreshUrl.href,
113970
+ reconstructionUrl: info.xet.reconstructionUrl.href,
113971
+ fetch: params.fetch,
113972
+ accessToken,
113973
+ size: info.size
113974
+ });
113975
+ }
113976
+ return new WebBlob(new URL(info.url), 0, info.size, "", true, params.fetch ?? fetch, accessToken);
113977
+ }
113978
+
113979
+ // src/lib/list-files.ts
113980
+ async function* listFiles(params) {
113981
+ const accessToken = checkCredentials(params);
113982
+ const repoId = toRepoId(params.repo);
113983
+ let url = `${params.hubUrl || HUB_URL}/api/${repoId.type}s/${repoId.name}/tree/${params.revision || "main"}${params.path ? "/" + params.path : ""}?recursive=${!!params.recursive}&expand=${!!params.expand}`;
113984
+ while (url) {
113985
+ const res = await (params.fetch ?? fetch)(url, {
113986
+ headers: {
113987
+ accept: "application/json",
113988
+ ...accessToken ? { Authorization: `Bearer ${accessToken}` } : void 0
113989
+ }
113990
+ });
113991
+ if (!res.ok) {
113992
+ throw await createApiError(res);
113993
+ }
113994
+ const items = await res.json();
113995
+ for (const item of items) {
113996
+ yield item;
113997
+ }
113998
+ const linkHeader = res.headers.get("Link");
113999
+ url = linkHeader ? parseLinkHeader(linkHeader).next : void 0;
114000
+ }
114001
+ }
114002
+
114003
+ const DIR_BASED_ENGINES = new Set(["exllamav3", "mlx-lm"]);
114004
+ const FLAG_BASED_ENGINE_ARGS = {
114005
+ "llama.cpp": "--chat-template-file",
114006
+ sglang: "--chat-template",
114007
+ vllm: "--chat-template"
114008
+ };
114009
+ function getChatTemplateLocalPath(targetDirectory) {
114010
+ return path$1.join(targetDirectory, CHAT_TEMPLATE_LOCAL_FILE_NAME);
114011
+ }
114012
+ async function fetchTemplateContent({ huggingFaceToken, override }) {
114013
+ const accessToken = huggingFaceToken ?? process.env.HF_TOKEN ?? undefined;
114014
+ const filePath = override.filePath || CHAT_TEMPLATE_DEFAULT_FILE_PATH;
114015
+ const blob = await downloadFile({
114016
+ accessToken,
114017
+ path: filePath,
114018
+ repo: override.repo
114019
+ });
114020
+ if (!blob) {
114021
+ throw new Error(`Chat template file not found: ${override.repo}/${filePath}`);
114022
+ }
114023
+ const content = await blob.text();
114024
+ if (!content.trim()) {
114025
+ throw new Error(`Chat template file is empty: ${override.repo}/${filePath}`);
114026
+ }
114027
+ return content;
114028
+ }
114029
+ /**
114030
+ * Materializes the model's chat template override into the model directory:
114031
+ * - Always writes the canonical copy for flag-based engines.
114032
+ * - For engines that read the model directory (exllamav3, mlx-lm), also writes
114033
+ * the transformers-style `chat_template.jinja` drop-in.
114034
+ * - When no override is configured, removes any previously materialized files,
114035
+ * restoring the model repo's own `chat_template.jinja` if we replaced it.
114036
+ */
114037
+ async function materializeChatTemplate({ engine, huggingFaceToken, model, targetDirectory }) {
114038
+ const override = model.chatTemplate ?? null;
114039
+ const canonicalPath = getChatTemplateLocalPath(targetDirectory);
114040
+ const dropInPath = path$1.join(targetDirectory, CHAT_TEMPLATE_DEFAULT_FILE_PATH);
114041
+ if (!override) {
114042
+ const markerPath = `${canonicalPath}.override`;
114043
+ if (require$$3$4.existsSync(markerPath)) {
114044
+ await require$$0$m.rm(dropInPath, { force: true });
114045
+ await require$$0$m.rm(markerPath, { force: true });
114046
+ if (model.source.type === "huggingface") {
114047
+ await restoreOriginalTemplate({
114048
+ huggingFaceToken,
114049
+ modelSlug: model.source.slug,
114050
+ targetDirectory
114051
+ });
114052
+ }
114053
+ }
114054
+ await require$$0$m.rm(canonicalPath, { force: true });
114055
+ return;
114056
+ }
114057
+ const content = override.type === "inline"
114058
+ ? override.content
114059
+ : await fetchTemplateContent({ huggingFaceToken, override });
114060
+ await require$$0$m.mkdir(targetDirectory, { recursive: true });
114061
+ await require$$0$m.writeFile(canonicalPath, content, "utf8");
114062
+ if (DIR_BASED_ENGINES.has(engine)) {
114063
+ await require$$0$m.writeFile(dropInPath, content, "utf8");
114064
+ await require$$0$m.writeFile(`${canonicalPath}.override`, "1", "utf8");
114065
+ }
114066
+ }
114067
+ async function restoreOriginalTemplate({ huggingFaceToken, modelSlug, targetDirectory }) {
114068
+ const accessToken = huggingFaceToken ?? process.env.HF_TOKEN ?? undefined;
114069
+ try {
114070
+ const blob = await downloadFile({
114071
+ accessToken,
114072
+ path: CHAT_TEMPLATE_DEFAULT_FILE_PATH,
114073
+ repo: modelSlug.split(":")[0].split("@")[0]
114074
+ });
114075
+ if (blob) {
114076
+ const content = await blob.text();
114077
+ if (content.trim()) {
114078
+ await require$$0$m.writeFile(path$1.join(targetDirectory, CHAT_TEMPLATE_DEFAULT_FILE_PATH), content, "utf8");
114079
+ }
114080
+ }
114081
+ }
114082
+ catch (error) {
114083
+ console.warn("[chatTemplate] Failed to restore original chat_template.jinja after override removal:", asError(error).message);
114084
+ }
114085
+ }
114086
+ /**
114087
+ * CLI arguments applying the materialized chat template for flag-based engines.
114088
+ * Returns an empty array when no override exists, the engine applies templates
114089
+ * from the model directory, or the engine does not support overrides.
114090
+ */
114091
+ async function getChatTemplateEngineArgs({ engine, model, targetDirectory }) {
114092
+ if (!model.chatTemplate)
114093
+ return [];
114094
+ const flag = FLAG_BASED_ENGINE_ARGS[engine];
114095
+ if (!flag) {
114096
+ if (engine === "tensorrt-llm") {
114097
+ console.warn("[chatTemplate] TensorRT-LLM does not support chat template overrides; ignoring");
114098
+ }
114099
+ return [];
114100
+ }
114101
+ const templatePath = getChatTemplateLocalPath(targetDirectory);
114102
+ if (!require$$3$4.existsSync(templatePath)) {
114103
+ console.warn(`[chatTemplate] Template file missing for ${engine}; continuing with embedded template`);
114104
+ return [];
114105
+ }
114106
+ return [flag, templatePath];
114107
+ }
114108
+ /**
114109
+ * Post-start verification for llama.cpp: compares the template the server
114110
+ * reports via `/props` against the materialized override file. Returns a
114111
+ * warning message on mismatch, or null when the template applied cleanly
114112
+ * (or verification is not applicable).
114113
+ */
114114
+ async function verifyEngineChatTemplate({ engine, enginePort, logger, model, targetDirectory }) {
114115
+ if (!model.chatTemplate || engine !== "llama.cpp")
114116
+ return null;
114117
+ try {
114118
+ const templatePath = getChatTemplateLocalPath(targetDirectory);
114119
+ if (!require$$3$4.existsSync(templatePath)) {
114120
+ return "Chat template override file missing on disk";
114121
+ }
114122
+ const [propsResponse, expected] = await Promise.all([
114123
+ fetch(`http://localhost:${enginePort}/props`, {
114124
+ signal: AbortSignal.timeout(5000)
114125
+ }),
114126
+ require$$0$m.readFile(templatePath, "utf8")
114127
+ ]);
114128
+ if (!propsResponse.ok) {
114129
+ return `Chat template verification unavailable: /props returned ${propsResponse.status}`;
114130
+ }
114131
+ const props = (await propsResponse.json());
114132
+ const served = typeof props.chat_template === "string" ? props.chat_template.trim() : "";
114133
+ if (served !== expected.trim()) {
114134
+ return "Chat template override did not apply: served template differs from configured template";
114135
+ }
114136
+ return null;
114137
+ }
114138
+ catch (error) {
114139
+ logger.warn("Chat template verification failed", {
114140
+ error: asError(error)
114141
+ });
114142
+ return null;
114143
+ }
114144
+ }
114145
+
114146
+ const SECRET_FLAGS = new Set([
114147
+ "api-key",
114148
+ "auth-token",
114149
+ "hf-token",
114150
+ "key",
114151
+ "password",
114152
+ "secret",
114153
+ "token"
114154
+ ]);
114155
+ function redactSecretArgs(args) {
114156
+ return args.map((arg, index) => {
114157
+ const equalsIndex = arg.indexOf("=");
114158
+ if (arg.startsWith("--") && equalsIndex > 0) {
114159
+ const flag = arg.slice(2, equalsIndex);
114160
+ if (SECRET_FLAGS.has(flag)) {
114161
+ return `${arg.slice(0, equalsIndex + 1)}***`;
114162
+ }
114163
+ }
114164
+ const previous = args[index - 1];
114165
+ if (previous &&
114166
+ previous.startsWith("--") &&
114167
+ !previous.includes("=") &&
114168
+ SECRET_FLAGS.has(previous.slice(2))) {
114169
+ return "***";
114170
+ }
114171
+ return arg;
114172
+ });
114173
+ }
114174
+ async function createEngineProcess({ args, bin, logger }) {
114175
+ logger.info("Starting engine process", {
114176
+ command: { args: redactSecretArgs(args), bin }
114177
+ });
114178
+ const processManager = new ProcessManager({ args, command: bin });
114179
+ await processManager.start();
114180
+ return processManager;
114181
+ }
114182
+
114183
+ const balanced = (a, b, str) => {
114184
+ const ma = a instanceof RegExp ? maybeMatch(a, str) : a;
114185
+ const mb = b instanceof RegExp ? maybeMatch(b, str) : b;
114186
+ const r = ma !== null && mb != null && range(ma, mb, str);
114187
+ return (r && {
114188
+ start: r[0],
114189
+ end: r[1],
114190
+ pre: str.slice(0, r[0]),
114191
+ body: str.slice(r[0] + ma.length, r[1]),
114192
+ post: str.slice(r[1] + mb.length),
114193
+ });
114194
+ };
114195
+ const maybeMatch = (reg, str) => {
114196
+ const m = str.match(reg);
114197
+ return m ? m[0] : null;
114198
+ };
114199
+ const range = (a, b, str) => {
114200
+ let begs, beg, left, right = undefined, result;
114201
+ let ai = str.indexOf(a);
114202
+ let bi = str.indexOf(b, ai + 1);
114203
+ let i = ai;
114204
+ if (ai >= 0 && bi > 0) {
114205
+ if (a === b) {
114206
+ return [ai, bi];
114207
+ }
114208
+ begs = [];
114209
+ left = str.length;
114210
+ while (i >= 0 && !result) {
114211
+ if (i === ai) {
114212
+ begs.push(i);
114213
+ ai = str.indexOf(a, i + 1);
114214
+ }
114215
+ else if (begs.length === 1) {
114216
+ const r = begs.pop();
114217
+ if (r !== undefined)
114218
+ result = [r, bi];
114219
+ }
114220
+ else {
114221
+ beg = begs.pop();
114222
+ if (beg !== undefined && beg < left) {
114223
+ left = beg;
114224
+ right = bi;
114225
+ }
114226
+ bi = str.indexOf(b, i + 1);
114227
+ }
114228
+ i = ai < bi && ai >= 0 ? ai : bi;
114229
+ }
114230
+ if (begs.length && right !== undefined) {
114231
+ result = [left, right];
114232
+ }
114233
+ }
114234
+ return result;
114235
+ };
114236
+
114237
+ const escSlash = '\0SLASH' + Math.random() + '\0';
114238
+ const escOpen = '\0OPEN' + Math.random() + '\0';
114239
+ const escClose = '\0CLOSE' + Math.random() + '\0';
114240
+ const escComma = '\0COMMA' + Math.random() + '\0';
114241
+ const escPeriod = '\0PERIOD' + Math.random() + '\0';
114242
+ const escSlashPattern = new RegExp(escSlash, 'g');
114243
+ const escOpenPattern = new RegExp(escOpen, 'g');
114244
+ const escClosePattern = new RegExp(escClose, 'g');
114245
+ const escCommaPattern = new RegExp(escComma, 'g');
114246
+ const escPeriodPattern = new RegExp(escPeriod, 'g');
114247
+ const slashPattern = /\\\\/g;
114248
+ const openPattern = /\\{/g;
114249
+ const closePattern = /\\}/g;
114250
+ const commaPattern = /\\,/g;
114251
+ const periodPattern = /\\\./g;
114252
+ const EXPANSION_MAX = 100_000;
114253
+ // `EXPANSION_MAX` caps the *number* of expansions, but not their length. An
114254
+ // input like `'{a,b}'.repeat(1500)` stays under that count - its output is
114255
+ // truncated to 100k results - while making every result ~1500 characters
114256
+ // long. The result set, and the intermediate arrays built while combining
114257
+ // brace sets, then grow large enough to exhaust memory and crash the process
114258
+ // (CVE-2026-14257). `EXPANSION_MAX_LENGTH` bounds the total number of
114259
+ // characters the accumulator may hold at any point, so memory stays flat no
114260
+ // matter how many brace groups are chained. The limit sits well above any
114261
+ // realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M
114262
+ // characters) so legitimate input is unaffected.
114263
+ const EXPANSION_MAX_LENGTH = 4_000_000;
114264
+ function numeric(str) {
114265
+ return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
114266
+ }
114267
+ function escapeBraces(str) {
114268
+ return str
114269
+ .replace(slashPattern, escSlash)
114270
+ .replace(openPattern, escOpen)
114271
+ .replace(closePattern, escClose)
114272
+ .replace(commaPattern, escComma)
114273
+ .replace(periodPattern, escPeriod);
114274
+ }
114275
+ function unescapeBraces(str) {
114276
+ return str
114277
+ .replace(escSlashPattern, '\\')
114278
+ .replace(escOpenPattern, '{')
114279
+ .replace(escClosePattern, '}')
114280
+ .replace(escCommaPattern, ',')
114281
+ .replace(escPeriodPattern, '.');
114282
+ }
114283
+ /**
114284
+ * Basically just str.split(","), but handling cases
114285
+ * where we have nested braced sections, which should be
114286
+ * treated as individual members, like {a,{b,c},d}
114287
+ */
114288
+ function parseCommaParts(str) {
114289
+ if (!str) {
114290
+ return [''];
114291
+ }
114292
+ const parts = [];
114293
+ const m = balanced('{', '}', str);
114294
+ if (!m) {
114295
+ return str.split(',');
114296
+ }
114297
+ const { pre, body, post } = m;
114298
+ const p = pre.split(',');
114299
+ p[p.length - 1] += '{' + body + '}';
114300
+ const postParts = parseCommaParts(post);
114301
+ if (post.length) {
114302
+ p[p.length - 1] += postParts.shift();
114303
+ p.push.apply(p, postParts);
114304
+ }
114305
+ parts.push.apply(parts, p);
114306
+ return parts;
114307
+ }
114308
+ function expand(str, options = {}) {
114309
+ if (!str) {
114310
+ return [];
114311
+ }
114312
+ const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH } = options;
114313
+ // I don't know why Bash 4.3 does this, but it does.
114314
+ // Anything starting with {} will have the first two bytes preserved
114315
+ // but *only* at the top level, so {},a}b will not expand to anything,
114316
+ // but a{},b}c will be expanded to [a}c,abc].
114317
+ // One could argue that this is a bug in Bash, but since the goal of
114318
+ // this module is to match Bash's rules, we escape a leading {}
114319
+ if (str.slice(0, 2) === '{}') {
114320
+ str = '\\{\\}' + str.slice(2);
114321
+ }
114322
+ return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
114323
+ }
114324
+ function embrace(str) {
114325
+ return '{' + str + '}';
114326
+ }
114327
+ function isPadded(el) {
114328
+ return /^-?0\d/.test(el);
114329
+ }
114330
+ function lte(i, y) {
114331
+ return i <= y;
114332
+ }
114333
+ function gte(i, y) {
114334
+ return i >= y;
114335
+ }
114336
+ // Build `{ acc[a] + pre + values[v] }` for every combination, capping the
114337
+ // number of results at `max` and the total number of characters at `maxLength`.
114338
+ // This is the one place output grows, so bounding it here keeps the single
114339
+ // accumulator - and therefore memory - flat regardless of how many brace groups
114340
+ // are combined (CVE-2026-14257).
114341
+ function combine(acc, pre, values, max, maxLength, dropEmpties) {
114342
+ const out = [];
114343
+ let length = 0;
114344
+ for (let a = 0; a < acc.length; a++) {
114345
+ for (let v = 0; v < values.length; v++) {
114346
+ if (out.length >= max)
114347
+ return out;
114348
+ const expansion = acc[a] + pre + values[v];
114349
+ // Bash drops empty results at the top level. Skip them before they count
114350
+ // against `max`, so `max` bounds the number of *kept* results.
114351
+ if (dropEmpties && !expansion)
114352
+ continue;
114353
+ if (length + expansion.length > maxLength)
114354
+ return out;
114355
+ out.push(expansion);
114356
+ length += expansion.length;
114357
+ }
114358
+ }
114359
+ return out;
114360
+ }
114361
+ // The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)
114362
+ // sequence body.
114363
+ function expandSequence(body, isAlphaSequence, max, maxLength) {
114364
+ const n = body.split(/\.\./);
114365
+ const N = [];
114366
+ // A sequence body always splits into two or three parts, but the compiler
114367
+ // can't know that.
114368
+ /* c8 ignore start */
114369
+ if (n[0] === undefined || n[1] === undefined) {
114370
+ return N;
114371
+ }
114372
+ /* c8 ignore stop */
114373
+ const x = numeric(n[0]);
114374
+ const y = numeric(n[1]);
114375
+ const width = Math.max(n[0].length, n[1].length);
114376
+ let incr = n.length === 3 && n[2] !== undefined ?
114377
+ Math.max(Math.abs(numeric(n[2])), 1)
114378
+ : 1;
114379
+ let test = lte;
114380
+ const reverse = y < x;
114381
+ if (reverse) {
114382
+ incr *= -1;
114383
+ test = gte;
114384
+ }
114385
+ const pad = n.some(isPadded);
114386
+ let length = 0;
114387
+ for (let i = x; test(i, y) && N.length < max; i += incr) {
114388
+ let c;
114389
+ if (isAlphaSequence) {
114390
+ c = String.fromCharCode(i);
114391
+ if (c === '\\') {
114392
+ c = '';
114393
+ }
114394
+ }
114395
+ else {
114396
+ c = String(i);
114397
+ if (pad) {
114398
+ const need = width - c.length;
114399
+ if (need > 0) {
114400
+ const z = new Array(need + 1).join('0');
114401
+ if (i < 0) {
114402
+ c = '-' + z + c.slice(1);
114403
+ }
114404
+ else {
114405
+ c = z + c;
114406
+ }
114407
+ }
114408
+ }
114409
+ }
114410
+ if (length + c.length > maxLength)
114411
+ break;
114412
+ N.push(c);
114413
+ length += c.length;
114414
+ }
114415
+ return N;
114416
+ }
114417
+ function expand_(str, max, maxLength, isTop) {
114418
+ // Consume the string's top-level brace groups left to right, threading a
114419
+ // running set of combined prefixes (`acc`). Expanding the tail iteratively -
114420
+ // rather than recursing on `m.post` once per group - keeps the native stack
114421
+ // depth constant, so deeply chained input (`'{a,b}'.repeat(3000)`) can no
114422
+ // longer overflow the stack, and leaves a single accumulator whose size
114423
+ // `maxLength` bounds directly (CVE-2026-14257).
114424
+ let acc = [''];
114425
+ // Bash drops empty results, but only when the *first* top-level group is a
114426
+ // comma set - a sequence like `{a..\}` may legitimately yield ''. The drop
114427
+ // is on the final strings, so it is applied to whichever `combine` produces
114428
+ // them (the one with no brace set left in the tail).
114429
+ let dropEmpties = false;
114430
+ let firstGroup = true;
114431
+ for (;;) {
114432
+ const m = balanced('{', '}', str);
114433
+ // No brace set left: the rest of the string is literal.
114434
+ if (!m) {
114435
+ return combine(acc, str, [''], max, maxLength, dropEmpties);
114436
+ }
114437
+ // no need to expand pre, since it is guaranteed to be free of brace-sets
114438
+ const pre = m.pre;
114439
+ if (/\$$/.test(pre)) {
114440
+ acc = combine(acc, pre + '{' + m.body + '}', [''], max, maxLength, dropEmpties && !m.post.length);
114441
+ firstGroup = false;
114442
+ if (!m.post.length)
114443
+ break;
114444
+ str = m.post;
114445
+ continue;
114446
+ }
114447
+ const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
114448
+ const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
114449
+ const isSequence = isNumericSequence || isAlphaSequence;
114450
+ const isOptions = m.body.indexOf(',') >= 0;
114451
+ if (!isSequence && !isOptions) {
114452
+ // {a},b}
114453
+ if (m.post.match(/,(?!,).*\}/)) {
114454
+ str = m.pre + '{' + m.body + escClose + m.post;
114455
+ isTop = true;
114456
+ continue;
114457
+ }
114458
+ // Nothing here expands, so the whole remaining string is literal.
114459
+ return combine(acc, pre + '{' + m.body + '}' + m.post, [''], max, maxLength, dropEmpties);
114460
+ }
114461
+ if (firstGroup) {
114462
+ dropEmpties = isTop && !isSequence;
114463
+ firstGroup = false;
114464
+ }
114465
+ let values;
114466
+ if (isSequence) {
114467
+ values = expandSequence(m.body, isAlphaSequence, max, maxLength);
114468
+ }
114469
+ else {
114470
+ let n = parseCommaParts(m.body);
114471
+ if (n.length === 1 && n[0] !== undefined) {
114472
+ // x{{a,b}}y ==> x{a}y x{b}y
114473
+ n = expand_(n[0], max, maxLength, false).map(embrace);
114474
+ //XXX is this necessary? Can't seem to hit it in tests.
114475
+ /* c8 ignore start */
114476
+ if (n.length === 1) {
114477
+ acc = combine(acc, pre + n[0], [''], max, maxLength, dropEmpties && !m.post.length);
114478
+ if (!m.post.length)
114479
+ break;
114480
+ str = m.post;
114481
+ continue;
114482
+ }
114483
+ /* c8 ignore stop */
114484
+ }
114485
+ // Values that `combine` is going to drop as empty produce no result, so
114486
+ // they must not count against `max` - otherwise `{a,,b}` with `max: 2`
114487
+ // would stop at `['a', '']` and yield one result instead of two. Skipping
114488
+ // them outright keeps `values` bounded while leaving `max` a bound on
114489
+ // *kept* results.
114490
+ let dropsEmpties = dropEmpties && !m.post.length && !pre;
114491
+ for (let d = 0; dropsEmpties && d < acc.length; d++) {
114492
+ if (acc[d]) {
114493
+ dropsEmpties = false;
114494
+ }
114495
+ }
114496
+ values = [];
114497
+ let valuesLength = 0;
114498
+ outer: for (let j = 0; j < n.length; j++) {
114499
+ const expanded = expand_(n[j], max, maxLength, false);
114500
+ for (let k = 0; k < expanded.length; k++) {
114501
+ const v = expanded[k];
114502
+ if (dropsEmpties && !v)
114503
+ continue;
114504
+ if (values.length >= max || valuesLength + v.length > maxLength) {
114505
+ break outer;
114506
+ }
114507
+ values.push(v);
114508
+ valuesLength += v.length;
114509
+ }
114510
+ }
114511
+ }
114512
+ acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length);
114513
+ if (!m.post.length)
114514
+ break;
114515
+ str = m.post;
114516
+ }
114517
+ return acc;
114518
+ }
114519
+
114520
+ const MAX_PATTERN_LENGTH = 1024 * 64;
114521
+ const assertValidPattern = (pattern) => {
114522
+ if (typeof pattern !== 'string') {
114523
+ throw new TypeError('invalid pattern');
114524
+ }
114525
+ if (pattern.length > MAX_PATTERN_LENGTH) {
114526
+ throw new TypeError('pattern is too long');
114527
+ }
114528
+ };
114529
+
114530
+ // translate the various posix character classes into unicode properties
114531
+ // this works across all unicode locales
114532
+ // { <posix class>: [<translation>, /u flag required, negated]
114533
+ const posixClasses = {
114534
+ '[:alnum:]': ['\\p{L}\\p{Nl}\\p{Nd}', true],
114535
+ '[:alpha:]': ['\\p{L}\\p{Nl}', true],
114536
+ '[:ascii:]': ['\\x' + '00-\\x' + '7f', false],
114537
+ '[:blank:]': ['\\p{Zs}\\t', true],
114538
+ '[:cntrl:]': ['\\p{Cc}', true],
114539
+ '[:digit:]': ['\\p{Nd}', true],
114540
+ '[:graph:]': ['\\p{Z}\\p{C}', true, true],
114541
+ '[:lower:]': ['\\p{Ll}', true],
114542
+ '[:print:]': ['\\p{C}', true],
114543
+ '[:punct:]': ['\\p{P}', true],
114544
+ '[:space:]': ['\\p{Z}\\t\\r\\n\\v\\f', true],
114545
+ '[:upper:]': ['\\p{Lu}', true],
114546
+ '[:word:]': ['\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}', true],
114547
+ '[:xdigit:]': ['A-Fa-f0-9', false],
114548
+ };
114549
+ // only need to escape a few things inside of brace expressions
114550
+ // escapes: [ \ ] -
114551
+ const braceEscape = (s) => s.replace(/[[\]\\-]/g, '\\$&');
114552
+ // escape all regexp magic characters
113402
114553
  const regexpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
113403
114554
  // everything has already been escaped, we just have to join
113404
114555
  const rangesToString = (ranges) => ranges.join('');
@@ -120982,1551 +122133,491 @@ class GlobUtil {
120982
122133
  cb();
120983
122134
  };
120984
122135
  for (const [m, absolute, ifDir] of processor.matches.entries()) {
120985
- if (this.#ignored(m))
120986
- continue;
120987
- this.matchSync(m, absolute, ifDir);
120988
- }
120989
- for (const [target, patterns] of processor.subwalks.entries()) {
120990
- tasks++;
120991
- this.walkCB2Sync(target, patterns, processor.child(), next);
120992
- }
120993
- next();
120994
- }
120995
- }
120996
- class GlobWalker extends GlobUtil {
120997
- matches = new Set();
120998
- constructor(patterns, path, opts) {
120999
- super(patterns, path, opts);
121000
- }
121001
- matchEmit(e) {
121002
- this.matches.add(e);
121003
- }
121004
- async walk() {
121005
- if (this.signal?.aborted)
121006
- throw this.signal.reason;
121007
- if (this.path.isUnknown()) {
121008
- await this.path.lstat();
121009
- }
121010
- await new Promise((res, rej) => {
121011
- this.walkCB(this.path, this.patterns, () => {
121012
- if (this.signal?.aborted) {
121013
- rej(this.signal.reason);
121014
- }
121015
- else {
121016
- res(this.matches);
121017
- }
121018
- });
121019
- });
121020
- return this.matches;
121021
- }
121022
- walkSync() {
121023
- if (this.signal?.aborted)
121024
- throw this.signal.reason;
121025
- if (this.path.isUnknown()) {
121026
- this.path.lstatSync();
121027
- }
121028
- // nothing for the callback to do, because this never pauses
121029
- this.walkCBSync(this.path, this.patterns, () => {
121030
- if (this.signal?.aborted)
121031
- throw this.signal.reason;
121032
- });
121033
- return this.matches;
121034
- }
121035
- }
121036
- class GlobStream extends GlobUtil {
121037
- results;
121038
- constructor(patterns, path, opts) {
121039
- super(patterns, path, opts);
121040
- this.results = new Minipass({
121041
- signal: this.signal,
121042
- objectMode: true,
121043
- });
121044
- this.results.on('drain', () => this.resume());
121045
- this.results.on('resume', () => this.resume());
121046
- }
121047
- matchEmit(e) {
121048
- this.results.write(e);
121049
- if (!this.results.flowing)
121050
- this.pause();
121051
- }
121052
- stream() {
121053
- const target = this.path;
121054
- if (target.isUnknown()) {
121055
- target.lstat().then(() => {
121056
- this.walkCB(target, this.patterns, () => this.results.end());
121057
- });
121058
- }
121059
- else {
121060
- this.walkCB(target, this.patterns, () => this.results.end());
121061
- }
121062
- return this.results;
121063
- }
121064
- streamSync() {
121065
- if (this.path.isUnknown()) {
121066
- this.path.lstatSync();
121067
- }
121068
- this.walkCBSync(this.path, this.patterns, () => this.results.end());
121069
- return this.results;
121070
- }
121071
- }
121072
-
121073
- // if no process global, just call it linux.
121074
- // so we default to case-sensitive, / separators
121075
- const defaultPlatform = (typeof process === 'object' &&
121076
- process &&
121077
- typeof process.platform === 'string') ?
121078
- process.platform
121079
- : 'linux';
121080
- /**
121081
- * An object that can perform glob pattern traversals.
121082
- */
121083
- class Glob {
121084
- absolute;
121085
- cwd;
121086
- root;
121087
- dot;
121088
- dotRelative;
121089
- follow;
121090
- ignore;
121091
- magicalBraces;
121092
- mark;
121093
- matchBase;
121094
- maxDepth;
121095
- nobrace;
121096
- nocase;
121097
- nodir;
121098
- noext;
121099
- noglobstar;
121100
- pattern;
121101
- platform;
121102
- realpath;
121103
- scurry;
121104
- stat;
121105
- signal;
121106
- windowsPathsNoEscape;
121107
- withFileTypes;
121108
- includeChildMatches;
121109
- /**
121110
- * The options provided to the constructor.
121111
- */
121112
- opts;
121113
- /**
121114
- * An array of parsed immutable {@link Pattern} objects.
121115
- */
121116
- patterns;
121117
- /**
121118
- * All options are stored as properties on the `Glob` object.
121119
- *
121120
- * See {@link GlobOptions} for full options descriptions.
121121
- *
121122
- * Note that a previous `Glob` object can be passed as the
121123
- * `GlobOptions` to another `Glob` instantiation to re-use settings
121124
- * and caches with a new pattern.
121125
- *
121126
- * Traversal functions can be called multiple times to run the walk
121127
- * again.
121128
- */
121129
- constructor(pattern, opts) {
121130
- /* c8 ignore start */
121131
- if (!opts)
121132
- throw new TypeError('glob options required');
121133
- /* c8 ignore stop */
121134
- this.withFileTypes = !!opts.withFileTypes;
121135
- this.signal = opts.signal;
121136
- this.follow = !!opts.follow;
121137
- this.dot = !!opts.dot;
121138
- this.dotRelative = !!opts.dotRelative;
121139
- this.nodir = !!opts.nodir;
121140
- this.mark = !!opts.mark;
121141
- if (!opts.cwd) {
121142
- this.cwd = '';
121143
- }
121144
- else if (opts.cwd instanceof URL || opts.cwd.startsWith('file://')) {
121145
- opts.cwd = require$$0$l.fileURLToPath(opts.cwd);
121146
- }
121147
- this.cwd = opts.cwd || '';
121148
- this.root = opts.root;
121149
- this.magicalBraces = !!opts.magicalBraces;
121150
- this.nobrace = !!opts.nobrace;
121151
- this.noext = !!opts.noext;
121152
- this.realpath = !!opts.realpath;
121153
- this.absolute = opts.absolute;
121154
- this.includeChildMatches = opts.includeChildMatches !== false;
121155
- this.noglobstar = !!opts.noglobstar;
121156
- this.matchBase = !!opts.matchBase;
121157
- this.maxDepth =
121158
- typeof opts.maxDepth === 'number' ? opts.maxDepth : Infinity;
121159
- this.stat = !!opts.stat;
121160
- this.ignore = opts.ignore;
121161
- if (this.withFileTypes && this.absolute !== undefined) {
121162
- throw new Error('cannot set absolute and withFileTypes:true');
121163
- }
121164
- if (typeof pattern === 'string') {
121165
- pattern = [pattern];
121166
- }
121167
- this.windowsPathsNoEscape =
121168
- !!opts.windowsPathsNoEscape ||
121169
- opts.allowWindowsEscape ===
121170
- false;
121171
- if (this.windowsPathsNoEscape) {
121172
- pattern = pattern.map(p => p.replace(/\\/g, '/'));
121173
- }
121174
- if (this.matchBase) {
121175
- if (opts.noglobstar) {
121176
- throw new TypeError('base matching requires globstar');
121177
- }
121178
- pattern = pattern.map(p => (p.includes('/') ? p : `./**/${p}`));
121179
- }
121180
- this.pattern = pattern;
121181
- this.platform = opts.platform || defaultPlatform;
121182
- this.opts = { ...opts, platform: this.platform };
121183
- if (opts.scurry) {
121184
- this.scurry = opts.scurry;
121185
- if (opts.nocase !== undefined &&
121186
- opts.nocase !== opts.scurry.nocase) {
121187
- throw new Error('nocase option contradicts provided scurry option');
121188
- }
121189
- }
121190
- else {
121191
- const Scurry = opts.platform === 'win32' ? PathScurryWin32
121192
- : opts.platform === 'darwin' ? PathScurryDarwin
121193
- : opts.platform ? PathScurryPosix
121194
- : PathScurry;
121195
- this.scurry = new Scurry(this.cwd, {
121196
- nocase: opts.nocase,
121197
- fs: opts.fs,
121198
- });
121199
- }
121200
- this.nocase = this.scurry.nocase;
121201
- // If you do nocase:true on a case-sensitive file system, then
121202
- // we need to use regexps instead of strings for non-magic
121203
- // path portions, because statting `aBc` won't return results
121204
- // for the file `AbC` for example.
121205
- const nocaseMagicOnly = this.platform === 'darwin' || this.platform === 'win32';
121206
- const mmo = {
121207
- // default nocase based on platform
121208
- ...opts,
121209
- dot: this.dot,
121210
- matchBase: this.matchBase,
121211
- nobrace: this.nobrace,
121212
- nocase: this.nocase,
121213
- nocaseMagicOnly,
121214
- nocomment: true,
121215
- noext: this.noext,
121216
- nonegate: true,
121217
- optimizationLevel: 2,
121218
- platform: this.platform,
121219
- windowsPathsNoEscape: this.windowsPathsNoEscape,
121220
- debug: !!this.opts.debug,
121221
- };
121222
- const mms = this.pattern.map(p => new Minimatch(p, mmo));
121223
- const [matchSet, globParts] = mms.reduce((set, m) => {
121224
- set[0].push(...m.set);
121225
- set[1].push(...m.globParts);
121226
- return set;
121227
- }, [[], []]);
121228
- this.patterns = matchSet.map((set, i) => {
121229
- const g = globParts[i];
121230
- /* c8 ignore start */
121231
- if (!g)
121232
- throw new Error('invalid pattern object');
121233
- /* c8 ignore stop */
121234
- return new Pattern(set, g, 0, this.platform);
121235
- });
121236
- }
121237
- async walk() {
121238
- // Walkers always return array of Path objects, so we just have to
121239
- // coerce them into the right shape. It will have already called
121240
- // realpath() if the option was set to do so, so we know that's cached.
121241
- // start out knowing the cwd, at least
121242
- return [
121243
- ...(await new GlobWalker(this.patterns, this.scurry.cwd, {
121244
- ...this.opts,
121245
- maxDepth: this.maxDepth !== Infinity ?
121246
- this.maxDepth + this.scurry.cwd.depth()
121247
- : Infinity,
121248
- platform: this.platform,
121249
- nocase: this.nocase,
121250
- includeChildMatches: this.includeChildMatches,
121251
- }).walk()),
121252
- ];
121253
- }
121254
- walkSync() {
121255
- return [
121256
- ...new GlobWalker(this.patterns, this.scurry.cwd, {
121257
- ...this.opts,
121258
- maxDepth: this.maxDepth !== Infinity ?
121259
- this.maxDepth + this.scurry.cwd.depth()
121260
- : Infinity,
121261
- platform: this.platform,
121262
- nocase: this.nocase,
121263
- includeChildMatches: this.includeChildMatches,
121264
- }).walkSync(),
121265
- ];
121266
- }
121267
- stream() {
121268
- return new GlobStream(this.patterns, this.scurry.cwd, {
121269
- ...this.opts,
121270
- maxDepth: this.maxDepth !== Infinity ?
121271
- this.maxDepth + this.scurry.cwd.depth()
121272
- : Infinity,
121273
- platform: this.platform,
121274
- nocase: this.nocase,
121275
- includeChildMatches: this.includeChildMatches,
121276
- }).stream();
121277
- }
121278
- streamSync() {
121279
- return new GlobStream(this.patterns, this.scurry.cwd, {
121280
- ...this.opts,
121281
- maxDepth: this.maxDepth !== Infinity ?
121282
- this.maxDepth + this.scurry.cwd.depth()
121283
- : Infinity,
121284
- platform: this.platform,
121285
- nocase: this.nocase,
121286
- includeChildMatches: this.includeChildMatches,
121287
- }).streamSync();
121288
- }
121289
- /**
121290
- * Default sync iteration function. Returns a Generator that
121291
- * iterates over the results.
121292
- */
121293
- iterateSync() {
121294
- return this.streamSync()[Symbol.iterator]();
121295
- }
121296
- [Symbol.iterator]() {
121297
- return this.iterateSync();
121298
- }
121299
- /**
121300
- * Default async iteration function. Returns an AsyncGenerator that
121301
- * iterates over the results.
121302
- */
121303
- iterate() {
121304
- return this.stream()[Symbol.asyncIterator]();
121305
- }
121306
- [Symbol.asyncIterator]() {
121307
- return this.iterate();
121308
- }
121309
- }
121310
-
121311
- /**
121312
- * Return true if the patterns provided contain any magic glob characters,
121313
- * given the options provided.
121314
- *
121315
- * Brace expansion is not considered "magic" unless the `magicalBraces` option
121316
- * is set, as brace expansion just turns one string into an array of strings.
121317
- * So a pattern like `'x{a,b}y'` would return `false`, because `'xay'` and
121318
- * `'xby'` both do not contain any magic glob characters, and it's treated the
121319
- * same as if you had called it on `['xay', 'xby']`. When `magicalBraces:true`
121320
- * is in the options, brace expansion _is_ treated as a pattern having magic.
121321
- */
121322
- const hasMagic = (pattern, options = {}) => {
121323
- if (!Array.isArray(pattern)) {
121324
- pattern = [pattern];
121325
- }
121326
- for (const p of pattern) {
121327
- if (new Minimatch(p, options).hasMagic())
121328
- return true;
121329
- }
121330
- return false;
121331
- };
121332
-
121333
- function globStreamSync(pattern, options = {}) {
121334
- return new Glob(pattern, options).streamSync();
121335
- }
121336
- function globStream(pattern, options = {}) {
121337
- return new Glob(pattern, options).stream();
121338
- }
121339
- function globSync(pattern, options = {}) {
121340
- return new Glob(pattern, options).walkSync();
121341
- }
121342
- async function glob_(pattern, options = {}) {
121343
- return new Glob(pattern, options).walk();
121344
- }
121345
- function globIterateSync(pattern, options = {}) {
121346
- return new Glob(pattern, options).iterateSync();
121347
- }
121348
- function globIterate(pattern, options = {}) {
121349
- return new Glob(pattern, options).iterate();
121350
- }
121351
- // aliases: glob.sync.stream() glob.stream.sync() glob.sync() etc
121352
- const streamSync = globStreamSync;
121353
- const stream = Object.assign(globStream, { sync: globStreamSync });
121354
- const iterateSync = globIterateSync;
121355
- const iterate = Object.assign(globIterate, {
121356
- sync: globIterateSync,
121357
- });
121358
- const sync = Object.assign(globSync, {
121359
- stream: globStreamSync,
121360
- iterate: globIterateSync,
121361
- });
121362
- const glob = Object.assign(glob_, {
121363
- glob: glob_,
121364
- globSync,
121365
- sync,
121366
- globStream,
121367
- stream,
121368
- globStreamSync,
121369
- streamSync,
121370
- globIterate,
121371
- iterate,
121372
- globIterateSync,
121373
- iterateSync,
121374
- Glob,
121375
- hasMagic,
121376
- escape: escape$1,
121377
- unescape: unescape$1,
121378
- });
121379
- glob.glob = glob;
121380
-
121381
- function matchesQuantizationVariant({ filePath, variant }) {
121382
- if (!variant) {
121383
- return false;
121384
- }
121385
- const escapedVariant = variant.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
121386
- const matcher = new RegExp(`(^|[\\-./_])${escapedVariant}(?=[\\-./]|$)`, "i");
121387
- const normalizedPath = filePath.replace(/\\/g, "/");
121388
- const segments = normalizedPath.split("/").filter(Boolean);
121389
- if (segments.length === 0) {
121390
- return false;
121391
- }
121392
- const filename = segments[segments.length - 1].replace(/\.gguf$/i, "");
121393
- if (matcher.test(filename)) {
121394
- return true;
121395
- }
121396
- return segments.slice(0, -1).some(segment => matcher.test(segment));
121397
- }
121398
- async function findQuantizedModelTarget({ model, path }) {
121399
- if (model.source.type === "storage") {
121400
- throw new Error("Model storage not supported yet");
121401
- }
121402
- if (model.format !== "gguf") {
121403
- throw new Error(`Model format not supported: ${model.format}`);
121404
- }
121405
- const [, variant = null] = model.source.slug.split(":");
121406
- const modelFiles = (await glob("**/*.gguf", {
121407
- absolute: true,
121408
- cwd: path,
121409
- nodir: true
121410
- })).filter(file => !/(mmproj|clip)/i.test(file));
121411
- if (modelFiles.length <= 0) {
121412
- throw new Error(`No models found for format: ${model.format}`);
121413
- }
121414
- modelFiles.sort((left, right) => left.localeCompare(right, undefined, { sensitivity: "base" }));
121415
- if (!variant) {
121416
- return modelFiles[0];
121417
- }
121418
- const matches = modelFiles.filter(fileName => matchesQuantizationVariant({ filePath: fileName, variant: variant ?? "" }));
121419
- if (matches.length === 0) {
121420
- throw new Error(`No model found for format and variant: ${model.format} / ${variant}`);
121421
- }
121422
- return matches[0];
121423
- }
121424
-
121425
- const VLLM_START_ARGS = ["-m", "vllm.entrypoints.openai.api_server", "--host", "0.0.0.0"];
121426
- const VLLM_EXECUTABLE = "python3";
121427
- const DEFAULT_VLLM_CONTEXT_LENGTH = 2048;
121428
- async function startVLLM({ enginePort, targetDirectory }) {
121429
- const contextLength = Math.max(1, this.contextLength ?? DEFAULT_VLLM_CONTEXT_LENGTH);
121430
- let modelPath = targetDirectory;
121431
- if (this.model.format === "gguf") {
121432
- modelPath = await findQuantizedModelTarget({ model: this.model, path: targetDirectory });
121433
- }
121434
- const engineConfig = this.engineConfig;
121435
- const device = typeof engineConfig?.device === "string" ? engineConfig.device : process.env.VLLM_DEVICE;
121436
- const dtype = typeof engineConfig?.dtype === "string" ? engineConfig.dtype : process.env.VLLM_DTYPE;
121437
- const tensorParallelSize = typeof engineConfig?.tensorParallelSize === "number" ? engineConfig.tensorParallelSize : 1;
121438
- const args = [
121439
- ...VLLM_START_ARGS,
121440
- "--port",
121441
- String(enginePort),
121442
- "--model",
121443
- modelPath,
121444
- "--served-model-name",
121445
- SERVED_MODEL_NAME,
121446
- "--max-model-len",
121447
- String(contextLength),
121448
- "--tensor-parallel-size",
121449
- String(tensorParallelSize)
121450
- ];
121451
- if (this.model.taskType === "embeddings") {
121452
- args.push("--task", "embed");
121453
- }
121454
- if (device) {
121455
- args.push("--device", device);
121456
- }
121457
- if (dtype) {
121458
- args.push("--dtype", dtype);
121459
- }
121460
- args.push(...parseExtraArgs(engineConfig?.extraArgs));
121461
- if (this.model.multimodalEnabled) {
121462
- args.push("--limit-mm-per-prompt", process.env.VLLM_MM_LIMIT ?? '{"image":5}');
121463
- }
121464
- if (process.env.VLLM_TRUST_REMOTE_CODE === "true") {
121465
- args.push("--trust-remote-code");
121466
- }
121467
- return createEngineProcess({ args, bin: VLLM_EXECUTABLE, logger: this.logger });
121468
- }
121469
-
121470
- // src/lib/cache-management.ts
121471
-
121472
- // src/consts.ts
121473
- var HUB_URL = "https://huggingface.co";
121474
-
121475
- // src/error.ts
121476
- async function createApiError(response, opts) {
121477
- const error = new HubApiError(response.url, response.status, response.headers.get("X-Request-Id") ?? opts?.requestId);
121478
- error.message = `Api error with status ${error.statusCode}${""}`;
121479
- const trailer = [`URL: ${error.url}`, error.requestId ? `Request ID: ${error.requestId}` : void 0].filter(Boolean).join(". ");
121480
- if (response.headers.get("Content-Type")?.startsWith("application/json")) {
121481
- const json = await response.json();
121482
- error.message = json.error || json.message || error.message;
121483
- if (json.error_description) {
121484
- error.message = error.message ? error.message + `: ${json.error_description}` : json.error_description;
121485
- }
121486
- error.data = json;
121487
- } else {
121488
- error.data = { message: await response.text() };
121489
- }
121490
- error.message += `. ${trailer}`;
121491
- throw error;
121492
- }
121493
- var HubApiError = class extends Error {
121494
- statusCode;
121495
- url;
121496
- requestId;
121497
- data;
121498
- constructor(url, statusCode, requestId, message) {
121499
- super(message);
121500
- this.statusCode = statusCode;
121501
- this.requestId = requestId;
121502
- this.url = url;
121503
- }
121504
- };
121505
- var InvalidApiResponseFormatError = class extends Error {
121506
- };
121507
-
121508
- // src/utils/checkCredentials.ts
121509
- function checkAccessToken(accessToken) {
121510
- if (!accessToken.startsWith("hf_")) {
121511
- throw new TypeError("Your access token must start with 'hf_'");
121512
- }
121513
- }
121514
- function checkCredentials(params) {
121515
- if (params.accessToken) {
121516
- checkAccessToken(params.accessToken);
121517
- return params.accessToken;
121518
- }
121519
- if (params.credentials?.accessToken) {
121520
- checkAccessToken(params.credentials.accessToken);
121521
- return params.credentials.accessToken;
121522
- }
121523
- }
121524
-
121525
- // src/utils/toRepoId.ts
121526
- function toRepoId(repo) {
121527
- if (typeof repo !== "string") {
121528
- return repo;
121529
- }
121530
- if (repo.startsWith("model/") || repo.startsWith("models/")) {
121531
- throw new TypeError(
121532
- "A repo designation for a model should not start with 'models/', directly specify the model namespace / name"
121533
- );
121534
- }
121535
- if (repo.startsWith("space/")) {
121536
- throw new TypeError("Spaces should start with 'spaces/', plural, not 'space/'");
121537
- }
121538
- if (repo.startsWith("dataset/")) {
121539
- throw new TypeError("Datasets should start with 'dataset/', plural, not 'dataset/'");
121540
- }
121541
- const slashes = repo.split("/").length - 1;
121542
- if (repo.startsWith("spaces/")) {
121543
- if (slashes !== 2) {
121544
- throw new TypeError("Space Id must include namespace and name of the space");
121545
- }
121546
- return {
121547
- type: "space",
121548
- name: repo.slice("spaces/".length)
121549
- };
121550
- }
121551
- if (repo.startsWith("datasets/")) {
121552
- if (slashes > 2) {
121553
- throw new TypeError("Too many slashes in repo designation: " + repo);
121554
- }
121555
- return {
121556
- type: "dataset",
121557
- name: repo.slice("datasets/".length)
121558
- };
121559
- }
121560
- if (slashes > 1) {
121561
- throw new TypeError("Too many slashes in repo designation: " + repo);
121562
- }
121563
- return {
121564
- type: "model",
121565
- name: repo
121566
- };
121567
- }
121568
- new Promise((r) => {
121569
- });
121570
-
121571
- // src/utils/combineUint8Arrays.ts
121572
- function combineUint8Arrays(a, b) {
121573
- const aLength = a.length;
121574
- const combinedBytes = new Uint8Array(aLength + b.length);
121575
- combinedBytes.set(a);
121576
- combinedBytes.set(b, aLength);
121577
- return combinedBytes;
121578
- }
121579
- function readU64(b, n) {
121580
- let x = 0;
121581
- x |= b[n++] << 0;
121582
- x |= b[n++] << 8;
121583
- x |= b[n++] << 16;
121584
- x |= b[n++] << 24;
121585
- x |= b[n++] << 32;
121586
- x |= b[n++] << 40;
121587
- x |= b[n++] << 48;
121588
- x |= b[n++] << 56;
121589
- return x;
121590
- }
121591
- function readU32(b, n) {
121592
- let x = 0;
121593
- x |= b[n++] << 0;
121594
- x |= b[n++] << 8;
121595
- x |= b[n++] << 16;
121596
- x |= b[n++] << 24;
121597
- return x;
121598
- }
121599
-
121600
- // src/vendor/lz4js/index.ts
121601
- var minMatch = 4;
121602
- var hashSize = 1 << 16;
121603
- makeHashTable();
121604
- var magicNum = 407708164;
121605
- var fdContentChksum = 4;
121606
- var fdContentSize = 8;
121607
- var fdBlockChksum = 16;
121608
- var fdVersion = 64;
121609
- var fdVersionMask = 192;
121610
- var bsUncompressed = 2147483648;
121611
- var bsShift = 4;
121612
- var bsMask = 7;
121613
- var bsMap = {
121614
- 4: 65536,
121615
- 5: 262144,
121616
- 6: 1048576,
121617
- 7: 4194304
121618
- };
121619
- function makeHashTable() {
121620
- try {
121621
- return new Uint32Array(hashSize);
121622
- } catch (error) {
121623
- const hashTable2 = new Array(hashSize);
121624
- for (let i = 0; i < hashSize; i++) {
121625
- hashTable2[i] = 0;
121626
- }
121627
- return hashTable2;
121628
- }
121629
- }
121630
- function makeBuffer(size) {
121631
- return new Uint8Array(size);
121632
- }
121633
- function sliceArray(array, start, end) {
121634
- return array.slice(start, end);
121635
- }
121636
- function decompressBound(src) {
121637
- let sIndex = 0;
121638
- if (readU32(src, sIndex) !== magicNum) {
121639
- throw new Error("invalid magic number");
121640
- }
121641
- sIndex += 4;
121642
- const descriptor = src[sIndex++];
121643
- if ((descriptor & fdVersionMask) !== fdVersion) {
121644
- throw new Error("incompatible descriptor version " + (descriptor & fdVersionMask));
121645
- }
121646
- const useBlockSum = (descriptor & fdBlockChksum) !== 0;
121647
- const useContentSize = (descriptor & fdContentSize) !== 0;
121648
- const bsIdx = src[sIndex++] >> bsShift & bsMask;
121649
- if (bsMap[bsIdx] === void 0) {
121650
- throw new Error("invalid block size " + bsIdx);
121651
- }
121652
- const maxBlockSize = bsMap[bsIdx];
121653
- if (useContentSize) {
121654
- return readU64(src, sIndex);
121655
- }
121656
- sIndex++;
121657
- let maxSize = 0;
121658
- while (true) {
121659
- let blockSize = readU32(src, sIndex);
121660
- sIndex += 4;
121661
- if (blockSize & bsUncompressed) {
121662
- blockSize &= ~bsUncompressed;
121663
- maxSize += blockSize;
121664
- } else if (blockSize > 0) {
121665
- maxSize += maxBlockSize;
121666
- }
121667
- if (blockSize === 0) {
121668
- return maxSize;
121669
- }
121670
- if (useBlockSum) {
121671
- sIndex += 4;
121672
- }
121673
- sIndex += blockSize;
121674
- }
121675
- }
121676
- function decompressBlock(src, dst, sIndex, sLength, dIndex) {
121677
- let mLength, mOffset, sEnd, n, i;
121678
- const hasCopyWithin = dst.copyWithin !== void 0 && dst.fill !== void 0;
121679
- sEnd = sIndex + sLength;
121680
- while (sIndex < sEnd) {
121681
- const token = src[sIndex++];
121682
- let literalCount = token >> 4;
121683
- if (literalCount > 0) {
121684
- if (literalCount === 15) {
121685
- while (true) {
121686
- literalCount += src[sIndex];
121687
- if (src[sIndex++] !== 255) {
121688
- break;
121689
- }
121690
- }
121691
- }
121692
- for (n = sIndex + literalCount; sIndex < n; ) {
121693
- dst[dIndex++] = src[sIndex++];
121694
- }
121695
- }
121696
- if (sIndex >= sEnd) {
121697
- break;
121698
- }
121699
- mLength = token & 15;
121700
- mOffset = src[sIndex++] | src[sIndex++] << 8;
121701
- if (mLength === 15) {
121702
- while (true) {
121703
- mLength += src[sIndex];
121704
- if (src[sIndex++] !== 255) {
121705
- break;
121706
- }
121707
- }
121708
- }
121709
- mLength += minMatch;
121710
- if (hasCopyWithin && mOffset === 1) {
121711
- dst.fill(dst[dIndex - 1] | 0, dIndex, dIndex + mLength);
121712
- dIndex += mLength;
121713
- } else if (hasCopyWithin && mOffset > mLength && mLength > 31) {
121714
- dst.copyWithin(dIndex, dIndex - mOffset, dIndex - mOffset + mLength);
121715
- dIndex += mLength;
121716
- } else {
121717
- for (i = dIndex - mOffset, n = i + mLength; i < n; ) {
121718
- dst[dIndex++] = dst[i++] | 0;
121719
- }
121720
- }
121721
- }
121722
- return dIndex;
121723
- }
121724
- function decompressFrame(src, dst) {
121725
- let useBlockSum, useContentSum, useContentSize, descriptor;
121726
- let sIndex = 0;
121727
- let dIndex = 0;
121728
- if (readU32(src, sIndex) !== magicNum) {
121729
- throw new Error("invalid magic number");
121730
- }
121731
- sIndex += 4;
121732
- descriptor = src[sIndex++];
121733
- if ((descriptor & fdVersionMask) !== fdVersion) {
121734
- throw new Error("incompatible descriptor version");
121735
- }
121736
- useBlockSum = (descriptor & fdBlockChksum) !== 0;
121737
- useContentSum = (descriptor & fdContentChksum) !== 0;
121738
- useContentSize = (descriptor & fdContentSize) !== 0;
121739
- const bsIdx = src[sIndex++] >> bsShift & bsMask;
121740
- if (bsMap[bsIdx] === void 0) {
121741
- throw new Error("invalid block size");
121742
- }
121743
- if (useContentSize) {
121744
- sIndex += 8;
121745
- }
121746
- sIndex++;
121747
- while (true) {
121748
- var compSize;
121749
- compSize = readU32(src, sIndex);
121750
- sIndex += 4;
121751
- if (compSize === 0) {
121752
- break;
121753
- }
121754
- if (useBlockSum) {
121755
- sIndex += 4;
121756
- }
121757
- if ((compSize & bsUncompressed) !== 0) {
121758
- compSize &= ~bsUncompressed;
121759
- for (let j = 0; j < compSize; j++) {
121760
- dst[dIndex++] = src[sIndex++];
121761
- }
121762
- } else {
121763
- dIndex = decompressBlock(src, dst, sIndex, compSize, dIndex);
121764
- sIndex += compSize;
121765
- }
121766
- }
121767
- if (useContentSum) {
121768
- sIndex += 4;
121769
- }
121770
- return dIndex;
121771
- }
121772
- function decompress(src, maxSize) {
121773
- let dst, size;
121774
- if (maxSize === void 0) {
121775
- maxSize = decompressBound(src);
121776
- }
121777
- dst = makeBuffer(maxSize);
121778
- size = decompressFrame(src, dst);
121779
- if (size !== maxSize) {
121780
- dst = sliceArray(dst, 0, size);
121781
- }
121782
- return dst;
121783
- }
121784
-
121785
- // src/utils/RangeList.ts
121786
- var RangeList = class {
121787
- ranges = [];
121788
- /**
121789
- * Add a range to the list. If it overlaps with existing ranges,
121790
- * it will split them and increment reference counts accordingly.
121791
- */
121792
- add(start, end) {
121793
- if (end <= start) {
121794
- throw new TypeError("End must be greater than start");
121795
- }
121796
- const overlappingRanges = [];
121797
- for (let i = 0; i < this.ranges.length; i++) {
121798
- const range2 = this.ranges[i];
121799
- if (start < range2.end && end > range2.start) {
121800
- overlappingRanges.push({ index: i, range: range2 });
121801
- }
121802
- if (range2.data !== null) {
121803
- throw new Error("Overlapping range already has data");
121804
- }
121805
- }
121806
- if (overlappingRanges.length === 0) {
121807
- this.ranges.push({ start, end, refCount: 1, data: null });
121808
- this.ranges.sort((a, b) => a.start - b.start);
121809
- return;
121810
- }
121811
- const newRanges = [];
121812
- let currentPos = start;
121813
- for (let i = 0; i < overlappingRanges.length; i++) {
121814
- const { range: range2 } = overlappingRanges[i];
121815
- if (currentPos < range2.start) {
121816
- newRanges.push({
121817
- start: currentPos,
121818
- end: range2.start,
121819
- refCount: 1,
121820
- data: null
121821
- });
121822
- } else if (range2.start < currentPos) {
121823
- newRanges.push({
121824
- start: range2.start,
121825
- end: currentPos,
121826
- refCount: range2.refCount,
121827
- data: null
121828
- });
121829
- }
121830
- newRanges.push({
121831
- start: Math.max(currentPos, range2.start),
121832
- end: Math.min(end, range2.end),
121833
- refCount: range2.refCount + 1,
121834
- data: null
121835
- });
121836
- if (range2.end > end) {
121837
- newRanges.push({
121838
- start: end,
121839
- end: range2.end,
121840
- refCount: range2.refCount,
121841
- data: null
121842
- });
121843
- }
121844
- currentPos = Math.max(currentPos, range2.end);
121845
- }
121846
- if (currentPos < end) {
121847
- newRanges.push({
121848
- start: currentPos,
121849
- end,
121850
- refCount: 1,
121851
- data: null
121852
- });
121853
- }
121854
- const firstIndex = overlappingRanges[0].index;
121855
- const lastIndex = overlappingRanges[overlappingRanges.length - 1].index;
121856
- this.ranges.splice(firstIndex, lastIndex - firstIndex + 1, ...newRanges);
121857
- this.ranges.sort((a, b) => a.start - b.start);
121858
- }
121859
- /**
121860
- * Remove a range from the list. The range must start and end at existing boundaries.
121861
- */
121862
- remove(start, end) {
121863
- if (end <= start) {
121864
- throw new TypeError("End must be greater than start");
121865
- }
121866
- const affectedRanges = [];
121867
- for (let i = 0; i < this.ranges.length; i++) {
121868
- const range2 = this.ranges[i];
121869
- if (start < range2.end && end > range2.start) {
121870
- affectedRanges.push({ index: i, range: range2 });
121871
- }
121872
- }
121873
- if (affectedRanges.length === 0) {
121874
- throw new Error("No ranges found to remove");
121875
- }
121876
- if (start !== affectedRanges[0].range.start || end !== affectedRanges[affectedRanges.length - 1].range.end) {
121877
- throw new Error("Range boundaries must match existing boundaries");
121878
- }
121879
- for (let i = 0; i < affectedRanges.length; i++) {
121880
- const { range: range2 } = affectedRanges[i];
121881
- range2.refCount--;
121882
- }
121883
- this.ranges = this.ranges.filter((range2) => range2.refCount > 0);
121884
- }
121885
- /**
121886
- * Get all ranges within the specified boundaries.
121887
- */
121888
- getRanges(start, end) {
121889
- if (end <= start) {
121890
- throw new TypeError("End must be greater than start");
121891
- }
121892
- return this.ranges.filter((range2) => start < range2.end && end > range2.start);
121893
- }
121894
- /**
121895
- * Get all ranges in the list
121896
- */
121897
- getAllRanges() {
121898
- return [...this.ranges];
121899
- }
121900
- };
121901
-
121902
- // src/utils/XetBlob.ts
121903
- var JWT_SAFETY_PERIOD = 6e4;
121904
- var JWT_CACHE_SIZE = 1e3;
121905
- var compressionSchemeLabels = {
121906
- [0 /* None */]: "None",
121907
- [1 /* LZ4 */]: "LZ4",
121908
- [2 /* ByteGroupingLZ4 */]: "ByteGroupingLZ4"
121909
- };
121910
- var XET_CHUNK_HEADER_BYTES = 8;
121911
- var XetBlob = class extends Blob {
121912
- fetch;
121913
- accessToken;
121914
- refreshUrl;
121915
- reconstructionUrl;
121916
- hash;
121917
- start = 0;
121918
- end = 0;
121919
- internalLogging = false;
121920
- reconstructionInfo;
121921
- listener;
121922
- constructor(params) {
121923
- super([]);
121924
- this.fetch = params.fetch ?? fetch.bind(globalThis);
121925
- this.accessToken = checkCredentials(params);
121926
- this.refreshUrl = params.refreshUrl;
121927
- this.end = params.size;
121928
- this.reconstructionUrl = params.reconstructionUrl;
121929
- this.hash = params.hash;
121930
- this.listener = params.listener;
121931
- this.internalLogging = params.internalLogging ?? false;
121932
- this.refreshUrl;
121933
- }
121934
- get size() {
121935
- return this.end - this.start;
121936
- }
121937
- #clone() {
121938
- const blob = new XetBlob({
121939
- fetch: this.fetch,
121940
- hash: this.hash,
121941
- refreshUrl: this.refreshUrl,
121942
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
121943
- reconstructionUrl: this.reconstructionUrl,
121944
- size: this.size
121945
- });
121946
- blob.accessToken = this.accessToken;
121947
- blob.start = this.start;
121948
- blob.end = this.end;
121949
- blob.reconstructionInfo = this.reconstructionInfo;
121950
- blob.listener = this.listener;
121951
- blob.internalLogging = this.internalLogging;
121952
- return blob;
121953
- }
121954
- slice(start = 0, end = this.size) {
121955
- const slice = this.#clone();
121956
- slice.start = this.start + start;
121957
- slice.end = Math.min(this.start + end, this.end);
121958
- if (slice.start !== this.start || slice.end !== this.end) {
121959
- slice.reconstructionInfo = void 0;
122136
+ if (this.#ignored(m))
122137
+ continue;
122138
+ this.matchSync(m, absolute, ifDir);
122139
+ }
122140
+ for (const [target, patterns] of processor.subwalks.entries()) {
122141
+ tasks++;
122142
+ this.walkCB2Sync(target, patterns, processor.child(), next);
122143
+ }
122144
+ next();
121960
122145
  }
121961
- return slice;
121962
- }
121963
- #reconstructionInfoPromise;
121964
- #loadReconstructionInfo() {
121965
- if (this.#reconstructionInfoPromise) {
121966
- return this.#reconstructionInfoPromise;
122146
+ }
122147
+ class GlobWalker extends GlobUtil {
122148
+ matches = new Set();
122149
+ constructor(patterns, path, opts) {
122150
+ super(patterns, path, opts);
121967
122151
  }
121968
- this.#reconstructionInfoPromise = (async () => {
121969
- const connParams = await getAccessToken(this.accessToken, this.fetch, this.refreshUrl);
121970
- const resp = await this.fetch(this.reconstructionUrl ?? `${connParams.casUrl}/v1/reconstructions/${this.hash}`, {
121971
- headers: {
121972
- Authorization: `Bearer ${connParams.accessToken}`,
121973
- Range: `bytes=${this.start}-${this.end - 1}`
122152
+ matchEmit(e) {
122153
+ this.matches.add(e);
122154
+ }
122155
+ async walk() {
122156
+ if (this.signal?.aborted)
122157
+ throw this.signal.reason;
122158
+ if (this.path.isUnknown()) {
122159
+ await this.path.lstat();
121974
122160
  }
121975
- });
121976
- if (!resp.ok) {
121977
- throw await createApiError(resp);
121978
- }
121979
- this.reconstructionInfo = await resp.json();
121980
- return this.reconstructionInfo;
121981
- })().finally(() => this.#reconstructionInfoPromise = void 0);
121982
- return this.#reconstructionInfoPromise;
121983
- }
121984
- async #fetch() {
121985
- if (!this.reconstructionInfo) {
121986
- await this.#loadReconstructionInfo();
122161
+ await new Promise((res, rej) => {
122162
+ this.walkCB(this.path, this.patterns, () => {
122163
+ if (this.signal?.aborted) {
122164
+ rej(this.signal.reason);
122165
+ }
122166
+ else {
122167
+ res(this.matches);
122168
+ }
122169
+ });
122170
+ });
122171
+ return this.matches;
121987
122172
  }
121988
- const rangeLists = /* @__PURE__ */ new Map();
121989
- if (!this.reconstructionInfo) {
121990
- throw new Error("Failed to load reconstruction info");
122173
+ walkSync() {
122174
+ if (this.signal?.aborted)
122175
+ throw this.signal.reason;
122176
+ if (this.path.isUnknown()) {
122177
+ this.path.lstatSync();
122178
+ }
122179
+ // nothing for the callback to do, because this never pauses
122180
+ this.walkCBSync(this.path, this.patterns, () => {
122181
+ if (this.signal?.aborted)
122182
+ throw this.signal.reason;
122183
+ });
122184
+ return this.matches;
121991
122185
  }
121992
- for (const term of this.reconstructionInfo.terms) {
121993
- let rangeList = rangeLists.get(term.hash);
121994
- if (!rangeList) {
121995
- rangeList = new RangeList();
121996
- rangeLists.set(term.hash, rangeList);
121997
- }
121998
- rangeList.add(term.range.start, term.range.end);
122186
+ }
122187
+ class GlobStream extends GlobUtil {
122188
+ results;
122189
+ constructor(patterns, path, opts) {
122190
+ super(patterns, path, opts);
122191
+ this.results = new Minipass({
122192
+ signal: this.signal,
122193
+ objectMode: true,
122194
+ });
122195
+ this.results.on('drain', () => this.resume());
122196
+ this.results.on('resume', () => this.resume());
121999
122197
  }
122000
- const listener = this.listener;
122001
- const log = this.internalLogging ? (...args) => console.log(...args) : () => {
122002
- };
122003
- async function* readData(reconstructionInfo, customFetch, maxBytes, reloadReconstructionInfo) {
122004
- let totalBytesRead = 0;
122005
- let readBytesToSkip = reconstructionInfo.offset_into_first_range;
122006
- for (const term of reconstructionInfo.terms) {
122007
- if (totalBytesRead >= maxBytes) {
122008
- break;
122198
+ matchEmit(e) {
122199
+ this.results.write(e);
122200
+ if (!this.results.flowing)
122201
+ this.pause();
122202
+ }
122203
+ stream() {
122204
+ const target = this.path;
122205
+ if (target.isUnknown()) {
122206
+ target.lstat().then(() => {
122207
+ this.walkCB(target, this.patterns, () => this.results.end());
122208
+ });
122009
122209
  }
122010
- const rangeList = rangeLists.get(term.hash);
122011
- if (!rangeList) {
122012
- throw new Error(`Failed to find range list for term ${term.hash}`);
122210
+ else {
122211
+ this.walkCB(target, this.patterns, () => this.results.end());
122013
122212
  }
122014
- {
122015
- const termRanges = rangeList.getRanges(term.range.start, term.range.end);
122016
- if (termRanges.every((range2) => range2.data)) {
122017
- log("all data available for term", term.hash, readBytesToSkip);
122018
- rangeLoop:
122019
- for (const range2 of termRanges) {
122020
- for (let chunk2 of range2.data) {
122021
- if (readBytesToSkip) {
122022
- const skipped = Math.min(readBytesToSkip, chunk2.byteLength);
122023
- chunk2 = chunk2.slice(skipped);
122024
- readBytesToSkip -= skipped;
122025
- if (!chunk2.byteLength) {
122026
- continue;
122027
- }
122028
- }
122029
- if (chunk2.byteLength > maxBytes - totalBytesRead) {
122030
- chunk2 = chunk2.slice(0, maxBytes - totalBytesRead);
122031
- }
122032
- totalBytesRead += chunk2.byteLength;
122033
- yield range2.refCount > 1 ? chunk2.slice() : chunk2;
122034
- listener?.({ event: "progress", progress: { read: totalBytesRead, total: maxBytes } });
122035
- if (totalBytesRead >= maxBytes) {
122036
- break rangeLoop;
122037
- }
122038
- }
122039
- }
122040
- rangeList.remove(term.range.start, term.range.end);
122041
- continue;
122042
- }
122213
+ return this.results;
122214
+ }
122215
+ streamSync() {
122216
+ if (this.path.isUnknown()) {
122217
+ this.path.lstatSync();
122043
122218
  }
122044
- const fetchInfo = reconstructionInfo.fetch_info[term.hash].find(
122045
- (info) => info.range.start <= term.range.start && info.range.end >= term.range.end
122046
- );
122047
- if (!fetchInfo) {
122048
- throw new Error(
122049
- `Failed to find fetch info for term ${term.hash} and range ${term.range.start}-${term.range.end}`
122050
- );
122219
+ this.walkCBSync(this.path, this.patterns, () => this.results.end());
122220
+ return this.results;
122221
+ }
122222
+ }
122223
+
122224
+ // if no process global, just call it linux.
122225
+ // so we default to case-sensitive, / separators
122226
+ const defaultPlatform = (typeof process === 'object' &&
122227
+ process &&
122228
+ typeof process.platform === 'string') ?
122229
+ process.platform
122230
+ : 'linux';
122231
+ /**
122232
+ * An object that can perform glob pattern traversals.
122233
+ */
122234
+ class Glob {
122235
+ absolute;
122236
+ cwd;
122237
+ root;
122238
+ dot;
122239
+ dotRelative;
122240
+ follow;
122241
+ ignore;
122242
+ magicalBraces;
122243
+ mark;
122244
+ matchBase;
122245
+ maxDepth;
122246
+ nobrace;
122247
+ nocase;
122248
+ nodir;
122249
+ noext;
122250
+ noglobstar;
122251
+ pattern;
122252
+ platform;
122253
+ realpath;
122254
+ scurry;
122255
+ stat;
122256
+ signal;
122257
+ windowsPathsNoEscape;
122258
+ withFileTypes;
122259
+ includeChildMatches;
122260
+ /**
122261
+ * The options provided to the constructor.
122262
+ */
122263
+ opts;
122264
+ /**
122265
+ * An array of parsed immutable {@link Pattern} objects.
122266
+ */
122267
+ patterns;
122268
+ /**
122269
+ * All options are stored as properties on the `Glob` object.
122270
+ *
122271
+ * See {@link GlobOptions} for full options descriptions.
122272
+ *
122273
+ * Note that a previous `Glob` object can be passed as the
122274
+ * `GlobOptions` to another `Glob` instantiation to re-use settings
122275
+ * and caches with a new pattern.
122276
+ *
122277
+ * Traversal functions can be called multiple times to run the walk
122278
+ * again.
122279
+ */
122280
+ constructor(pattern, opts) {
122281
+ /* c8 ignore start */
122282
+ if (!opts)
122283
+ throw new TypeError('glob options required');
122284
+ /* c8 ignore stop */
122285
+ this.withFileTypes = !!opts.withFileTypes;
122286
+ this.signal = opts.signal;
122287
+ this.follow = !!opts.follow;
122288
+ this.dot = !!opts.dot;
122289
+ this.dotRelative = !!opts.dotRelative;
122290
+ this.nodir = !!opts.nodir;
122291
+ this.mark = !!opts.mark;
122292
+ if (!opts.cwd) {
122293
+ this.cwd = '';
122051
122294
  }
122052
- log("term", term);
122053
- log("fetchinfo", fetchInfo);
122054
- log("readBytesToSkip", readBytesToSkip);
122055
- let resp = await customFetch(fetchInfo.url, {
122056
- headers: {
122057
- Range: `bytes=${fetchInfo.url_range.start}-${fetchInfo.url_range.end}`
122058
- }
122059
- });
122060
- if (resp.status === 403) {
122061
- reconstructionInfo = await reloadReconstructionInfo();
122062
- resp = await customFetch(fetchInfo.url, {
122063
- headers: {
122064
- Range: `bytes=${fetchInfo.url_range.start}-${fetchInfo.url_range.end}`
122065
- }
122066
- });
122295
+ else if (opts.cwd instanceof URL || opts.cwd.startsWith('file://')) {
122296
+ opts.cwd = require$$0$l.fileURLToPath(opts.cwd);
122067
122297
  }
122068
- if (!resp.ok) {
122069
- throw await createApiError(resp);
122298
+ this.cwd = opts.cwd || '';
122299
+ this.root = opts.root;
122300
+ this.magicalBraces = !!opts.magicalBraces;
122301
+ this.nobrace = !!opts.nobrace;
122302
+ this.noext = !!opts.noext;
122303
+ this.realpath = !!opts.realpath;
122304
+ this.absolute = opts.absolute;
122305
+ this.includeChildMatches = opts.includeChildMatches !== false;
122306
+ this.noglobstar = !!opts.noglobstar;
122307
+ this.matchBase = !!opts.matchBase;
122308
+ this.maxDepth =
122309
+ typeof opts.maxDepth === 'number' ? opts.maxDepth : Infinity;
122310
+ this.stat = !!opts.stat;
122311
+ this.ignore = opts.ignore;
122312
+ if (this.withFileTypes && this.absolute !== undefined) {
122313
+ throw new Error('cannot set absolute and withFileTypes:true');
122070
122314
  }
122071
- log(
122072
- "expected content length",
122073
- resp.headers.get("content-length"),
122074
- "range",
122075
- fetchInfo.url_range,
122076
- resp.headers.get("content-range")
122077
- );
122078
- const reader = resp.body?.getReader();
122079
- if (!reader) {
122080
- throw new Error("Failed to get reader from response body");
122315
+ if (typeof pattern === 'string') {
122316
+ pattern = [pattern];
122081
122317
  }
122082
- let done = false;
122083
- let chunkIndex = fetchInfo.range.start;
122084
- const ranges = rangeList.getRanges(fetchInfo.range.start, fetchInfo.range.end);
122085
- let leftoverBytes = void 0;
122086
- let totalFetchBytes = 0;
122087
- fetchData:
122088
- while (!done && totalBytesRead < maxBytes) {
122089
- const result = await reader.read();
122090
- listener?.({ event: "read" });
122091
- done = result.done;
122092
- log("read", result.value?.byteLength, "bytes", "total read", totalBytesRead, "toSkip", readBytesToSkip);
122093
- if (!result.value) {
122094
- log("no data in result, cancelled", result);
122095
- continue;
122096
- }
122097
- totalFetchBytes += result.value.byteLength;
122098
- if (leftoverBytes) {
122099
- result.value = combineUint8Arrays(leftoverBytes, result.value);
122100
- leftoverBytes = void 0;
122318
+ this.windowsPathsNoEscape =
122319
+ !!opts.windowsPathsNoEscape ||
122320
+ opts.allowWindowsEscape ===
122321
+ false;
122322
+ if (this.windowsPathsNoEscape) {
122323
+ pattern = pattern.map(p => p.replace(/\\/g, '/'));
122324
+ }
122325
+ if (this.matchBase) {
122326
+ if (opts.noglobstar) {
122327
+ throw new TypeError('base matching requires globstar');
122101
122328
  }
122102
- while (totalBytesRead < maxBytes && result.value?.byteLength) {
122103
- if (result.value.byteLength < 8) {
122104
- leftoverBytes = result.value;
122105
- continue fetchData;
122106
- }
122107
- const header = new DataView(result.value.buffer, result.value.byteOffset, XET_CHUNK_HEADER_BYTES);
122108
- const chunkHeader = {
122109
- version: header.getUint8(0),
122110
- compressed_length: header.getUint8(1) | header.getUint8(2) << 8 | header.getUint8(3) << 16,
122111
- compression_scheme: header.getUint8(4),
122112
- uncompressed_length: header.getUint8(5) | header.getUint8(6) << 8 | header.getUint8(7) << 16
122113
- };
122114
- log("chunk header", chunkHeader, "to skip", readBytesToSkip);
122115
- if (chunkHeader.version !== 0) {
122116
- throw new Error(`Unsupported chunk version ${chunkHeader.version}`);
122117
- }
122118
- if (chunkHeader.compression_scheme !== 0 /* None */ && chunkHeader.compression_scheme !== 1 /* LZ4 */ && chunkHeader.compression_scheme !== 2 /* ByteGroupingLZ4 */) {
122119
- throw new Error(
122120
- `Unsupported compression scheme ${compressionSchemeLabels[chunkHeader.compression_scheme] ?? chunkHeader.compression_scheme}`
122121
- );
122122
- }
122123
- if (result.value.byteLength < chunkHeader.compressed_length + XET_CHUNK_HEADER_BYTES) {
122124
- leftoverBytes = result.value;
122125
- continue fetchData;
122126
- }
122127
- result.value = result.value.slice(XET_CHUNK_HEADER_BYTES);
122128
- let uncompressed = chunkHeader.compression_scheme === 1 /* LZ4 */ ? decompress(result.value.slice(0, chunkHeader.compressed_length), chunkHeader.uncompressed_length) : chunkHeader.compression_scheme === 2 /* ByteGroupingLZ4 */ ? bg4_regroup_bytes(
122129
- decompress(
122130
- result.value.slice(0, chunkHeader.compressed_length),
122131
- chunkHeader.uncompressed_length
122132
- )
122133
- ) : result.value.slice(0, chunkHeader.compressed_length);
122134
- const range2 = ranges.find((range3) => chunkIndex >= range3.start && chunkIndex < range3.end);
122135
- const shouldYield = chunkIndex >= term.range.start && chunkIndex < term.range.end;
122136
- const minRefCountToStore = shouldYield ? 2 : 1;
122137
- let stored = false;
122138
- if (range2 && range2.refCount >= minRefCountToStore) {
122139
- range2.data ??= [];
122140
- range2.data.push(uncompressed);
122141
- stored = true;
122142
- }
122143
- if (shouldYield) {
122144
- if (readBytesToSkip) {
122145
- const skipped = Math.min(readBytesToSkip, uncompressed.byteLength);
122146
- uncompressed = uncompressed.slice(readBytesToSkip);
122147
- readBytesToSkip -= skipped;
122148
- }
122149
- if (uncompressed.byteLength > maxBytes - totalBytesRead) {
122150
- uncompressed = uncompressed.slice(0, maxBytes - totalBytesRead);
122151
- }
122152
- if (uncompressed.byteLength) {
122153
- log(
122154
- "yield",
122155
- uncompressed.byteLength,
122156
- "bytes",
122157
- result.value.byteLength,
122158
- "total read",
122159
- totalBytesRead,
122160
- stored
122161
- );
122162
- totalBytesRead += uncompressed.byteLength;
122163
- yield stored ? uncompressed.slice() : uncompressed;
122164
- listener?.({ event: "progress", progress: { read: totalBytesRead, total: maxBytes } });
122165
- }
122166
- }
122167
- chunkIndex++;
122168
- result.value = result.value.slice(chunkHeader.compressed_length);
122329
+ pattern = pattern.map(p => (p.includes('/') ? p : `./**/${p}`));
122330
+ }
122331
+ this.pattern = pattern;
122332
+ this.platform = opts.platform || defaultPlatform;
122333
+ this.opts = { ...opts, platform: this.platform };
122334
+ if (opts.scurry) {
122335
+ this.scurry = opts.scurry;
122336
+ if (opts.nocase !== undefined &&
122337
+ opts.nocase !== opts.scurry.nocase) {
122338
+ throw new Error('nocase option contradicts provided scurry option');
122169
122339
  }
122170
- }
122171
- if (done && totalBytesRead < maxBytes && totalFetchBytes < fetchInfo.url_range.end - fetchInfo.url_range.start + 1) {
122172
- log("done", done, "total read", totalBytesRead, maxBytes, totalFetchBytes);
122173
- log("failed to fetch all data for term", term.hash);
122174
- throw new Error(
122175
- `Failed to fetch all data for term ${term.hash}, fetched ${totalFetchBytes} bytes out of ${fetchInfo.url_range.end - fetchInfo.url_range.start + 1}`
122176
- );
122177
122340
  }
122178
- log("done", done, "total read", totalBytesRead, maxBytes, totalFetchBytes);
122179
- log("cancel reader");
122180
- await reader.cancel();
122181
- }
122341
+ else {
122342
+ const Scurry = opts.platform === 'win32' ? PathScurryWin32
122343
+ : opts.platform === 'darwin' ? PathScurryDarwin
122344
+ : opts.platform ? PathScurryPosix
122345
+ : PathScurry;
122346
+ this.scurry = new Scurry(this.cwd, {
122347
+ nocase: opts.nocase,
122348
+ fs: opts.fs,
122349
+ });
122350
+ }
122351
+ this.nocase = this.scurry.nocase;
122352
+ // If you do nocase:true on a case-sensitive file system, then
122353
+ // we need to use regexps instead of strings for non-magic
122354
+ // path portions, because statting `aBc` won't return results
122355
+ // for the file `AbC` for example.
122356
+ const nocaseMagicOnly = this.platform === 'darwin' || this.platform === 'win32';
122357
+ const mmo = {
122358
+ // default nocase based on platform
122359
+ ...opts,
122360
+ dot: this.dot,
122361
+ matchBase: this.matchBase,
122362
+ nobrace: this.nobrace,
122363
+ nocase: this.nocase,
122364
+ nocaseMagicOnly,
122365
+ nocomment: true,
122366
+ noext: this.noext,
122367
+ nonegate: true,
122368
+ optimizationLevel: 2,
122369
+ platform: this.platform,
122370
+ windowsPathsNoEscape: this.windowsPathsNoEscape,
122371
+ debug: !!this.opts.debug,
122372
+ };
122373
+ const mms = this.pattern.map(p => new Minimatch(p, mmo));
122374
+ const [matchSet, globParts] = mms.reduce((set, m) => {
122375
+ set[0].push(...m.set);
122376
+ set[1].push(...m.globParts);
122377
+ return set;
122378
+ }, [[], []]);
122379
+ this.patterns = matchSet.map((set, i) => {
122380
+ const g = globParts[i];
122381
+ /* c8 ignore start */
122382
+ if (!g)
122383
+ throw new Error('invalid pattern object');
122384
+ /* c8 ignore stop */
122385
+ return new Pattern(set, g, 0, this.platform);
122386
+ });
122182
122387
  }
122183
- const iterator = readData(
122184
- this.reconstructionInfo,
122185
- this.fetch,
122186
- this.end - this.start,
122187
- this.#loadReconstructionInfo.bind(this)
122188
- );
122189
- return new ReadableStream(
122190
- {
122191
- // todo: when Safari supports it, type controller as ReadableByteStreamController
122192
- async pull(controller) {
122193
- const result = await iterator.next();
122194
- if (result.value) {
122195
- controller.enqueue(result.value);
122196
- }
122197
- if (result.done) {
122198
- controller.close();
122199
- }
122200
- },
122201
- type: "bytes"
122202
- // todo: when Safari supports it, add autoAllocateChunkSize param
122203
- },
122204
- // todo : use ByteLengthQueuingStrategy when there's good support for it, currently in Node.js it fails due to size being a function
122205
- {
122206
- highWaterMark: 1e3
122207
- // 1_000 chunks for ~1MB of RAM
122208
- }
122209
- );
122210
- }
122211
- async arrayBuffer() {
122212
- const result = await this.#fetch();
122213
- return new Response(result).arrayBuffer();
122214
- }
122215
- async text() {
122216
- const result = await this.#fetch();
122217
- return new Response(result).text();
122218
- }
122219
- async response() {
122220
- const result = await this.#fetch();
122221
- return new Response(result);
122222
- }
122223
- stream() {
122224
- const stream = new TransformStream();
122225
- this.#fetch().then((response) => response.pipeThrough(stream)).catch((error) => stream.writable.abort(error.message));
122226
- return stream.readable;
122227
- }
122228
- };
122229
- var jwtPromises = /* @__PURE__ */ new Map();
122230
- var jwts = /* @__PURE__ */ new Map();
122231
- function cacheKey(params) {
122232
- return JSON.stringify([params.refreshUrl, params.initialAccessToken]);
122233
- }
122234
- function bg4_regroup_bytes(bytes) {
122235
- const split = Math.floor(bytes.byteLength / 4);
122236
- const rem = bytes.byteLength % 4;
122237
- const g1_pos = split + (rem >= 1 ? 1 : 0);
122238
- const g2_pos = g1_pos + split + (rem >= 2 ? 1 : 0);
122239
- const g3_pos = g2_pos + split + (rem == 3 ? 1 : 0);
122240
- const ret = new Uint8Array(bytes.byteLength);
122241
- for (let i = 0, j = 0; i < bytes.byteLength; i += 4, j++) {
122242
- ret[i] = bytes[j];
122243
- }
122244
- for (let i = 1, j = g1_pos; i < bytes.byteLength; i += 4, j++) {
122245
- ret[i] = bytes[j];
122246
- }
122247
- for (let i = 2, j = g2_pos; i < bytes.byteLength; i += 4, j++) {
122248
- ret[i] = bytes[j];
122249
- }
122250
- for (let i = 3, j = g3_pos; i < bytes.byteLength; i += 4, j++) {
122251
- ret[i] = bytes[j];
122252
- }
122253
- return ret;
122254
- }
122255
- async function getAccessToken(initialAccessToken, customFetch, refreshUrl) {
122256
- const key = cacheKey({ refreshUrl, initialAccessToken });
122257
- const jwt = jwts.get(key);
122258
- if (jwt && jwt.expiresAt > new Date(Date.now() + JWT_SAFETY_PERIOD)) {
122259
- return { accessToken: jwt.accessToken, casUrl: jwt.casUrl };
122260
- }
122261
- const existingPromise = jwtPromises.get(key);
122262
- if (existingPromise) {
122263
- return existingPromise;
122264
- }
122265
- const promise = (async () => {
122266
- const resp = await customFetch(refreshUrl, {
122267
- headers: {
122268
- ...initialAccessToken ? {
122269
- Authorization: `Bearer ${initialAccessToken}`
122270
- } : {}
122271
- }
122272
- });
122273
- if (!resp.ok) {
122274
- throw new Error(`Failed to get JWT token: ${resp.status} ${await resp.text()}`);
122388
+ async walk() {
122389
+ // Walkers always return array of Path objects, so we just have to
122390
+ // coerce them into the right shape. It will have already called
122391
+ // realpath() if the option was set to do so, so we know that's cached.
122392
+ // start out knowing the cwd, at least
122393
+ return [
122394
+ ...(await new GlobWalker(this.patterns, this.scurry.cwd, {
122395
+ ...this.opts,
122396
+ maxDepth: this.maxDepth !== Infinity ?
122397
+ this.maxDepth + this.scurry.cwd.depth()
122398
+ : Infinity,
122399
+ platform: this.platform,
122400
+ nocase: this.nocase,
122401
+ includeChildMatches: this.includeChildMatches,
122402
+ }).walk()),
122403
+ ];
122275
122404
  }
122276
- const json = await resp.json();
122277
- const jwt2 = {
122278
- accessToken: json.accessToken,
122279
- expiresAt: new Date(json.exp * 1e3),
122280
- casUrl: json.casUrl
122281
- };
122282
- jwtPromises.delete(key);
122283
- for (const [key2, value] of jwts.entries()) {
122284
- if (value.expiresAt < new Date(Date.now() + JWT_SAFETY_PERIOD)) {
122285
- jwts.delete(key2);
122286
- } else {
122287
- break;
122288
- }
122405
+ walkSync() {
122406
+ return [
122407
+ ...new GlobWalker(this.patterns, this.scurry.cwd, {
122408
+ ...this.opts,
122409
+ maxDepth: this.maxDepth !== Infinity ?
122410
+ this.maxDepth + this.scurry.cwd.depth()
122411
+ : Infinity,
122412
+ platform: this.platform,
122413
+ nocase: this.nocase,
122414
+ includeChildMatches: this.includeChildMatches,
122415
+ }).walkSync(),
122416
+ ];
122289
122417
  }
122290
- if (jwts.size >= JWT_CACHE_SIZE) {
122291
- const keyToDelete = jwts.keys().next().value;
122292
- if (keyToDelete) {
122293
- jwts.delete(keyToDelete);
122294
- }
122418
+ stream() {
122419
+ return new GlobStream(this.patterns, this.scurry.cwd, {
122420
+ ...this.opts,
122421
+ maxDepth: this.maxDepth !== Infinity ?
122422
+ this.maxDepth + this.scurry.cwd.depth()
122423
+ : Infinity,
122424
+ platform: this.platform,
122425
+ nocase: this.nocase,
122426
+ includeChildMatches: this.includeChildMatches,
122427
+ }).stream();
122428
+ }
122429
+ streamSync() {
122430
+ return new GlobStream(this.patterns, this.scurry.cwd, {
122431
+ ...this.opts,
122432
+ maxDepth: this.maxDepth !== Infinity ?
122433
+ this.maxDepth + this.scurry.cwd.depth()
122434
+ : Infinity,
122435
+ platform: this.platform,
122436
+ nocase: this.nocase,
122437
+ includeChildMatches: this.includeChildMatches,
122438
+ }).streamSync();
122439
+ }
122440
+ /**
122441
+ * Default sync iteration function. Returns a Generator that
122442
+ * iterates over the results.
122443
+ */
122444
+ iterateSync() {
122445
+ return this.streamSync()[Symbol.iterator]();
122446
+ }
122447
+ [Symbol.iterator]() {
122448
+ return this.iterateSync();
122449
+ }
122450
+ /**
122451
+ * Default async iteration function. Returns an AsyncGenerator that
122452
+ * iterates over the results.
122453
+ */
122454
+ iterate() {
122455
+ return this.stream()[Symbol.asyncIterator]();
122456
+ }
122457
+ [Symbol.asyncIterator]() {
122458
+ return this.iterate();
122295
122459
  }
122296
- jwts.set(key, jwt2);
122297
- return {
122298
- accessToken: json.accessToken,
122299
- casUrl: json.casUrl
122300
- };
122301
- })();
122302
- jwtPromises.set(key, promise);
122303
- return promise;
122304
122460
  }
122305
122461
 
122306
- // src/utils/WebBlob.ts
122307
- var WebBlob = class extends Blob {
122308
- static async create(url, opts) {
122309
- const customFetch = opts?.fetch ?? fetch;
122310
- const response = await customFetch(url, {
122311
- method: "HEAD",
122312
- ...opts?.accessToken && {
122313
- headers: {
122314
- Authorization: `Bearer ${opts.accessToken}`
122315
- }
122316
- }
122317
- });
122318
- const size = Number(response.headers.get("content-length"));
122319
- const contentType = response.headers.get("content-type") || "";
122320
- const supportRange = response.headers.get("accept-ranges") === "bytes";
122321
- if (!supportRange || size < (opts?.cacheBelow ?? 1e6)) {
122322
- return await (await customFetch(url)).blob();
122462
+ /**
122463
+ * Return true if the patterns provided contain any magic glob characters,
122464
+ * given the options provided.
122465
+ *
122466
+ * Brace expansion is not considered "magic" unless the `magicalBraces` option
122467
+ * is set, as brace expansion just turns one string into an array of strings.
122468
+ * So a pattern like `'x{a,b}y'` would return `false`, because `'xay'` and
122469
+ * `'xby'` both do not contain any magic glob characters, and it's treated the
122470
+ * same as if you had called it on `['xay', 'xby']`. When `magicalBraces:true`
122471
+ * is in the options, brace expansion _is_ treated as a pattern having magic.
122472
+ */
122473
+ const hasMagic = (pattern, options = {}) => {
122474
+ if (!Array.isArray(pattern)) {
122475
+ pattern = [pattern];
122323
122476
  }
122324
- return new WebBlob(url, 0, size, contentType, true, customFetch, opts?.accessToken);
122325
- }
122326
- url;
122327
- start;
122328
- end;
122329
- contentType;
122330
- full;
122331
- fetch;
122332
- accessToken;
122333
- constructor(url, start, end, contentType, full, customFetch, accessToken) {
122334
- super([]);
122335
- this.url = url;
122336
- this.start = start;
122337
- this.end = end;
122338
- this.contentType = contentType;
122339
- this.full = full;
122340
- this.fetch = customFetch;
122341
- this.accessToken = accessToken;
122342
- }
122343
- get size() {
122344
- return this.end - this.start;
122345
- }
122346
- get type() {
122347
- return this.contentType;
122348
- }
122349
- slice(start = 0, end = this.size) {
122350
- const slice = new WebBlob(
122351
- this.url,
122352
- this.start + start,
122353
- Math.min(this.start + end, this.end),
122354
- this.contentType,
122355
- start === 0 && end === this.size ? this.full : false,
122356
- this.fetch,
122357
- this.accessToken
122358
- );
122359
- return slice;
122360
- }
122361
- async arrayBuffer() {
122362
- const result = await this.fetchRange();
122363
- return result.arrayBuffer();
122364
- }
122365
- async text() {
122366
- const result = await this.fetchRange();
122367
- return result.text();
122368
- }
122369
- stream() {
122370
- const stream = new TransformStream();
122371
- this.fetchRange().then((response) => response.body?.pipeThrough(stream)).catch((error) => stream.writable.abort(error.message));
122372
- return stream.readable;
122373
- }
122374
- fetchRange() {
122375
- const fetch2 = this.fetch;
122376
- if (this.full) {
122377
- return fetch2(this.url, {
122378
- ...this.accessToken && {
122379
- headers: {
122380
- Authorization: `Bearer ${this.accessToken}`
122381
- }
122382
- }
122383
- }).then((resp) => resp.ok ? resp : createApiError(resp));
122477
+ for (const p of pattern) {
122478
+ if (new Minimatch(p, options).hasMagic())
122479
+ return true;
122384
122480
  }
122385
- return fetch2(this.url, {
122386
- headers: {
122387
- Range: `bytes=${this.start}-${this.end - 1}`,
122388
- ...this.accessToken && { Authorization: `Bearer ${this.accessToken}` }
122389
- }
122390
- }).then((resp) => resp.ok ? resp : createApiError(resp));
122391
- }
122481
+ return false;
122392
122482
  };
122393
122483
 
122394
- // src/utils/parseLinkHeader.ts
122395
- function parseLinkHeader(header) {
122396
- const regex = /<(https?:[/][/][^>]+)>;\s+rel="([^"]+)"/g;
122397
- return Object.fromEntries([...header.matchAll(regex)].map(([, url, rel]) => [rel, url]));
122484
+ function globStreamSync(pattern, options = {}) {
122485
+ return new Glob(pattern, options).streamSync();
122398
122486
  }
122487
+ function globStream(pattern, options = {}) {
122488
+ return new Glob(pattern, options).stream();
122489
+ }
122490
+ function globSync(pattern, options = {}) {
122491
+ return new Glob(pattern, options).walkSync();
122492
+ }
122493
+ async function glob_(pattern, options = {}) {
122494
+ return new Glob(pattern, options).walk();
122495
+ }
122496
+ function globIterateSync(pattern, options = {}) {
122497
+ return new Glob(pattern, options).iterateSync();
122498
+ }
122499
+ function globIterate(pattern, options = {}) {
122500
+ return new Glob(pattern, options).iterate();
122501
+ }
122502
+ // aliases: glob.sync.stream() glob.stream.sync() glob.sync() etc
122503
+ const streamSync = globStreamSync;
122504
+ const stream = Object.assign(globStream, { sync: globStreamSync });
122505
+ const iterateSync = globIterateSync;
122506
+ const iterate = Object.assign(globIterate, {
122507
+ sync: globIterateSync,
122508
+ });
122509
+ const sync = Object.assign(globSync, {
122510
+ stream: globStreamSync,
122511
+ iterate: globIterateSync,
122512
+ });
122513
+ const glob = Object.assign(glob_, {
122514
+ glob: glob_,
122515
+ globSync,
122516
+ sync,
122517
+ globStream,
122518
+ stream,
122519
+ globStreamSync,
122520
+ streamSync,
122521
+ globIterate,
122522
+ iterate,
122523
+ globIterateSync,
122524
+ iterateSync,
122525
+ Glob,
122526
+ hasMagic,
122527
+ escape: escape$1,
122528
+ unescape: unescape$1,
122529
+ });
122530
+ glob.glob = glob;
122399
122531
 
122400
- // src/lib/file-download-info.ts
122401
- async function fileDownloadInfo(params) {
122402
- const accessToken = checkCredentials(params);
122403
- const repoId = toRepoId(params.repo);
122404
- const hubUrl = params.hubUrl ?? HUB_URL;
122405
- const url = `${hubUrl}/${repoId.type === "model" ? "" : `${repoId.type}s/`}${repoId.name}/${params.raw ? "raw" : "resolve"}/${encodeURIComponent(params.revision ?? "main")}/${params.path}` + (params.noContentDisposition ? "?noContentDisposition=1" : "");
122406
- const resp = await (params.fetch ?? fetch)(url, {
122407
- method: "GET",
122408
- headers: {
122409
- ...accessToken && {
122410
- Authorization: `Bearer ${accessToken}`
122411
- },
122412
- Range: "bytes=0-0",
122413
- Accept: "application/vnd.xet-fileinfo+json, */*"
122532
+ function matchesQuantizationVariant({ filePath, variant }) {
122533
+ if (!variant) {
122534
+ return false;
122414
122535
  }
122415
- });
122416
- if (resp.status === 404 && resp.headers.get("X-Error-Code") === "EntryNotFound") {
122417
- return null;
122418
- }
122419
- if (!resp.ok) {
122420
- throw await createApiError(resp);
122421
- }
122422
- let size;
122423
- let xetInfo;
122424
- if (resp.headers.get("Content-Type")?.includes("application/vnd.xet-fileinfo+json")) {
122425
- size = parseInt(resp.headers.get("X-Linked-Size") ?? "invalid");
122426
- if (isNaN(size)) {
122427
- throw new InvalidApiResponseFormatError("Invalid file size received in X-Linked-Size header");
122536
+ const escapedVariant = variant.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
122537
+ const matcher = new RegExp(`(^|[\\-./_])${escapedVariant}(?=[\\-./]|$)`, "i");
122538
+ const normalizedPath = filePath.replace(/\\/g, "/");
122539
+ const segments = normalizedPath.split("/").filter(Boolean);
122540
+ if (segments.length === 0) {
122541
+ return false;
122428
122542
  }
122429
- const hash2 = resp.headers.get("X-Xet-Hash");
122430
- const links = parseLinkHeader(resp.headers.get("Link") ?? "");
122431
- const reconstructionUrl = (() => {
122432
- try {
122433
- return new URL(links["xet-reconstruction-info"]);
122434
- } catch {
122435
- return null;
122436
- }
122437
- })();
122438
- const refreshUrl = (() => {
122439
- try {
122440
- return new URL(links["xet-auth"]);
122441
- } catch {
122442
- return null;
122443
- }
122444
- })();
122445
- if (!hash2) {
122446
- throw new InvalidApiResponseFormatError("No hash received in X-Xet-Hash header");
122543
+ const filename = segments[segments.length - 1].replace(/\.gguf$/i, "");
122544
+ if (matcher.test(filename)) {
122545
+ return true;
122447
122546
  }
122448
- if (!reconstructionUrl || !refreshUrl) {
122449
- throw new InvalidApiResponseFormatError("No xet-reconstruction-info or xet-auth link header");
122547
+ return segments.slice(0, -1).some(segment => matcher.test(segment));
122548
+ }
122549
+ async function findQuantizedModelTarget({ model, path }) {
122550
+ if (model.source.type === "storage") {
122551
+ throw new Error("Model storage not supported yet");
122450
122552
  }
122451
- xetInfo = {
122452
- hash: hash2,
122453
- refreshUrl,
122454
- reconstructionUrl
122455
- };
122456
- }
122457
- if (size === void 0 || isNaN(size)) {
122458
- const contentRangeHeader = resp.headers.get("content-range");
122459
- if (!contentRangeHeader) {
122460
- throw new InvalidApiResponseFormatError("Expected size information");
122553
+ if (model.format !== "gguf") {
122554
+ throw new Error(`Model format not supported: ${model.format}`);
122461
122555
  }
122462
- const [, parsedSize] = contentRangeHeader.split("/");
122463
- size = parseInt(parsedSize);
122464
- if (isNaN(size)) {
122465
- throw new InvalidApiResponseFormatError("Invalid file size received");
122556
+ const [, variant = null] = model.source.slug.split(":");
122557
+ const modelFiles = (await glob("**/*.gguf", {
122558
+ absolute: true,
122559
+ cwd: path,
122560
+ nodir: true
122561
+ })).filter(file => !/(mmproj|clip)/i.test(file));
122562
+ if (modelFiles.length <= 0) {
122563
+ throw new Error(`No models found for format: ${model.format}`);
122466
122564
  }
122467
- }
122468
- const etag = resp.headers.get("X-Linked-ETag") ?? resp.headers.get("ETag") ?? void 0;
122469
- if (!etag) {
122470
- throw new InvalidApiResponseFormatError("Expected ETag");
122471
- }
122472
- return {
122473
- etag,
122474
- size,
122475
- xet: xetInfo,
122476
- // Cannot use resp.url in case it's a S3 url and the user adds an Authorization header to it.
122477
- url: resp.url && (new URL(resp.url).origin === new URL(hubUrl).origin || resp.headers.get("X-Cache")?.endsWith(" cloudfront")) ? resp.url : url
122478
- };
122479
- }
122480
-
122481
- // src/lib/download-file.ts
122482
- async function downloadFile(params) {
122483
- const accessToken = checkCredentials(params);
122484
- const info = params.downloadInfo ?? await fileDownloadInfo({
122485
- accessToken,
122486
- repo: params.repo,
122487
- path: params.path,
122488
- revision: params.revision,
122489
- hubUrl: params.hubUrl,
122490
- fetch: params.fetch,
122491
- raw: params.raw
122492
- });
122493
- if (!info) {
122494
- return null;
122495
- }
122496
- if (info.xet && params.xet) {
122497
- return new XetBlob({
122498
- refreshUrl: info.xet.refreshUrl.href,
122499
- reconstructionUrl: info.xet.reconstructionUrl.href,
122500
- fetch: params.fetch,
122501
- accessToken,
122502
- size: info.size
122503
- });
122504
- }
122505
- return new WebBlob(new URL(info.url), 0, info.size, "", true, params.fetch ?? fetch, accessToken);
122565
+ modelFiles.sort((left, right) => left.localeCompare(right, undefined, { sensitivity: "base" }));
122566
+ if (!variant) {
122567
+ return modelFiles[0];
122568
+ }
122569
+ const matches = modelFiles.filter(fileName => matchesQuantizationVariant({ filePath: fileName, variant: variant ?? "" }));
122570
+ if (matches.length === 0) {
122571
+ throw new Error(`No model found for format and variant: ${model.format} / ${variant}`);
122572
+ }
122573
+ return matches[0];
122506
122574
  }
122507
122575
 
122508
- // src/lib/list-files.ts
122509
- async function* listFiles(params) {
122510
- const accessToken = checkCredentials(params);
122511
- const repoId = toRepoId(params.repo);
122512
- let url = `${params.hubUrl || HUB_URL}/api/${repoId.type}s/${repoId.name}/tree/${params.revision || "main"}${params.path ? "/" + params.path : ""}?recursive=${!!params.recursive}&expand=${!!params.expand}`;
122513
- while (url) {
122514
- const res = await (params.fetch ?? fetch)(url, {
122515
- headers: {
122516
- accept: "application/json",
122517
- ...accessToken ? { Authorization: `Bearer ${accessToken}` } : void 0
122518
- }
122519
- });
122520
- if (!res.ok) {
122521
- throw await createApiError(res);
122576
+ const VLLM_START_ARGS = ["-m", "vllm.entrypoints.openai.api_server", "--host", "0.0.0.0"];
122577
+ const VLLM_EXECUTABLE = "python3";
122578
+ const DEFAULT_VLLM_CONTEXT_LENGTH = 2048;
122579
+ async function startVLLM({ enginePort, targetDirectory }) {
122580
+ const contextLength = Math.max(1, this.contextLength ?? DEFAULT_VLLM_CONTEXT_LENGTH);
122581
+ let modelPath = targetDirectory;
122582
+ if (this.model.format === "gguf") {
122583
+ modelPath = await findQuantizedModelTarget({ model: this.model, path: targetDirectory });
122522
122584
  }
122523
- const items = await res.json();
122524
- for (const item of items) {
122525
- yield item;
122585
+ const engineConfig = this.engineConfig;
122586
+ const device = process.env.VLLM_DEVICE;
122587
+ const dtype = process.env.VLLM_DTYPE;
122588
+ const args = [
122589
+ ...VLLM_START_ARGS,
122590
+ "--port",
122591
+ String(enginePort),
122592
+ "--model",
122593
+ modelPath,
122594
+ "--served-model-name",
122595
+ SERVED_MODEL_NAME,
122596
+ "--max-model-len",
122597
+ String(contextLength)
122598
+ ];
122599
+ if (this.model.taskType === "embeddings") {
122600
+ args.push("--task", "embed");
122526
122601
  }
122527
- const linkHeader = res.headers.get("Link");
122528
- url = linkHeader ? parseLinkHeader(linkHeader).next : void 0;
122529
- }
122602
+ args.push(...(await getChatTemplateEngineArgs({
122603
+ engine: this.engine,
122604
+ model: this.model,
122605
+ targetDirectory
122606
+ })));
122607
+ if (device) {
122608
+ args.push("--device", device);
122609
+ }
122610
+ if (dtype) {
122611
+ args.push("--dtype", dtype);
122612
+ }
122613
+ args.push(...parseExtraArgs(engineConfig?.extraArgs));
122614
+ if (this.model.multimodalEnabled) {
122615
+ args.push("--limit-mm-per-prompt", process.env.VLLM_MM_LIMIT ?? '{"image":5}');
122616
+ }
122617
+ if (process.env.VLLM_TRUST_REMOTE_CODE === "true") {
122618
+ args.push("--trust-remote-code");
122619
+ }
122620
+ return createEngineProcess({ args, bin: VLLM_EXECUTABLE, logger: this.logger });
122530
122621
  }
122531
122622
 
122532
122623
  const ModelDownloadProgressSchema = object$1({
@@ -123073,9 +123164,6 @@ const DEFAULT_EXLLAMAV3_CONTEXT_LENGTH = 4096;
123073
123164
  async function startExllamav3({ enginePort, targetDirectory }) {
123074
123165
  const contextLength = Math.max(1, this.contextLength ?? DEFAULT_EXLLAMAV3_CONTEXT_LENGTH);
123075
123166
  const engineConfig = this.engineConfig;
123076
- const cacheMode = typeof engineConfig?.cacheMode === "string" ? engineConfig.cacheMode : "q4";
123077
- const gpuSplit = typeof engineConfig?.gpuSplit === "string" ? engineConfig.gpuSplit : null;
123078
- const maxSeqLen = typeof engineConfig?.maxSeqLen === "number" ? engineConfig.maxSeqLen : contextLength;
123079
123167
  const args = [
123080
123168
  SERVER_SCRIPT,
123081
123169
  "--model",
@@ -123084,20 +123172,15 @@ async function startExllamav3({ enginePort, targetDirectory }) {
123084
123172
  "127.0.0.1",
123085
123173
  "--port",
123086
123174
  String(enginePort),
123087
- "--cache-mode",
123088
- cacheMode,
123089
123175
  "--max-seq-len",
123090
- String(maxSeqLen)
123176
+ String(contextLength)
123091
123177
  ];
123092
- if (gpuSplit) {
123093
- args.push("--gpu-split", gpuSplit);
123094
- }
123095
123178
  args.push(...parseExtraArgs(engineConfig?.extraArgs));
123096
123179
  return createEngineProcess({ args, bin: EXLLAMAV3_EXECUTABLE, logger: this.logger });
123097
123180
  }
123098
123181
 
123099
123182
  const DEFAULT_LLAMACPP_GPU_LAYERS = 999;
123100
- const LLAMACPP_START_ARGS = ["--host", "0.0.0.0", "--jinja"];
123183
+ const LLAMACPP_START_ARGS = ["--host", "0.0.0.0", "--jinja", "--flash-attn", "on"];
123101
123184
  const LLAMACPP_EXECUTABLE = process.env.LLAMACPP_EXECUTABLE ?? "llama-server";
123102
123185
  const DEFAULT_LLAMACPP_CONTEXT_LENGTH = 131072;
123103
123186
  async function findMultimodalProjector({ path }) {
@@ -123119,7 +123202,6 @@ async function startLlamacpp({ enginePort, targetDirectory }) {
123119
123202
  const target = await findQuantizedModelTarget({ model: this.model, path: targetDirectory });
123120
123203
  const contextLength = Math.max(1, this.contextLength ?? DEFAULT_LLAMACPP_CONTEXT_LENGTH);
123121
123204
  const engineConfig = this.engineConfig;
123122
- const parallelism = typeof engineConfig?.parallelism === "number" ? engineConfig.parallelism : null;
123123
123205
  const args = [
123124
123206
  ...LLAMACPP_START_ARGS,
123125
123207
  "--port",
@@ -123129,46 +123211,18 @@ async function startLlamacpp({ enginePort, targetDirectory }) {
123129
123211
  "--ctx-size",
123130
123212
  String(contextLength)
123131
123213
  ];
123214
+ args.push(...(await getChatTemplateEngineArgs({
123215
+ engine: this.engine,
123216
+ model: this.model,
123217
+ targetDirectory
123218
+ })));
123132
123219
  if (this.model.taskType === "embeddings") {
123133
123220
  args.push("--embedding");
123134
123221
  }
123135
- const gpuLayers = typeof engineConfig?.gpuLayers === "number"
123136
- ? engineConfig.gpuLayers
123137
- : Number.parseInt(process.env.LLAMACPP_GPU_LAYERS ?? String(DEFAULT_LLAMACPP_GPU_LAYERS), 10);
123222
+ const gpuLayers = Number.parseInt(process.env.LLAMACPP_GPU_LAYERS ?? String(DEFAULT_LLAMACPP_GPU_LAYERS), 10);
123138
123223
  if (Number.isFinite(gpuLayers) && gpuLayers > 0) {
123139
123224
  args.push("--n-gpu-layers", String(gpuLayers));
123140
123225
  }
123141
- if (typeof parallelism === "number") {
123142
- args.push("--parallel", String(Math.max(1, parallelism)));
123143
- }
123144
- const flashAttn = engineConfig?.flashAttn;
123145
- if (flashAttn === true || flashAttn === undefined) {
123146
- args.push("--flash-attn", "on");
123147
- }
123148
- const cacheTypeK = typeof engineConfig?.cacheTypeK === "string" ? engineConfig.cacheTypeK : null;
123149
- if (cacheTypeK) {
123150
- args.push("--cache-type-k", cacheTypeK);
123151
- }
123152
- const cacheTypeV = typeof engineConfig?.cacheTypeV === "string" ? engineConfig.cacheTypeV : null;
123153
- if (cacheTypeV) {
123154
- args.push("--cache-type-v", cacheTypeV);
123155
- }
123156
- const batchSize = typeof engineConfig?.batchSize === "number" ? engineConfig.batchSize : null;
123157
- if (batchSize !== null) {
123158
- args.push("--batch-size", String(batchSize));
123159
- }
123160
- const ubatchSize = typeof engineConfig?.ubatchSize === "number" ? engineConfig.ubatchSize : null;
123161
- if (ubatchSize !== null) {
123162
- args.push("--ubatch-size", String(ubatchSize));
123163
- }
123164
- const tensorSplit = typeof engineConfig?.tensorSplit === "string" ? engineConfig.tensorSplit : null;
123165
- if (tensorSplit) {
123166
- args.push("--tensor-split", tensorSplit);
123167
- }
123168
- const mainGpu = typeof engineConfig?.mainGpu === "number" ? engineConfig.mainGpu : null;
123169
- if (mainGpu !== null) {
123170
- args.push("--main-gpu", String(mainGpu));
123171
- }
123172
123226
  args.push(...parseExtraArgs(engineConfig?.extraArgs));
123173
123227
  if (this.model.multimodalEnabled) {
123174
123228
  const projector = await findMultimodalProjector({ path: targetDirectory });
@@ -123207,12 +123261,7 @@ async function startMLXLM({ enginePort, targetDirectory }) {
123207
123261
  "--context-length",
123208
123262
  String(contextLength)
123209
123263
  ];
123210
- const maxKvSize = typeof engineConfig?.maxKvSize === "number" ? engineConfig.maxKvSize : null;
123211
- if (maxKvSize !== null) {
123212
- args.push("--max-kv-size", String(maxKvSize));
123213
- }
123214
- const trustRemoteCode = engineConfig?.trustRemoteCode === true;
123215
- if (trustRemoteCode || process.env.MLXLM_TRUST_REMOTE_CODE === "true") {
123264
+ if (process.env.MLXLM_TRUST_REMOTE_CODE === "true") {
123216
123265
  args.push("--trust-remote-code");
123217
123266
  }
123218
123267
  args.push(...parseExtraArgs(engineConfig?.extraArgs));
@@ -123249,9 +123298,6 @@ const DEFAULT_SGLANG_CONTEXT_LENGTH = 2048;
123249
123298
  async function startSGLang({ enginePort, targetDirectory }) {
123250
123299
  const contextLength = Math.max(1, this.contextLength ?? DEFAULT_SGLANG_CONTEXT_LENGTH);
123251
123300
  const engineConfig = this.engineConfig;
123252
- const device = typeof engineConfig?.device === "string" ? engineConfig.device : undefined;
123253
- const dtype = typeof engineConfig?.dtype === "string" ? engineConfig.dtype : undefined;
123254
- const tensorParallelSize = typeof engineConfig?.tensorParallelSize === "number" ? engineConfig.tensorParallelSize : 1;
123255
123301
  const args = [
123256
123302
  ...SGLANG_START_ARGS,
123257
123303
  "--port",
@@ -123261,19 +123307,16 @@ async function startSGLang({ enginePort, targetDirectory }) {
123261
123307
  "--served-model-name",
123262
123308
  SERVED_MODEL_NAME,
123263
123309
  "--context-length",
123264
- String(contextLength),
123265
- "--tp-size",
123266
- String(tensorParallelSize)
123310
+ String(contextLength)
123267
123311
  ];
123268
123312
  if (this.model.taskType === "embeddings") {
123269
123313
  args.push("--task", "embed");
123270
123314
  }
123271
- if (device) {
123272
- args.push("--device", device);
123273
- }
123274
- if (dtype) {
123275
- args.push("--dtype", dtype);
123276
- }
123315
+ args.push(...(await getChatTemplateEngineArgs({
123316
+ engine: this.engine,
123317
+ model: this.model,
123318
+ targetDirectory
123319
+ })));
123277
123320
  args.push(...parseExtraArgs(engineConfig?.extraArgs));
123278
123321
  if (this.model.multimodalEnabled) {
123279
123322
  args.push("--limit-mm-per-prompt", process.env.SGLANG_MM_LIMIT ?? '{"image":5}');
@@ -123289,9 +123332,6 @@ const DEFAULT_TRTLLM_CONTEXT_LENGTH = 2048;
123289
123332
  async function startTensorRTLLM({ enginePort, targetDirectory }) {
123290
123333
  const contextLength = Math.max(1, this.contextLength ?? DEFAULT_TRTLLM_CONTEXT_LENGTH);
123291
123334
  const engineConfig = this.engineConfig;
123292
- const backend = typeof engineConfig?.backend === "string" ? engineConfig.backend : "pytorch";
123293
- const dtype = typeof engineConfig?.dtype === "string" ? engineConfig.dtype : undefined;
123294
- const tensorParallelSize = typeof engineConfig?.tensorParallelSize === "number" ? engineConfig.tensorParallelSize : 1;
123295
123335
  const args = [
123296
123336
  "serve",
123297
123337
  targetDirectory,
@@ -123299,19 +123339,12 @@ async function startTensorRTLLM({ enginePort, targetDirectory }) {
123299
123339
  "127.0.0.1",
123300
123340
  "--port",
123301
123341
  String(enginePort),
123302
- "--backend",
123303
- backend,
123304
123342
  "--max-seq-len",
123305
- String(contextLength),
123306
- "--tp-size",
123307
- String(tensorParallelSize)
123343
+ String(contextLength)
123308
123344
  ];
123309
123345
  if (this.model.taskType === "embeddings") {
123310
123346
  args.push("--task", "embed");
123311
123347
  }
123312
- if (dtype) {
123313
- args.push("--dtype", dtype);
123314
- }
123315
123348
  args.push(...parseExtraArgs(engineConfig?.extraArgs));
123316
123349
  return createEngineProcess({ args, bin: TRTLLM_EXECUTABLE, logger: this.logger });
123317
123350
  }
@@ -123348,6 +123381,15 @@ class ModelManager extends EventEmitter {
123348
123381
  this.uniqueName = createModelStorageKey(this.model);
123349
123382
  this.modelsDirectory = path$1.join(root, "models");
123350
123383
  }
123384
+ async verifyChatTemplate() {
123385
+ return verifyEngineChatTemplate({
123386
+ engine: this.engine,
123387
+ enginePort: this.enginePort,
123388
+ logger: this.logger,
123389
+ model: this.model,
123390
+ targetDirectory: path$1.join(this.modelsDirectory, this.uniqueName)
123391
+ });
123392
+ }
123351
123393
  async fetchOpenAI(path, opts) {
123352
123394
  switch (this.engine) {
123353
123395
  case "exllamav3":
@@ -123425,6 +123467,12 @@ class ModelManager extends EventEmitter {
123425
123467
  finally {
123426
123468
  await this.releaseDownloadLock();
123427
123469
  }
123470
+ await materializeChatTemplate({
123471
+ engine: this.engine,
123472
+ huggingFaceToken: this.model.source.modelSecret,
123473
+ model: this.model,
123474
+ targetDirectory: path$1.join(this.modelsDirectory, this.uniqueName)
123475
+ });
123428
123476
  break;
123429
123477
  default: {
123430
123478
  const engineType = this.engine;
@@ -124408,7 +124456,50 @@ function stripImagesFromBody(body) {
124408
124456
  function isPlainObject$3(value) {
124409
124457
  return typeof value === "object" && value !== null && !Array.isArray(value);
124410
124458
  }
124411
- function serializeRequestBody$1(body) {
124459
+ /**
124460
+ * Builds `chat_template_kwargs` for engines that read template variables at
124461
+ * render time. Only active when the model carries a template override or
124462
+ * thinking config; otherwise the body forwards untouched (engines like vLLM
124463
+ * consume top-level `reasoning_effort` natively for supported models).
124464
+ *
124465
+ * Precedence (highest wins):
124466
+ * 1. Request `chat_template_kwargs` (per key)
124467
+ * 2. Request top-level `reasoning_effort`
124468
+ * 3. Model thinking config defaults
124469
+ */
124470
+ function applyChatTemplateKwargs({ body, model }) {
124471
+ const hasTemplateOverride = Boolean(model.chatTemplate);
124472
+ const thinkingConfig = model.thinkingConfig ?? null;
124473
+ if (!hasTemplateOverride && !thinkingConfig)
124474
+ return body;
124475
+ const requestKwargs = isPlainObject$3(body.chat_template_kwargs)
124476
+ ? body.chat_template_kwargs
124477
+ : null;
124478
+ const requestEffort = typeof body.reasoning_effort === "string" ? body.reasoning_effort : null;
124479
+ const mergedKwargs = {};
124480
+ if (thinkingConfig?.enabled === false) {
124481
+ mergedKwargs.enable_thinking = false;
124482
+ }
124483
+ if (thinkingConfig?.effort) {
124484
+ mergedKwargs.reasoning_effort = thinkingConfig.effort;
124485
+ }
124486
+ if (requestKwargs) {
124487
+ Object.assign(mergedKwargs, requestKwargs);
124488
+ }
124489
+ const hasRequestReasoningEffort = requestKwargs !== null && "reasoning_effort" in requestKwargs;
124490
+ if (requestEffort && !hasRequestReasoningEffort) {
124491
+ mergedKwargs.reasoning_effort = requestEffort;
124492
+ }
124493
+ const payload = { ...body };
124494
+ if (Object.keys(mergedKwargs).length > 0) {
124495
+ payload.chat_template_kwargs = mergedKwargs;
124496
+ }
124497
+ if (requestEffort !== null) {
124498
+ delete payload.reasoning_effort;
124499
+ }
124500
+ return payload;
124501
+ }
124502
+ function serializeRequestBody$1(body, { model, path } = {}) {
124412
124503
  if (!isPlainObject$3(body)) {
124413
124504
  const payload = typeof body === "string" ? body : JSON.stringify(body);
124414
124505
  return {
@@ -124416,7 +124507,10 @@ function serializeRequestBody$1(body) {
124416
124507
  payload
124417
124508
  };
124418
124509
  }
124419
- const requestPayload = { ...body };
124510
+ let requestPayload = { ...body };
124511
+ if (path === "/v1/chat/completions" && model) {
124512
+ requestPayload = applyChatTemplateKwargs({ body: requestPayload, model });
124513
+ }
124420
124514
  if (requestPayload.stream === true) {
124421
124515
  const streamOptions = requestPayload.stream_options;
124422
124516
  const normalizedStreamOptions = isPlainObject$3(streamOptions)
@@ -124469,7 +124563,7 @@ async function proxyEmbeddingsRoute({ body, conduitConfiguration, endpointId, lo
124469
124563
  });
124470
124564
  }
124471
124565
  const engineType = conduitConfiguration.engineConfig?.type ?? null;
124472
- const engineConfig = conduitConfiguration.engineConfig?.config ?? null;
124566
+ const engineConfig = conduitConfiguration.engineConfig ?? null;
124473
124567
  const serializedBody = isPlainObject$3(body)
124474
124568
  ? JSON.stringify(body)
124475
124569
  : typeof body === "string"
@@ -124613,9 +124707,9 @@ async function proxyOpenAIStreamingRoute({ body, conduitConfiguration, endpointI
124613
124707
  });
124614
124708
  }
124615
124709
  const engineType = conduitConfiguration.engineConfig?.type ?? null;
124616
- const engineConfig = conduitConfiguration.engineConfig?.config ?? null;
124710
+ const engineConfig = conduitConfiguration.engineConfig ?? null;
124617
124711
  const effectiveBody = modelManager.model.multimodalEnabled ? body : stripImagesFromBody(body);
124618
- const { bytes: requestBodyBytes, payload: serializedBody } = serializeRequestBody$1(effectiveBody);
124712
+ const { bytes: requestBodyBytes, payload: serializedBody } = serializeRequestBody$1(effectiveBody, { model: modelManager.model, path });
124619
124713
  const requestStartedAt = Date.now();
124620
124714
  const requestBody = JSON.parse(serializedBody);
124621
124715
  const streamRequested = requestBody.stream === true;
@@ -124862,7 +124956,7 @@ function createConduitOpenAIAPIReferenceHandlers({ apiClient, conduitConfigurati
124862
124956
  const currentConfig = conduitConfiguration();
124863
124957
  const effectiveContextLength = getEffectiveContextLength({
124864
124958
  contextLength: modelManager.contextLength,
124865
- engineConfig: currentConfig.engineConfig?.config ?? null,
124959
+ engineConfig: currentConfig.engineConfig ?? null,
124866
124960
  engineType: currentConfig.engineConfig?.type ?? null
124867
124961
  });
124868
124962
  return {
@@ -125001,6 +125095,17 @@ function translateAnthropicRequestToOpenAI(body) {
125001
125095
  result.top_p = parsed.top_p;
125002
125096
  if (Array.isArray(parsed.stop_sequences))
125003
125097
  result.stop = parsed.stop_sequences;
125098
+ if (parsed.thinking && typeof parsed.thinking === "object") {
125099
+ const thinking = parsed.thinking;
125100
+ if (thinking.type === "enabled") {
125101
+ const budgetTokens = typeof thinking.budget_tokens === "number" ? thinking.budget_tokens : null;
125102
+ result.chat_template_kwargs = {
125103
+ reasoning_effort: budgetTokens
125104
+ ? reasoningEffortForAnthropicBudget(budgetTokens)
125105
+ : "high"
125106
+ };
125107
+ }
125108
+ }
125004
125109
  if (Array.isArray(parsed.tools)) {
125005
125110
  result.tools = parsed.tools.map((tool) => {
125006
125111
  const t = tool;
@@ -125272,11 +125377,13 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125272
125377
  const requestStartedAt = Date.now();
125273
125378
  const requestBody = JSON.parse(serializedBody);
125274
125379
  const streamRequested = requestBody.stream === true;
125275
- const targetPath = needsTranslation
125276
- ? translateAnthropicRequestToOpenAI(serializedBody).path
125277
- : "/v1/messages";
125278
- const targetBody = needsTranslation
125279
- ? translateAnthropicRequestToOpenAI(serializedBody).body
125380
+ const translated = needsTranslation ? translateAnthropicRequestToOpenAI(serializedBody) : null;
125381
+ const targetPath = translated?.path ?? "/v1/messages";
125382
+ const targetBody = translated
125383
+ ? JSON.stringify(applyChatTemplateKwargs({
125384
+ body: JSON.parse(translated.body),
125385
+ model: modelManager.model
125386
+ }))
125280
125387
  : serializedBody;
125281
125388
  const onMonitoringComplete = ({ durationMs, error, responseBytes, timeToFirstTokenMs, usage }) => {
125282
125389
  const promptTokens = normalizeTokenCount(usage?.inputTokens);
@@ -156174,13 +156281,14 @@ async function createApplication({ abortController, apiClient, configuration, lo
156174
156281
  });
156175
156282
  conduitStateReportManager.reportStateChange();
156176
156283
  };
156177
- const setOnlineState = () => {
156178
- if (conduitStateManager.getState().state === "online") {
156284
+ const setOnlineState = ({ warnings } = {}) => {
156285
+ if (conduitStateManager.getState().state === "online" && warnings === undefined) {
156179
156286
  return;
156180
156287
  }
156181
156288
  conduitStateManager.setState({
156182
156289
  modelName,
156183
- state: "online"
156290
+ state: "online",
156291
+ ...(warnings !== undefined ? { warnings } : {})
156184
156292
  });
156185
156293
  conduitStateReportManager.reportStateChange();
156186
156294
  };
@@ -156202,6 +156310,23 @@ async function createApplication({ abortController, apiClient, configuration, lo
156202
156310
  });
156203
156311
  modelManager.on("engineReady", () => {
156204
156312
  setOnlineState();
156313
+ const readyModelManager = modelManager;
156314
+ readyModelManager
156315
+ .verifyChatTemplate()
156316
+ .then(warning => {
156317
+ if (modelManager !== readyModelManager) {
156318
+ return;
156319
+ }
156320
+ if (warning) {
156321
+ logger.warn("Chat template verification", { warning });
156322
+ setOnlineState({ warnings: [warning] });
156323
+ }
156324
+ })
156325
+ .catch(error => {
156326
+ logger.warn("Chat template verification failed", {
156327
+ error: asError(error)
156328
+ });
156329
+ });
156205
156330
  });
156206
156331
  modelManager.on("engineTerminated", () => {
156207
156332
  if (stopRequestedByControl) {
@@ -156513,7 +156638,9 @@ function createModelManagerFromConfig(conduitConfiguration, configuration, logge
156513
156638
  const engineConfig = conduitConfiguration.engineConfig;
156514
156639
  return new ModelManager({
156515
156640
  contextLength: conduitConfiguration.contextLength ?? null,
156516
- engineConfig: engineConfig?.config ?? null,
156641
+ engineConfig: engineConfig
156642
+ ? { extraArgs: engineConfig.extraArgs, type: engineConfig.type }
156643
+ : null,
156517
156644
  enginePort: configuration.enginePort,
156518
156645
  engineType: engineConfig?.type ?? "llama.cpp",
156519
156646
  logger,