leehack commited on
Commit
2d85b33
·
verified ·
1 Parent(s): ae7b55e

chore: deploy chat app 838143e

Browse files
flutter_bootstrap.js CHANGED
@@ -42,6 +42,6 @@ _flutter.buildConfig = {"engineRevision":"5d531788691ec3404cac0cee66ead4007b1773
42
 
43
  _flutter.loader.load({
44
  serviceWorkerSettings: {
45
- serviceWorkerVersion: "2510919536" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
46
  }
47
  });
 
42
 
43
  _flutter.loader.load({
44
  serviceWorkerSettings: {
45
+ serviceWorkerVersion: "1025218781" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
46
  }
47
  });
index.html CHANGED
@@ -211,7 +211,7 @@
211
  typeof configuredRepo === 'string' && configuredRepo.length > 0
212
  ? configuredRepo
213
  : 'leehack/llama-web-bridge-assets';
214
- const defaultBridgeAssetsTag = 'v0.1.44';
215
  const defaultBridgeLlamaCppTag = 'v0.4.1';
216
  const bridgeAssetsTag =
217
  typeof configuredTag === 'string' && configuredTag.length > 0
 
211
  typeof configuredRepo === 'string' && configuredRepo.length > 0
212
  ? configuredRepo
213
  : 'leehack/llama-web-bridge-assets';
214
+ const defaultBridgeAssetsTag = 'v0.1.47';
215
  const defaultBridgeLlamaCppTag = 'v0.4.1';
216
  const bridgeAssetsTag =
217
  typeof configuredTag === 'string' && configuredTag.length > 0
llamadart-build.json CHANGED
@@ -1 +1 @@
1
- {"commit":"03bca335fe499104a6067ec3515ac06208d048a1","tree":"18f9680b97ee5110cab6e4c9db133c0ae77e1493","base_href":"/","target":"lib/main.dart","flutter_version":"3.47.1"}
 
1
+ {"commit":"838143e3eb8160cd03ce8cf2758a99e03c249ffc","tree":"b07164124f1115bcae6de9ba399f5fef1577ece4","base_href":"/","target":"lib/main.dart","flutter_version":"3.47.1"}
main.dart.js CHANGED
The diff for this file is too large to render. See raw diff
 
webgpu_bridge/llama_webgpu_bridge.d.ts CHANGED
@@ -143,6 +143,48 @@ export interface TextToSpeechResult {
143
  truncated: boolean;
144
  }
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  export type ModelMetadata = Record<string, unknown>;
147
 
148
  export interface StateLoadResult {
@@ -189,6 +231,13 @@ export class LlamaWebGpuBridge {
189
  supportsAudio(): boolean;
190
  getTextToSpeechCapabilities(): Promise<TextToSpeechCapabilities>;
191
  synthesizeSpeech(options: TextToSpeechOptions): Promise<TextToSpeechResult>;
 
 
 
 
 
 
 
192
 
193
  getModelMetadata(): ModelMetadata | null;
194
  getContextSize(): number;
 
143
  truncated: boolean;
144
  }
145
 
146
+ export interface DecisionCapabilities {
147
+ apiVersion: number;
148
+ supported: boolean;
149
+ /** Why the loaded model cannot run decision heads; absent when supported. */
150
+ reason?: string;
151
+ }
152
+
153
+ export interface DecisionHeadOptions {
154
+ /** Laya `rl_agent_config.json` text; omit to read the head's `laya.config` metadata. */
155
+ configJson?: string | null;
156
+ /** Download progress of a URL head, in bytes. */
157
+ onProgress?: (progress: { loaded: number; total: number }) => void;
158
+ }
159
+
160
+ export interface DecisionHeadInfo {
161
+ apiVersion: number;
162
+ handle: number;
163
+ hiddenSize: number;
164
+ clsToken: number;
165
+ sepToken: number;
166
+ maskToken: number;
167
+ maskText: string;
168
+ configJson: string;
169
+ deviceName: string;
170
+ }
171
+
172
+ /** 0 = choice, 1 = score, 2 = noul. */
173
+ export type DecisionQuestionType = 0 | 1 | 2;
174
+
175
+ export interface DecisionSequence {
176
+ tokens: Int32Array | readonly number[];
177
+ /** Token indexes of the option markers, in option order. */
178
+ markers: Int32Array | readonly number[];
179
+ questionType: DecisionQuestionType;
180
+ }
181
+
182
+ export interface DecisionOutput {
183
+ /** One raw logit per marker. */
184
+ logits: Float32Array;
185
+ actLogits: Float32Array;
186
+ }
187
+
188
  export type ModelMetadata = Record<string, unknown>;
189
 
190
  export interface StateLoadResult {
 
231
  supportsAudio(): boolean;
232
  getTextToSpeechCapabilities(): Promise<TextToSpeechCapabilities>;
233
  synthesizeSpeech(options: TextToSpeechOptions): Promise<TextToSpeechResult>;
234
+ getDecisionCapabilities(): Promise<DecisionCapabilities>;
235
+ loadDecisionHead(
236
+ source: string | ArrayBuffer | ArrayBufferView,
237
+ options?: DecisionHeadOptions,
238
+ ): Promise<DecisionHeadInfo>;
239
+ runDecision(handle: number, sequences: readonly DecisionSequence[]): Promise<DecisionOutput[]>;
240
+ freeDecisionHead(handle: number): Promise<void>;
241
 
242
  getModelMetadata(): ModelMetadata | null;
243
  getContextSize(): number;
webgpu_bridge/llama_webgpu_bridge.js CHANGED
@@ -8,6 +8,8 @@ var defaultModelCacheName = "llamadart-webgpu-model-cache-v1";
8
  var BRIDGE_DISPOSED_MESSAGE = "Bridge has been disposed.";
9
  var GENERATION_ALREADY_ACTIVE_RC = -7;
10
  var GENERATION_ALREADY_ACTIVE_MESSAGE = "Generation is already active on this bridge runtime.";
 
 
11
  function createAbortError(message) {
12
  if (typeof DOMException === "function") {
13
  return new DOMException(message, "AbortError");
@@ -332,8 +334,7 @@ async function writeResponseToFsFileWithProgress(response, fs, filePath, progres
332
  const useBigIntPosition = writeOptions.useBigIntPosition === true;
333
  const startOffset = parsePositiveInteger(writeOptions.startOffset);
334
  const preservePartialOnError = writeOptions.preservePartialOnError === true;
335
- const allowAppend = writeOptions.allowAppend === true || startOffset > 0;
336
- const appendMode = allowAppend && startOffset > 0;
337
  const chunkTimeoutMs = parsePositiveInteger(writeOptions.chunkTimeoutMs);
338
  const signal = writeOptions.signal || null;
339
  const abortMessage = writeOptions.abortMessage || "Model transfer was cancelled.";
@@ -503,6 +504,120 @@ function toFloat32Array(value) {
503
  }
504
  return null;
505
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
506
  async function decodeImageBytesToRgb(bytes, options = {}) {
507
  const sourceBytes = toUint8Array(bytes);
508
  if (!sourceBytes || sourceBytes.length === 0) {
@@ -602,6 +717,37 @@ async function decodeImageBytesToRgb(bytes, options = {}) {
602
  }
603
  }
604
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
605
  function serializeWorkerError(error) {
606
  if (!error) {
607
  return "Unknown worker error";
@@ -861,6 +1007,29 @@ function installBridgeWorkerHost() {
861
  );
862
  return;
863
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
864
  if (method === "unloadMultimodalProjector") {
865
  const value2 = await bridge.unloadMultimodalProjector();
866
  self.postMessage({ type: "result", id, value: value2, state: snapshotBridgeState(bridge) });
@@ -1059,7 +1228,7 @@ var BridgeWorkerProxy = class {
1059
  async call(method, args, onEvent, transferList = [], operationMeta = null) {
1060
  await this._ready;
1061
  const id = this._nextId++;
1062
- const timeoutMs = this._resolveRequestTimeoutMs(method);
1063
  const transfers = Array.isArray(transferList) ? transferList.filter((item) => item != null) : [];
1064
  return new Promise((resolve, reject) => {
1065
  let timeoutHandle = null;
@@ -1127,7 +1296,7 @@ var BridgeWorkerProxy = class {
1127
  }
1128
  }, timeoutMs);
1129
  }
1130
- _resolveRequestTimeoutMs(method) {
1131
  const explicitGlobal = Number(this._config.workerRequestTimeoutMs);
1132
  const clamp = (value, fallback) => {
1133
  if (!Number.isFinite(value) || value <= 0) {
@@ -1147,6 +1316,13 @@ var BridgeWorkerProxy = class {
1147
  if (method === "synthesizeSpeech") {
1148
  return clamp(Number(this._config.workerTextToSpeechTimeoutMs), clamp(explicitGlobal, 20 * 60 * 1e3));
1149
  }
 
 
 
 
 
 
 
1150
  return clamp(explicitGlobal, 12e4);
1151
  }
1152
  async dispose() {
@@ -1191,6 +1367,7 @@ var LlamaWebGpuBridgeRuntime = class {
1191
  this._mmSupportsAudio = false;
1192
  this._mediaFileCounter = 0;
1193
  this._stateFileCounter = 0;
 
1194
  this._stagedMediaPaths = [];
1195
  this._nCtx = 4096;
1196
  this._abortRequested = false;
@@ -1485,49 +1662,18 @@ var LlamaWebGpuBridgeRuntime = class {
1485
  return () => {
1486
  };
1487
  }
1488
- _logLevelForName(level) {
1489
- switch (level) {
1490
- case "debug":
1491
- return 0;
1492
- case "log":
1493
- case "info":
1494
- return 1;
1495
- case "warn":
1496
- return 2;
1497
- case "error":
1498
- return 3;
1499
- default:
1500
- return 1;
1501
- }
1502
- }
1503
- _logThresholdForConfiguredLevel(level) {
1504
- switch (level) {
1505
- case 0:
1506
- return 99;
1507
- case 1:
1508
- return 0;
1509
- case 2:
1510
- return 1;
1511
- case 3:
1512
- return 2;
1513
- case 4:
1514
- return 3;
1515
- default:
1516
- return 1;
1517
- }
1518
- }
1519
  _shouldEmitLoggerLevel(level) {
1520
  const current = Number(this._logLevel);
1521
  if (!Number.isFinite(current) || current < 0) {
1522
  return true;
1523
  }
1524
- const threshold = this._logThresholdForConfiguredLevel(
1525
  Math.max(0, Math.min(4, Math.trunc(current)))
1526
  );
1527
  if (threshold > 3) {
1528
  return false;
1529
  }
1530
- return this._logLevelForName(level) >= threshold;
1531
  }
1532
  _emitLogger(level, message) {
1533
  if (!this._shouldEmitLoggerLevel(level)) {
@@ -1762,19 +1908,7 @@ var LlamaWebGpuBridgeRuntime = class {
1762
  ];
1763
  }
1764
  _nativeLoadOptionTypes() {
1765
- return [
1766
- "number",
1767
- "number",
1768
- "number",
1769
- "number",
1770
- "number",
1771
- "number",
1772
- "number",
1773
- "number",
1774
- "number",
1775
- "number",
1776
- "number"
1777
- ];
1778
  }
1779
  async _tryLoadModelFromRemoteFetchBackend(core, url, options = {}) {
1780
  if (!this._canUseRemoteFetchBackend(options)) {
@@ -2060,6 +2194,15 @@ var LlamaWebGpuBridgeRuntime = class {
2060
  }
2061
  }
2062
  }
 
 
 
 
 
 
 
 
 
2063
  _deleteFsFile(path) {
2064
  if (!this._core || typeof path !== "string" || path.length === 0) {
2065
  return false;
@@ -2704,7 +2847,6 @@ var LlamaWebGpuBridgeRuntime = class {
2704
  {
2705
  useBigIntPosition: this._coreVariant === "wasm64",
2706
  startOffset: resumeOffset,
2707
- allowAppend: resumeOffset > 0,
2708
  preservePartialOnError: true,
2709
  totalBytes: knownTotalBytes,
2710
  chunkTimeoutMs: streamChunkTimeoutMs,
@@ -3288,6 +3430,201 @@ var LlamaWebGpuBridgeRuntime = class {
3288
  this._textToSpeechDone = null;
3289
  }
3290
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3291
  _clearStagedMediaFiles() {
3292
  if (!this._core || this._stagedMediaPaths.length === 0) {
3293
  this._stagedMediaPaths = [];
@@ -3993,6 +4330,8 @@ var LlamaWebGpuBridge = class {
3993
  this._disposed = false;
3994
  this._disposePromise = null;
3995
  this._disposalWaiters = /* @__PURE__ */ new Set();
 
 
3996
  if (this._shouldUseWorker()) {
3997
  try {
3998
  this._workerProxy = new BridgeWorkerProxy({
@@ -4526,7 +4865,7 @@ var LlamaWebGpuBridge = class {
4526
  }
4527
  _isRecoverableWorkerFsError(error) {
4528
  const text = serializeWorkerError(error).toLowerCase();
4529
- return text.includes("fs error") || text.includes("no such file") || text.includes("not found") || text.includes("invalid argument") || text.includes("worker request timeout") || text.includes("timed out");
4530
  }
4531
  _isWorkerRequestTimeoutError(error) {
4532
  const text = serializeWorkerError(error).toLowerCase();
@@ -4610,9 +4949,6 @@ var LlamaWebGpuBridge = class {
4610
  const text = serializeWorkerError(error).toLowerCase();
4611
  return text.includes("worker completion stalled") || text.includes("worker createcompletion stalled") || text.includes("worker timed out") || text.includes("worker timeout");
4612
  }
4613
- _isForcedCpuMultimodalFallbackError(error) {
4614
- return error && typeof error === "object" && error.llamadartForceCpuMultimodal === true;
4615
- }
4616
  _isCpuModelMode() {
4617
  const requestedLayers = Number(this._loadedModelOptions?.nGpuLayers);
4618
  if (Number.isFinite(requestedLayers)) {
@@ -4655,12 +4991,11 @@ var LlamaWebGpuBridge = class {
4655
  const multimodalRuntimeRequired = mediaPartsRequested || textToSpeechRequested;
4656
  const shouldEnsureMultimodalInRuntime = multimodalRuntimeRequired && typeof this._loadedMmProjUrl === "string" && this._loadedMmProjUrl.length > 0;
4657
  const workerTimedOut = this._isWorkerTimeoutError(fallbackError);
4658
- const forcedCpuFallback = this._isForcedCpuMultimodalFallbackError(fallbackError);
4659
  const dispatchWorkgroupFallback = this._isDispatchWorkgroupLimitError(fallbackError);
4660
  const loadedGpuLayers = Number(this._loadedModelOptions?.nGpuLayers);
4661
  const metadataGpuLayers = Number(this._metadata?.["llamadart.webgpu.n_gpu_layers"]);
4662
  const modelLoadedWithGpu = Number.isFinite(loadedGpuLayers) ? loadedGpuLayers !== 0 : Number.isFinite(metadataGpuLayers) ? metadataGpuLayers !== 0 : true;
4663
- const shouldUseCpuMultimodalFallback = multimodalRuntimeRequired && modelLoadedWithGpu && (dispatchWorkgroupFallback || forcedCpuFallback || workerTimedOut);
4664
  try {
4665
  if (Number(this._runtime?._modelBytes) > 0 && !forceReloadRequested && !shouldUseCpuMultimodalFallback) {
4666
  if (shouldEnsureMultimodalInRuntime) {
@@ -4689,10 +5024,6 @@ var LlamaWebGpuBridge = class {
4689
  this._emitBridgeWarn(
4690
  "llamadart: retrying text-to-speech once with CPU fallback after WebGPU failure."
4691
  );
4692
- } else if (forcedCpuFallback) {
4693
- this._emitBridgeWarn(
4694
- "llamadart: using CPU fallback for multimodal generation stability."
4695
- );
4696
  } else if (workerTimedOut) {
4697
  this._emitBridgeWarn(
4698
  "llamadart: retrying multimodal generation with CPU fallback after worker timeout."
@@ -4884,44 +5215,13 @@ var LlamaWebGpuBridge = class {
4884
  }
4885
  return 2;
4886
  }
4887
- _bridgeLogLevelForName(level) {
4888
- switch (level) {
4889
- case "debug":
4890
- return 0;
4891
- case "log":
4892
- case "info":
4893
- return 1;
4894
- case "warn":
4895
- return 2;
4896
- case "error":
4897
- return 3;
4898
- default:
4899
- return 1;
4900
- }
4901
- }
4902
- _bridgeLogThresholdForConfiguredLevel(level) {
4903
- switch (level) {
4904
- case 0:
4905
- return 99;
4906
- case 1:
4907
- return 0;
4908
- case 2:
4909
- return 1;
4910
- case 3:
4911
- return 2;
4912
- case 4:
4913
- return 3;
4914
- default:
4915
- return 1;
4916
- }
4917
- }
4918
  _shouldEmitBridgeLevel(level) {
4919
  const configured = this._resolvedBridgeLogLevel();
4920
- const threshold = this._bridgeLogThresholdForConfiguredLevel(configured);
4921
  if (threshold > 3) {
4922
  return false;
4923
  }
4924
- return this._bridgeLogLevelForName(level) >= threshold;
4925
  }
4926
  _shouldSuppressBridgeWarn(message) {
4927
  const text = String(message || "").trim();
@@ -4959,21 +5259,14 @@ var LlamaWebGpuBridge = class {
4959
  }
4960
  }
4961
  _disableWorkerFallback(error) {
4962
- const forcedCpuMultimodal = this._isForcedCpuMultimodalFallbackError(error);
4963
- const reason = forcedCpuMultimodal ? "multimodal_stability_mode" : serializeWorkerError(error);
4964
  this._workerFallbackReason = reason;
4965
  if (typeof globalThis !== "undefined") {
4966
  globalThis.__llamadartBridgeWorkerFallbackReason = reason;
4967
  }
4968
- if (forcedCpuMultimodal) {
4969
- this._emitBridgeWarn(
4970
- "llamadart: switching multimodal pipeline to main-thread runtime for stability."
4971
- );
4972
- } else {
4973
- this._emitBridgeWarn(
4974
- `llamadart: bridge worker unavailable, falling back to main thread (${reason})`
4975
- );
4976
- }
4977
  if (this._workerProxy) {
4978
  const workerProxy = this._workerProxy;
4979
  this._advanceWorkerGeneration();
@@ -4991,9 +5284,6 @@ var LlamaWebGpuBridge = class {
4991
  }
4992
  if (this._runtime && Array.isArray(this._runtime._runtimeNotes) && typeof reason === "string" && reason.length > 0) {
4993
  this._runtime._runtimeNotes.push(`worker_fallback:${reason}`);
4994
- if (forcedCpuMultimodal) {
4995
- this._runtime._runtimeNotes.push("worker_fallback_forced_multimodal");
4996
- }
4997
  }
4998
  }
4999
  async _callWorker(method, args, onEvent, transferList = []) {
@@ -5517,6 +5807,203 @@ var LlamaWebGpuBridge = class {
5517
  throw error;
5518
  }
5519
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5520
  async tokenize(text, addSpecial = true) {
5521
  return this._runExclusive(
5522
  () => this._tokenizeUnlocked(text, addSpecial),
@@ -5793,6 +6280,7 @@ var LlamaWebGpuBridge = class {
5793
  this._loadedMmProjUrl = null;
5794
  this._workerFallbackReason = null;
5795
  this._multimodalWorkerCpuMode = false;
 
5796
  this._lifecycleState = "disposed";
5797
  }
5798
  }
 
8
  var BRIDGE_DISPOSED_MESSAGE = "Bridge has been disposed.";
9
  var GENERATION_ALREADY_ACTIVE_RC = -7;
10
  var GENERATION_ALREADY_ACTIVE_MESSAGE = "Generation is already active on this bridge runtime.";
11
+ var DECISION_API_VERSION = 1;
12
+ var DECISION_WORKER_TIMEOUT_PER_SEQUENCE_MS = 60 * 1e3;
13
  function createAbortError(message) {
14
  if (typeof DOMException === "function") {
15
  return new DOMException(message, "AbortError");
 
334
  const useBigIntPosition = writeOptions.useBigIntPosition === true;
335
  const startOffset = parsePositiveInteger(writeOptions.startOffset);
336
  const preservePartialOnError = writeOptions.preservePartialOnError === true;
337
+ const appendMode = startOffset > 0;
 
338
  const chunkTimeoutMs = parsePositiveInteger(writeOptions.chunkTimeoutMs);
339
  const signal = writeOptions.signal || null;
340
  const abortMessage = writeOptions.abortMessage || "Model transfer was cancelled.";
 
504
  }
505
  return null;
506
  }
507
+ function isInt32(value) {
508
+ return typeof value === "number" && Number.isInteger(value) && value >= -2147483648 && value <= 2147483647;
509
+ }
510
+ function decisionHandleFrom(handle) {
511
+ if (!isInt32(handle) || handle <= 0) {
512
+ throw new TypeError(`Decision head handle must be a positive integer, got ${String(handle)}.`);
513
+ }
514
+ return handle;
515
+ }
516
+ function decisionHeadBytes(source) {
517
+ if (source instanceof ArrayBuffer) {
518
+ return new Uint8Array(source);
519
+ }
520
+ if (ArrayBuffer.isView(source)) {
521
+ return new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
522
+ }
523
+ return null;
524
+ }
525
+ function decisionIntegerList(value, label) {
526
+ const isList = Array.isArray(value) || ArrayBuffer.isView(value) && !(value instanceof DataView);
527
+ if (!isList) {
528
+ throw new TypeError(`${label} must be an array or typed array of integers.`);
529
+ }
530
+ const list = (
531
+ /** @type {ArrayLike<unknown>} */
532
+ value
533
+ );
534
+ const out = new Int32Array(list.length);
535
+ for (let index = 0; index < list.length; index += 1) {
536
+ const item = list[index];
537
+ if (!isInt32(item)) {
538
+ throw new TypeError(`${label}[${index}] is ${String(item)}; expected a 32-bit integer.`);
539
+ }
540
+ out[index] = /** @type {number} */
541
+ item;
542
+ }
543
+ return out;
544
+ }
545
+ function normalizeDecisionSequences(sequences) {
546
+ if (!Array.isArray(sequences)) {
547
+ throw new TypeError("Decision sequences must be an array.");
548
+ }
549
+ return sequences.map((sequence, index) => {
550
+ const label = `Decision sequence ${index}`;
551
+ if (!sequence || typeof sequence !== "object") {
552
+ throw new TypeError(`${label} must be an object with tokens, markers and questionType.`);
553
+ }
554
+ const tokens = decisionIntegerList(sequence.tokens, `${label} tokens`);
555
+ const markers = decisionIntegerList(sequence.markers, `${label} markers`);
556
+ const questionType = sequence.questionType;
557
+ if (!isInt32(questionType)) {
558
+ throw new TypeError(
559
+ `${label} questionType is ${String(questionType)}; expected 0 (choice), 1 (score) or 2 (noul).`
560
+ );
561
+ }
562
+ return { tokens, markers, questionType: (
563
+ /** @type {number} */
564
+ questionType
565
+ ) };
566
+ });
567
+ }
568
+ function encodeDecisionSequences(sequences) {
569
+ const encoded = normalizeDecisionSequences(sequences);
570
+ let words = 1;
571
+ for (const sequence of encoded) {
572
+ words += 3 + sequence.tokens.length + sequence.markers.length;
573
+ }
574
+ const bytes = new Uint8Array(words * 4);
575
+ const view = new DataView(bytes.buffer);
576
+ let offset = 0;
577
+ const put = (value) => {
578
+ view.setInt32(offset, value, true);
579
+ offset += 4;
580
+ };
581
+ put(encoded.length);
582
+ for (const sequence of encoded) {
583
+ put(sequence.questionType);
584
+ put(sequence.tokens.length);
585
+ put(sequence.markers.length);
586
+ sequence.tokens.forEach(put);
587
+ sequence.markers.forEach(put);
588
+ }
589
+ return bytes;
590
+ }
591
+ function decodeDecisionOutputs(bytes, count) {
592
+ const malformed = () => new Error("Decision output from the WebGPU core is malformed.");
593
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
594
+ let offset = 0;
595
+ const floats = (length) => {
596
+ const values = new Float32Array(length);
597
+ for (let index = 0; index < length; index += 1) {
598
+ values[index] = view.getFloat32(offset, true);
599
+ offset += 4;
600
+ }
601
+ return values;
602
+ };
603
+ const outputs = [];
604
+ for (let index = 0; index < count; index += 1) {
605
+ if (bytes.byteLength - offset < 8) {
606
+ throw malformed();
607
+ }
608
+ const logitCount = view.getInt32(offset, true);
609
+ const actCount = view.getInt32(offset + 4, true);
610
+ offset += 8;
611
+ if (logitCount < 0 || actCount < 0 || (logitCount + actCount) * 4 > bytes.byteLength - offset) {
612
+ throw malformed();
613
+ }
614
+ outputs.push({ logits: floats(logitCount), actLogits: floats(actCount) });
615
+ }
616
+ if (offset !== bytes.byteLength) {
617
+ throw malformed();
618
+ }
619
+ return outputs;
620
+ }
621
  async function decodeImageBytesToRgb(bytes, options = {}) {
622
  const sourceBytes = toUint8Array(bytes);
623
  if (!sourceBytes || sourceBytes.length === 0) {
 
717
  }
718
  }
719
  }
720
+ function logLevelForName(level) {
721
+ switch (level) {
722
+ case "debug":
723
+ return 0;
724
+ case "log":
725
+ case "info":
726
+ return 1;
727
+ case "warn":
728
+ return 2;
729
+ case "error":
730
+ return 3;
731
+ default:
732
+ return 1;
733
+ }
734
+ }
735
+ function logThresholdForConfiguredLevel(level) {
736
+ switch (level) {
737
+ case 0:
738
+ return 99;
739
+ case 1:
740
+ return 0;
741
+ case 2:
742
+ return 1;
743
+ case 3:
744
+ return 2;
745
+ case 4:
746
+ return 3;
747
+ default:
748
+ return 1;
749
+ }
750
+ }
751
  function serializeWorkerError(error) {
752
  if (!error) {
753
  return "Unknown worker error";
 
1007
  );
1008
  return;
1009
  }
1010
+ if (method === "loadDecisionHead") {
1011
+ const options = args[1] && typeof args[1] === "object" ? { ...args[1] } : {};
1012
+ options.onProgress = (progress) => {
1013
+ self.postMessage({ type: "event", id, event: "progress", payload: progress || {} });
1014
+ };
1015
+ const value2 = await bridge.loadDecisionHead(args[0], options);
1016
+ self.postMessage({ type: "result", id, value: value2 });
1017
+ return;
1018
+ }
1019
+ if (method === "runDecision") {
1020
+ const value2 = await bridge.runDecision(args[0], args[1]);
1021
+ const transfers = [];
1022
+ for (const output of Array.isArray(value2) ? value2 : []) {
1023
+ for (const values of [output?.logits, output?.actLogits]) {
1024
+ const buffer = values?.buffer;
1025
+ if (buffer instanceof ArrayBuffer && !transfers.includes(buffer)) {
1026
+ transfers.push(buffer);
1027
+ }
1028
+ }
1029
+ }
1030
+ self.postMessage({ type: "result", id, value: value2 }, transfers);
1031
+ return;
1032
+ }
1033
  if (method === "unloadMultimodalProjector") {
1034
  const value2 = await bridge.unloadMultimodalProjector();
1035
  self.postMessage({ type: "result", id, value: value2, state: snapshotBridgeState(bridge) });
 
1228
  async call(method, args, onEvent, transferList = [], operationMeta = null) {
1229
  await this._ready;
1230
  const id = this._nextId++;
1231
+ const timeoutMs = this._resolveRequestTimeoutMs(method, args);
1232
  const transfers = Array.isArray(transferList) ? transferList.filter((item) => item != null) : [];
1233
  return new Promise((resolve, reject) => {
1234
  let timeoutHandle = null;
 
1296
  }
1297
  }, timeoutMs);
1298
  }
1299
+ _resolveRequestTimeoutMs(method, args = []) {
1300
  const explicitGlobal = Number(this._config.workerRequestTimeoutMs);
1301
  const clamp = (value, fallback) => {
1302
  if (!Number.isFinite(value) || value <= 0) {
 
1316
  if (method === "synthesizeSpeech") {
1317
  return clamp(Number(this._config.workerTextToSpeechTimeoutMs), clamp(explicitGlobal, 20 * 60 * 1e3));
1318
  }
1319
+ if (method === "loadDecisionHead") {
1320
+ return clamp(explicitGlobal, 10 * 60 * 1e3);
1321
+ }
1322
+ if (method === "runDecision") {
1323
+ const sequences = Array.isArray(args?.[1]) ? args[1].length : 0;
1324
+ return clamp(explicitGlobal, 10 * 60 * 1e3 + sequences * DECISION_WORKER_TIMEOUT_PER_SEQUENCE_MS);
1325
+ }
1326
  return clamp(explicitGlobal, 12e4);
1327
  }
1328
  async dispose() {
 
1367
  this._mmSupportsAudio = false;
1368
  this._mediaFileCounter = 0;
1369
  this._stateFileCounter = 0;
1370
+ this._decisionFileCounter = 0;
1371
  this._stagedMediaPaths = [];
1372
  this._nCtx = 4096;
1373
  this._abortRequested = false;
 
1662
  return () => {
1663
  };
1664
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1665
  _shouldEmitLoggerLevel(level) {
1666
  const current = Number(this._logLevel);
1667
  if (!Number.isFinite(current) || current < 0) {
1668
  return true;
1669
  }
1670
+ const threshold = logThresholdForConfiguredLevel(
1671
  Math.max(0, Math.min(4, Math.trunc(current)))
1672
  );
1673
  if (threshold > 3) {
1674
  return false;
1675
  }
1676
+ return logLevelForName(level) >= threshold;
1677
  }
1678
  _emitLogger(level, message) {
1679
  if (!this._shouldEmitLoggerLevel(level)) {
 
1908
  ];
1909
  }
1910
  _nativeLoadOptionTypes() {
1911
+ return this._nativeLoadOptionValues().map(() => "number");
 
 
 
 
 
 
 
 
 
 
 
 
1912
  }
1913
  async _tryLoadModelFromRemoteFetchBackend(core, url, options = {}) {
1914
  if (!this._canUseRemoteFetchBackend(options)) {
 
2194
  }
2195
  }
2196
  }
2197
+ _unlinkDecisionFile(path) {
2198
+ if (!this._core || typeof path !== "string" || path.length === 0) {
2199
+ return;
2200
+ }
2201
+ try {
2202
+ this._core.FS.unlink(path);
2203
+ } catch (_) {
2204
+ }
2205
+ }
2206
  _deleteFsFile(path) {
2207
  if (!this._core || typeof path !== "string" || path.length === 0) {
2208
  return false;
 
2847
  {
2848
  useBigIntPosition: this._coreVariant === "wasm64",
2849
  startOffset: resumeOffset,
 
2850
  preservePartialOnError: true,
2851
  totalBytes: knownTotalBytes,
2852
  chunkTimeoutMs: streamChunkTimeoutMs,
 
3430
  this._textToSpeechDone = null;
3431
  }
3432
  }
3433
+ getDecisionCapabilities() {
3434
+ const unsupported = (reason) => ({
3435
+ apiVersion: DECISION_API_VERSION,
3436
+ supported: false,
3437
+ reason
3438
+ });
3439
+ const core = this._core;
3440
+ if (!core) {
3441
+ return unsupported("WebGPU core is not initialized");
3442
+ }
3443
+ if (typeof core._llamadart_webgpu_decision_capabilities_json !== "function") {
3444
+ return unsupported("This WebGPU core build does not include decision heads.");
3445
+ }
3446
+ const coreVersion = Number(
3447
+ core.ccall("llamadart_webgpu_decision_api_version", "number", [], [])
3448
+ );
3449
+ if (coreVersion !== DECISION_API_VERSION) {
3450
+ return unsupported(
3451
+ `The WebGPU core implements decision API version ${coreVersion}; this bridge needs version ${DECISION_API_VERSION}.`
3452
+ );
3453
+ }
3454
+ const raw = core.ccall(
3455
+ "llamadart_webgpu_decision_capabilities_json",
3456
+ "string",
3457
+ [],
3458
+ []
3459
+ ) || "{}";
3460
+ try {
3461
+ return JSON.parse(raw);
3462
+ } catch (_) {
3463
+ return unsupported("WebGPU decision capability response is invalid");
3464
+ }
3465
+ }
3466
+ _ensureDecisionDir() {
3467
+ try {
3468
+ this._core.FS.mkdir("/decision");
3469
+ } catch (_) {
3470
+ }
3471
+ }
3472
+ async _stageDecisionHeadFromUrl(url, headPath, onProgress) {
3473
+ const fetchTimeoutMs = this._resolveFetchTimeoutMs({}, 18e4);
3474
+ const chunkTimeoutMs = this._resolveStreamChunkTimeoutMs({}, 9e4);
3475
+ for (let attempt = 0; ; attempt += 1) {
3476
+ try {
3477
+ const response = await this._fetchWithTimeout(
3478
+ url,
3479
+ { cache: "no-store" },
3480
+ fetchTimeoutMs
3481
+ );
3482
+ if (!response.ok) {
3483
+ throw new Error(
3484
+ `Failed to fetch decision head: ${response.status} ${response.statusText}`
3485
+ );
3486
+ }
3487
+ await writeResponseToFsFileWithProgress(
3488
+ response,
3489
+ this._core.FS,
3490
+ headPath,
3491
+ typeof onProgress === "function" ? onProgress : null,
3492
+ {
3493
+ useBigIntPosition: this._coreVariant === "wasm64",
3494
+ chunkTimeoutMs
3495
+ }
3496
+ );
3497
+ return;
3498
+ } catch (error) {
3499
+ this._unlinkDecisionFile(headPath);
3500
+ if (!isRetryableStreamNetworkError(error) || attempt >= 1) {
3501
+ throw error;
3502
+ }
3503
+ this._runtimeNotes.push(`decision_head_fetch_retry:${attempt + 1}`);
3504
+ }
3505
+ }
3506
+ }
3507
+ /**
3508
+ * @param {string | ArrayBuffer | ArrayBufferView} source
3509
+ * @param {{ configJson?: string | null, onProgress?: (progress: { loaded: number, total: number }) => void }} [options]
3510
+ */
3511
+ async loadDecisionHead(source, options = {}) {
3512
+ if (!this._core || this._modelBytes <= 0) {
3513
+ throw new Error("No model loaded. Call loadModelFromUrl first.");
3514
+ }
3515
+ const configJson = options?.configJson ?? null;
3516
+ if (configJson !== null && typeof configJson !== "string") {
3517
+ throw new TypeError("Decision head configJson must be a string.");
3518
+ }
3519
+ let bytes = null;
3520
+ if (typeof source === "string") {
3521
+ if (source.length === 0) {
3522
+ throw new Error("Decision head URL is empty.");
3523
+ }
3524
+ } else {
3525
+ bytes = decisionHeadBytes(source);
3526
+ if (!bytes) {
3527
+ throw new TypeError("Decision head source must be a URL string, an ArrayBuffer or a typed array.");
3528
+ }
3529
+ if (bytes.byteLength === 0) {
3530
+ throw new Error("Decision head bytes are empty.");
3531
+ }
3532
+ }
3533
+ const capabilities = this.getDecisionCapabilities();
3534
+ if (capabilities.supported !== true) {
3535
+ throw new Error(
3536
+ capabilities.reason || "The loaded model does not support decision heads."
3537
+ );
3538
+ }
3539
+ const core = this._core;
3540
+ this._ensureDecisionDir();
3541
+ const taskId = `${Date.now()}_${++this._decisionFileCounter}`;
3542
+ const headPath = `/decision/head_${taskId}.safetensors`;
3543
+ const configPath = configJson === null ? null : `/decision/config_${taskId}.json`;
3544
+ try {
3545
+ let label = "decision head bytes";
3546
+ if (bytes) {
3547
+ core.FS.writeFile(headPath, bytes);
3548
+ } else {
3549
+ label = basenameFromUrl(source).slice(0, 256);
3550
+ await this._stageDecisionHeadFromUrl(source, headPath, options?.onProgress);
3551
+ }
3552
+ if (configPath !== null) {
3553
+ core.FS.writeFile(configPath, textEncoder.encode(configJson));
3554
+ }
3555
+ const handle = Number(
3556
+ await core.ccall(
3557
+ "llamadart_webgpu_decision_load",
3558
+ "number",
3559
+ ["string", "string", "string"],
3560
+ [headPath, label, configPath],
3561
+ { async: true }
3562
+ )
3563
+ );
3564
+ if (handle <= 0) {
3565
+ throw new Error(this._coreErrorMessage("Failed to load decision head", handle));
3566
+ }
3567
+ const raw = core.ccall(
3568
+ "llamadart_webgpu_decision_head_info_json",
3569
+ "string",
3570
+ ["number"],
3571
+ [handle]
3572
+ ) || "{}";
3573
+ return JSON.parse(raw);
3574
+ } finally {
3575
+ this._unlinkDecisionFile(headPath);
3576
+ this._unlinkDecisionFile(configPath);
3577
+ }
3578
+ }
3579
+ /**
3580
+ * @param {number} handle
3581
+ * @param {unknown} sequences
3582
+ */
3583
+ async runDecision(handle, sequences) {
3584
+ const nativeHandle = decisionHandleFrom(handle);
3585
+ const input = encodeDecisionSequences(sequences);
3586
+ if (!this._core || this._modelBytes <= 0) {
3587
+ throw new Error("No model loaded. Call loadModelFromUrl first.");
3588
+ }
3589
+ const core = this._core;
3590
+ this._ensureDecisionDir();
3591
+ const taskId = `${Date.now()}_${++this._decisionFileCounter}`;
3592
+ const inputPath = `/decision/input_${taskId}.bin`;
3593
+ const outputPath = `/decision/output_${taskId}.bin`;
3594
+ try {
3595
+ core.FS.writeFile(inputPath, input);
3596
+ const count = Number(
3597
+ await core.ccall(
3598
+ "llamadart_webgpu_decision_run",
3599
+ "number",
3600
+ ["number", "string", "string"],
3601
+ [nativeHandle, inputPath, outputPath],
3602
+ { async: true }
3603
+ )
3604
+ );
3605
+ if (count < 0) {
3606
+ throw new Error(this._coreErrorMessage("Decision run failed", count));
3607
+ }
3608
+ return decodeDecisionOutputs(core.FS.readFile(outputPath), count);
3609
+ } finally {
3610
+ this._unlinkDecisionFile(inputPath);
3611
+ this._unlinkDecisionFile(outputPath);
3612
+ }
3613
+ }
3614
+ /** @param {number} handle */
3615
+ async freeDecisionHead(handle) {
3616
+ const nativeHandle = decisionHandleFrom(handle);
3617
+ if (!this._core) {
3618
+ return;
3619
+ }
3620
+ await this._core.ccall(
3621
+ "llamadart_webgpu_decision_free",
3622
+ "number",
3623
+ ["number"],
3624
+ [nativeHandle],
3625
+ { async: true }
3626
+ );
3627
+ }
3628
  _clearStagedMediaFiles() {
3629
  if (!this._core || this._stagedMediaPaths.length === 0) {
3630
  this._stagedMediaPaths = [];
 
4330
  this._disposed = false;
4331
  this._disposePromise = null;
4332
  this._disposalWaiters = /* @__PURE__ */ new Set();
4333
+ this._decisionHeads = /* @__PURE__ */ new Map();
4334
+ this._nextDecisionHandle = 1;
4335
  if (this._shouldUseWorker()) {
4336
  try {
4337
  this._workerProxy = new BridgeWorkerProxy({
 
4865
  }
4866
  _isRecoverableWorkerFsError(error) {
4867
  const text = serializeWorkerError(error).toLowerCase();
4868
+ return text.includes("fs error") || text.includes("no such file") || text.includes("not found") || text.includes("invalid argument") || text.includes("timed out");
4869
  }
4870
  _isWorkerRequestTimeoutError(error) {
4871
  const text = serializeWorkerError(error).toLowerCase();
 
4949
  const text = serializeWorkerError(error).toLowerCase();
4950
  return text.includes("worker completion stalled") || text.includes("worker createcompletion stalled") || text.includes("worker timed out") || text.includes("worker timeout");
4951
  }
 
 
 
4952
  _isCpuModelMode() {
4953
  const requestedLayers = Number(this._loadedModelOptions?.nGpuLayers);
4954
  if (Number.isFinite(requestedLayers)) {
 
4991
  const multimodalRuntimeRequired = mediaPartsRequested || textToSpeechRequested;
4992
  const shouldEnsureMultimodalInRuntime = multimodalRuntimeRequired && typeof this._loadedMmProjUrl === "string" && this._loadedMmProjUrl.length > 0;
4993
  const workerTimedOut = this._isWorkerTimeoutError(fallbackError);
 
4994
  const dispatchWorkgroupFallback = this._isDispatchWorkgroupLimitError(fallbackError);
4995
  const loadedGpuLayers = Number(this._loadedModelOptions?.nGpuLayers);
4996
  const metadataGpuLayers = Number(this._metadata?.["llamadart.webgpu.n_gpu_layers"]);
4997
  const modelLoadedWithGpu = Number.isFinite(loadedGpuLayers) ? loadedGpuLayers !== 0 : Number.isFinite(metadataGpuLayers) ? metadataGpuLayers !== 0 : true;
4998
+ const shouldUseCpuMultimodalFallback = multimodalRuntimeRequired && modelLoadedWithGpu && (dispatchWorkgroupFallback || workerTimedOut);
4999
  try {
5000
  if (Number(this._runtime?._modelBytes) > 0 && !forceReloadRequested && !shouldUseCpuMultimodalFallback) {
5001
  if (shouldEnsureMultimodalInRuntime) {
 
5024
  this._emitBridgeWarn(
5025
  "llamadart: retrying text-to-speech once with CPU fallback after WebGPU failure."
5026
  );
 
 
 
 
5027
  } else if (workerTimedOut) {
5028
  this._emitBridgeWarn(
5029
  "llamadart: retrying multimodal generation with CPU fallback after worker timeout."
 
5215
  }
5216
  return 2;
5217
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5218
  _shouldEmitBridgeLevel(level) {
5219
  const configured = this._resolvedBridgeLogLevel();
5220
+ const threshold = logThresholdForConfiguredLevel(configured);
5221
  if (threshold > 3) {
5222
  return false;
5223
  }
5224
+ return logLevelForName(level) >= threshold;
5225
  }
5226
  _shouldSuppressBridgeWarn(message) {
5227
  const text = String(message || "").trim();
 
5259
  }
5260
  }
5261
  _disableWorkerFallback(error) {
5262
+ const reason = serializeWorkerError(error);
 
5263
  this._workerFallbackReason = reason;
5264
  if (typeof globalThis !== "undefined") {
5265
  globalThis.__llamadartBridgeWorkerFallbackReason = reason;
5266
  }
5267
+ this._emitBridgeWarn(
5268
+ `llamadart: bridge worker unavailable, falling back to main thread (${reason})`
5269
+ );
 
 
 
 
 
 
5270
  if (this._workerProxy) {
5271
  const workerProxy = this._workerProxy;
5272
  this._advanceWorkerGeneration();
 
5284
  }
5285
  if (this._runtime && Array.isArray(this._runtime._runtimeNotes) && typeof reason === "string" && reason.length > 0) {
5286
  this._runtime._runtimeNotes.push(`worker_fallback:${reason}`);
 
 
 
5287
  }
5288
  }
5289
  async _callWorker(method, args, onEvent, transferList = []) {
 
5807
  throw error;
5808
  }
5809
  }
5810
+ /** @returns {Map<number, { owner: object, handle: number }>} */
5811
+ _decisionHeadMap() {
5812
+ if (!(this._decisionHeads instanceof Map)) {
5813
+ this._decisionHeads = /* @__PURE__ */ new Map();
5814
+ this._nextDecisionHandle = 1;
5815
+ }
5816
+ return this._decisionHeads;
5817
+ }
5818
+ _registerDecisionHead(owner, info) {
5819
+ const heads = this._decisionHeadMap();
5820
+ const handle = this._nextDecisionHandle++;
5821
+ heads.set(handle, { owner, handle: Number(info?.handle) });
5822
+ return { ...info, handle };
5823
+ }
5824
+ _decisionOwner() {
5825
+ return this._workerProxy || this._runtime || null;
5826
+ }
5827
+ _staleDecisionHeadError(handle) {
5828
+ return new Error(
5829
+ `Decision head ${handle} is not loaded; it was freed, its model was unloaded, or the bridge runtime restarted. Load the decision head again.`
5830
+ );
5831
+ }
5832
+ /** @param {number} handle */
5833
+ _resolveDecisionHead(handle) {
5834
+ decisionHandleFrom(handle);
5835
+ const heads = this._decisionHeadMap();
5836
+ const entry = heads.get(handle);
5837
+ if (!entry) {
5838
+ return null;
5839
+ }
5840
+ if (entry.owner !== this._decisionOwner()) {
5841
+ heads.delete(handle);
5842
+ return null;
5843
+ }
5844
+ return entry;
5845
+ }
5846
+ _requireDecisionRuntime() {
5847
+ if (!this._runtime) {
5848
+ throw new Error("No model loaded. Call loadModelFromUrl first.");
5849
+ }
5850
+ return this._runtime;
5851
+ }
5852
+ /**
5853
+ * Moves a failed worker's work to the main-thread runtime. Heads the worker
5854
+ * held are gone with it; the model is reloaded so later calls keep working.
5855
+ */
5856
+ async _recoverDecisionWorker(error) {
5857
+ this._disableWorkerFallback(error);
5858
+ await this._waitForWorkerDisposal();
5859
+ await this._ensureRuntimeReadyAfterWorkerFallback({}, error);
5860
+ }
5861
+ async getDecisionCapabilities() {
5862
+ return this._runExclusive(
5863
+ () => this._getDecisionCapabilitiesUnlocked(),
5864
+ { kind: "decision-capabilities" }
5865
+ );
5866
+ }
5867
+ async _getDecisionCapabilitiesUnlocked() {
5868
+ if (!this._workerProxy) {
5869
+ return this._runtime ? this._runtime.getDecisionCapabilities() : { apiVersion: DECISION_API_VERSION, supported: false, reason: "WebGPU core is not initialized" };
5870
+ }
5871
+ try {
5872
+ return await this._callWorker("getDecisionCapabilities", []);
5873
+ } catch (error) {
5874
+ this._throwIfOperationCancelled(error, "Decision capability probe was cancelled.");
5875
+ if (!this._shouldFallbackToMainThread(error)) {
5876
+ throw error;
5877
+ }
5878
+ await this._recoverDecisionWorker(error);
5879
+ return this._requireDecisionRuntime().getDecisionCapabilities();
5880
+ }
5881
+ }
5882
+ /**
5883
+ * @param {string | ArrayBuffer | ArrayBufferView} source
5884
+ * @param {{ configJson?: string | null, onProgress?: (progress: { loaded: number, total: number }) => void }} [options]
5885
+ */
5886
+ async loadDecisionHead(source, options = {}) {
5887
+ return this._runExclusive(
5888
+ () => this._loadDecisionHeadUnlocked(source, options),
5889
+ { kind: "decision-head-load" }
5890
+ );
5891
+ }
5892
+ /**
5893
+ * @param {string | ArrayBuffer | ArrayBufferView} source
5894
+ * @param {{ configJson?: string | null, onProgress?: (progress: { loaded: number, total: number }) => void }} [options]
5895
+ */
5896
+ async _loadDecisionHeadUnlocked(source, options = {}) {
5897
+ const loadInRuntime = async () => {
5898
+ const runtime = this._requireDecisionRuntime();
5899
+ return this._registerDecisionHead(
5900
+ runtime,
5901
+ await runtime.loadDecisionHead(source, options)
5902
+ );
5903
+ };
5904
+ if (!this._workerProxy) {
5905
+ return loadInRuntime();
5906
+ }
5907
+ const proxy = this._workerProxy;
5908
+ const workerOptions = { configJson: options?.configJson ?? null };
5909
+ let workerSource = source;
5910
+ const transferList = [];
5911
+ if (typeof source === "string") {
5912
+ workerSource = source.length > 0 ? normalizeAbsoluteUrl(source) : source;
5913
+ } else {
5914
+ const bytes = decisionHeadBytes(source);
5915
+ if (bytes) {
5916
+ const copy = new Uint8Array(bytes);
5917
+ workerSource = copy;
5918
+ transferList.push(copy.buffer);
5919
+ }
5920
+ }
5921
+ try {
5922
+ const info = await this._callWorker(
5923
+ "loadDecisionHead",
5924
+ [workerSource, workerOptions],
5925
+ (event) => {
5926
+ if (event.event === "progress") {
5927
+ options?.onProgress?.(event.payload || {});
5928
+ }
5929
+ },
5930
+ transferList
5931
+ );
5932
+ return this._registerDecisionHead(proxy, info);
5933
+ } catch (error) {
5934
+ this._throwIfOperationCancelled(error, "Decision head load was cancelled.");
5935
+ if (!this._shouldFallbackToMainThread(error)) {
5936
+ throw error;
5937
+ }
5938
+ await this._recoverDecisionWorker(error);
5939
+ return loadInRuntime();
5940
+ }
5941
+ }
5942
+ /**
5943
+ * @param {number} handle
5944
+ * @param {readonly import('./llama_webgpu_bridge.d.ts').DecisionSequence[]} sequences
5945
+ */
5946
+ async runDecision(handle, sequences) {
5947
+ return this._runExclusive(
5948
+ () => this._runDecisionUnlocked(handle, sequences),
5949
+ { kind: "decision-run" }
5950
+ );
5951
+ }
5952
+ /**
5953
+ * @param {number} handle
5954
+ * @param {readonly import('./llama_webgpu_bridge.d.ts').DecisionSequence[]} sequences
5955
+ */
5956
+ async _runDecisionUnlocked(handle, sequences) {
5957
+ const entry = this._resolveDecisionHead(handle);
5958
+ if (!entry) {
5959
+ throw this._staleDecisionHeadError(handle);
5960
+ }
5961
+ const normalized = normalizeDecisionSequences(sequences);
5962
+ if (!this._workerProxy) {
5963
+ return this._requireDecisionRuntime().runDecision(entry.handle, normalized);
5964
+ }
5965
+ try {
5966
+ return await this._callWorker("runDecision", [entry.handle, normalized]);
5967
+ } catch (error) {
5968
+ this._throwIfOperationCancelled(error, "Decision run was cancelled.");
5969
+ if (!this._shouldFallbackToMainThread(error)) {
5970
+ throw error;
5971
+ }
5972
+ this._decisionHeadMap().delete(handle);
5973
+ await this._recoverDecisionWorker(error);
5974
+ throw new Error(
5975
+ `Decision head ${handle} was lost when the bridge worker failed (${serializeWorkerError(error)}). Load the decision head again.`
5976
+ );
5977
+ }
5978
+ }
5979
+ /** @param {number} handle */
5980
+ async freeDecisionHead(handle) {
5981
+ return this._runExclusive(
5982
+ () => this._freeDecisionHeadUnlocked(handle),
5983
+ { kind: "decision-head-free" }
5984
+ );
5985
+ }
5986
+ /** @param {number} handle */
5987
+ async _freeDecisionHeadUnlocked(handle) {
5988
+ const entry = this._resolveDecisionHead(handle);
5989
+ if (!entry) {
5990
+ return;
5991
+ }
5992
+ this._decisionHeadMap().delete(handle);
5993
+ if (!this._workerProxy) {
5994
+ await this._requireDecisionRuntime().freeDecisionHead(entry.handle);
5995
+ return;
5996
+ }
5997
+ try {
5998
+ await this._callWorker("freeDecisionHead", [entry.handle]);
5999
+ } catch (error) {
6000
+ this._throwIfOperationCancelled(error, "Decision head free was cancelled.");
6001
+ if (!this._shouldFallbackToMainThread(error)) {
6002
+ throw error;
6003
+ }
6004
+ await this._recoverDecisionWorker(error);
6005
+ }
6006
+ }
6007
  async tokenize(text, addSpecial = true) {
6008
  return this._runExclusive(
6009
  () => this._tokenizeUnlocked(text, addSpecial),
 
6280
  this._loadedMmProjUrl = null;
6281
  this._workerFallbackReason = null;
6282
  this._multimodalWorkerCpuMode = false;
6283
+ this._decisionHeads?.clear();
6284
  this._lifecycleState = "disposed";
6285
  }
6286
  }
webgpu_bridge/llama_webgpu_core.js CHANGED
The diff for this file is too large to render. See raw diff
 
webgpu_bridge/llama_webgpu_core.wasm CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:f643e79520ac97bc150db6806735b9b73a98b07eb1b2fa4146bb773944315c71
3
- size 8918014
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4c2e81f5c44808367aa3f484776e7e4faa9f3841511d6a7ad2a39e6ec063d4a9
3
+ size 9170142
webgpu_bridge/llama_webgpu_core_mem64.js CHANGED
The diff for this file is too large to render. See raw diff
 
webgpu_bridge/llama_webgpu_core_mem64.wasm CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:aaf399050af09af0c44b55ecf9d665e8f6e18df6f6deada3feab07677ddd7233
3
- size 9145549
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a6de570070c13c73d90666e903c4770f5eeb2d24be7fc630444de6d6609133a9
3
+ size 9410357
webgpu_bridge/manifest.json CHANGED
@@ -1,37 +1,37 @@
1
  {
2
  "artifacts": {
3
  "llama_webgpu_bridge.d.ts": {
4
- "sha256": "be584430457c76cf991c39ebfd19f771424f86f6304899840bf9e50f1b32cafc",
5
- "size_bytes": 6330
6
  },
7
  "llama_webgpu_bridge.js": {
8
- "sha256": "a704115fe87d3defff4a02c5a2b1d1bf0ab3bc1f00de3f40ed2c9b2d5983fd73",
9
- "size_bytes": 210601
10
  },
11
  "llama_webgpu_bridge_worker.js": {
12
  "sha256": "47bbfa0fe897e708455b9497e9aa41d2e94489c329300c33b12936fb3169deca",
13
  "size_bytes": 257
14
  },
15
  "llama_webgpu_core.js": {
16
- "sha256": "67bade52aad19471ee96a7180db691e1f6b4e87d4254adaa3e5d9a31f6206ed1",
17
- "size_bytes": 113847
18
  },
19
  "llama_webgpu_core.wasm": {
20
- "sha256": "f643e79520ac97bc150db6806735b9b73a98b07eb1b2fa4146bb773944315c71",
21
- "size_bytes": 8918014
22
  },
23
  "llama_webgpu_core_mem64.js": {
24
- "sha256": "6575880ad6a631b6a8f9aaaebb9a5c3f1cc2910f59700ce529d3de6077276337",
25
- "size_bytes": 130764
26
  },
27
  "llama_webgpu_core_mem64.wasm": {
28
- "sha256": "aaf399050af09af0c44b55ecf9d665e8f6e18df6f6deada3feab07677ddd7233",
29
- "size_bytes": 9145549
30
  }
31
  },
32
  "assets_repository": "leehack/llama-web-bridge-assets",
33
- "bridge_assets_tag": "v0.1.44",
34
- "bridge_commit": "89178be67c3c84300bc1b129182bd5bc5a8e21fc",
35
  "bridge_repository": "leehack/llama-web-bridge",
36
  "capabilities": {
37
  "memory64": true,
@@ -62,43 +62,43 @@
62
  "emscripten_version": "6.0.8",
63
  "files": {
64
  "llama_webgpu_bridge.d.ts": {
65
- "sha256": "be584430457c76cf991c39ebfd19f771424f86f6304899840bf9e50f1b32cafc",
66
- "size_bytes": 6330
67
  },
68
  "llama_webgpu_bridge.js": {
69
- "sha256": "a704115fe87d3defff4a02c5a2b1d1bf0ab3bc1f00de3f40ed2c9b2d5983fd73",
70
- "size_bytes": 210601
71
  },
72
  "llama_webgpu_bridge_worker.js": {
73
  "sha256": "47bbfa0fe897e708455b9497e9aa41d2e94489c329300c33b12936fb3169deca",
74
  "size_bytes": 257
75
  },
76
  "llama_webgpu_core.js": {
77
- "sha256": "67bade52aad19471ee96a7180db691e1f6b4e87d4254adaa3e5d9a31f6206ed1",
78
- "size_bytes": 113847
79
  },
80
  "llama_webgpu_core.wasm": {
81
- "sha256": "f643e79520ac97bc150db6806735b9b73a98b07eb1b2fa4146bb773944315c71",
82
- "size_bytes": 8918014
83
  },
84
  "llama_webgpu_core_mem64.js": {
85
- "sha256": "6575880ad6a631b6a8f9aaaebb9a5c3f1cc2910f59700ce529d3de6077276337",
86
- "size_bytes": 130764
87
  },
88
  "llama_webgpu_core_mem64.wasm": {
89
- "sha256": "aaf399050af09af0c44b55ecf9d665e8f6e18df6f6deada3feab07677ddd7233",
90
- "size_bytes": 9145549
91
  }
92
  },
93
- "github_run_id": "35075283754",
94
- "github_run_url": "https://github.com/leehack/llama-web-bridge/actions/runs/35075283754",
95
  "llama_cpp_commit": "b29c606e28a01b1bc8c1351026a0fa6e616bf6c4",
96
  "llama_cpp_tag": "v0.4.1",
97
  "native_commit": "a4ee6b9fa71127d6cdf625e26d82ca5ab7b1d102",
98
  "native_manifest_sha256": "d8dc86fcb55e566ee04aa9ed235716bd0e7a48cdaecb17822c098b074ec33d3e",
99
  "native_release_tag": "v0.4.1",
100
  "native_repository": "leehack/llamadart-native",
101
- "orchestrator_correlation_id": "auto-stable-v0.4.1-d8dc86fcb55e566e-build-89178be67c3c8430",
102
  "qualification_gates": {
103
  "multimodal": "passed",
104
  "speech_to_text": "required-automated-qualification",
@@ -107,9 +107,9 @@
107
  },
108
  "release_channel": "stable",
109
  "release_rebuild": 0,
110
- "release_tag": "v0.1.44",
111
  "schema_version": 2,
112
- "source_commit": "89178be67c3c84300bc1b129182bd5bc5a8e21fc",
113
  "source_repository": "leehack/llama-web-bridge",
114
  "unproven_capabilities": {
115
  "hardware_gpu_acceleration": "unavailable-on-hosted-runners",
 
1
  {
2
  "artifacts": {
3
  "llama_webgpu_bridge.d.ts": {
4
+ "sha256": "d8fa58ab587bb79c44dff40714fa8fa130da8ead160c8aa33f9254ed75055837",
5
+ "size_bytes": 7810
6
  },
7
  "llama_webgpu_bridge.js": {
8
+ "sha256": "eaa670759e559ca7ee7182fe8d5440872b6861aa6c3a5e8b7ec7f6e55c604254",
9
+ "size_bytes": 227520
10
  },
11
  "llama_webgpu_bridge_worker.js": {
12
  "sha256": "47bbfa0fe897e708455b9497e9aa41d2e94489c329300c33b12936fb3169deca",
13
  "size_bytes": 257
14
  },
15
  "llama_webgpu_core.js": {
16
+ "sha256": "7e0617766b459bd1d1e398705716730e472bdfc0147f54212a5eb113b75b8a43",
17
+ "size_bytes": 114678
18
  },
19
  "llama_webgpu_core.wasm": {
20
+ "sha256": "4c2e81f5c44808367aa3f484776e7e4faa9f3841511d6a7ad2a39e6ec063d4a9",
21
+ "size_bytes": 9170142
22
  },
23
  "llama_webgpu_core_mem64.js": {
24
+ "sha256": "3f9c7e8738588b043ba69688df836feefd1a95a211a281d9ae5ba6ac181f3bb2",
25
+ "size_bytes": 131595
26
  },
27
  "llama_webgpu_core_mem64.wasm": {
28
+ "sha256": "a6de570070c13c73d90666e903c4770f5eeb2d24be7fc630444de6d6609133a9",
29
+ "size_bytes": 9410357
30
  }
31
  },
32
  "assets_repository": "leehack/llama-web-bridge-assets",
33
+ "bridge_assets_tag": "v0.1.47",
34
+ "bridge_commit": "64ba8250871bf2472cc2064c6a00fff050783f02",
35
  "bridge_repository": "leehack/llama-web-bridge",
36
  "capabilities": {
37
  "memory64": true,
 
62
  "emscripten_version": "6.0.8",
63
  "files": {
64
  "llama_webgpu_bridge.d.ts": {
65
+ "sha256": "d8fa58ab587bb79c44dff40714fa8fa130da8ead160c8aa33f9254ed75055837",
66
+ "size_bytes": 7810
67
  },
68
  "llama_webgpu_bridge.js": {
69
+ "sha256": "eaa670759e559ca7ee7182fe8d5440872b6861aa6c3a5e8b7ec7f6e55c604254",
70
+ "size_bytes": 227520
71
  },
72
  "llama_webgpu_bridge_worker.js": {
73
  "sha256": "47bbfa0fe897e708455b9497e9aa41d2e94489c329300c33b12936fb3169deca",
74
  "size_bytes": 257
75
  },
76
  "llama_webgpu_core.js": {
77
+ "sha256": "7e0617766b459bd1d1e398705716730e472bdfc0147f54212a5eb113b75b8a43",
78
+ "size_bytes": 114678
79
  },
80
  "llama_webgpu_core.wasm": {
81
+ "sha256": "4c2e81f5c44808367aa3f484776e7e4faa9f3841511d6a7ad2a39e6ec063d4a9",
82
+ "size_bytes": 9170142
83
  },
84
  "llama_webgpu_core_mem64.js": {
85
+ "sha256": "3f9c7e8738588b043ba69688df836feefd1a95a211a281d9ae5ba6ac181f3bb2",
86
+ "size_bytes": 131595
87
  },
88
  "llama_webgpu_core_mem64.wasm": {
89
+ "sha256": "a6de570070c13c73d90666e903c4770f5eeb2d24be7fc630444de6d6609133a9",
90
+ "size_bytes": 9410357
91
  }
92
  },
93
+ "github_run_id": "35904377401",
94
+ "github_run_url": "https://github.com/leehack/llama-web-bridge/actions/runs/35904377401",
95
  "llama_cpp_commit": "b29c606e28a01b1bc8c1351026a0fa6e616bf6c4",
96
  "llama_cpp_tag": "v0.4.1",
97
  "native_commit": "a4ee6b9fa71127d6cdf625e26d82ca5ab7b1d102",
98
  "native_manifest_sha256": "d8dc86fcb55e566ee04aa9ed235716bd0e7a48cdaecb17822c098b074ec33d3e",
99
  "native_release_tag": "v0.4.1",
100
  "native_repository": "leehack/llamadart-native",
101
+ "orchestrator_correlation_id": "auto-stable-v0.4.1-d8dc86fcb55e566e-build-64ba8250871bf247",
102
  "qualification_gates": {
103
  "multimodal": "passed",
104
  "speech_to_text": "required-automated-qualification",
 
107
  },
108
  "release_channel": "stable",
109
  "release_rebuild": 0,
110
+ "release_tag": "v0.1.47",
111
  "schema_version": 2,
112
+ "source_commit": "64ba8250871bf2472cc2064c6a00fff050783f02",
113
  "source_repository": "leehack/llama-web-bridge",
114
  "unproven_capabilities": {
115
  "hardware_gpu_acceleration": "unavailable-on-hosted-runners",
webgpu_bridge/sha256sums.txt CHANGED
@@ -1,7 +1,7 @@
1
- a704115fe87d3defff4a02c5a2b1d1bf0ab3bc1f00de3f40ed2c9b2d5983fd73 llama_webgpu_bridge.js
2
- 67bade52aad19471ee96a7180db691e1f6b4e87d4254adaa3e5d9a31f6206ed1 llama_webgpu_core.js
3
- f643e79520ac97bc150db6806735b9b73a98b07eb1b2fa4146bb773944315c71 llama_webgpu_core.wasm
4
  47bbfa0fe897e708455b9497e9aa41d2e94489c329300c33b12936fb3169deca llama_webgpu_bridge_worker.js
5
- be584430457c76cf991c39ebfd19f771424f86f6304899840bf9e50f1b32cafc llama_webgpu_bridge.d.ts
6
- 6575880ad6a631b6a8f9aaaebb9a5c3f1cc2910f59700ce529d3de6077276337 llama_webgpu_core_mem64.js
7
- aaf399050af09af0c44b55ecf9d665e8f6e18df6f6deada3feab07677ddd7233 llama_webgpu_core_mem64.wasm
 
1
+ eaa670759e559ca7ee7182fe8d5440872b6861aa6c3a5e8b7ec7f6e55c604254 llama_webgpu_bridge.js
2
+ 7e0617766b459bd1d1e398705716730e472bdfc0147f54212a5eb113b75b8a43 llama_webgpu_core.js
3
+ 4c2e81f5c44808367aa3f484776e7e4faa9f3841511d6a7ad2a39e6ec063d4a9 llama_webgpu_core.wasm
4
  47bbfa0fe897e708455b9497e9aa41d2e94489c329300c33b12936fb3169deca llama_webgpu_bridge_worker.js
5
+ d8fa58ab587bb79c44dff40714fa8fa130da8ead160c8aa33f9254ed75055837 llama_webgpu_bridge.d.ts
6
+ 3f9c7e8738588b043ba69688df836feefd1a95a211a281d9ae5ba6ac181f3bb2 llama_webgpu_core_mem64.js
7
+ a6de570070c13c73d90666e903c4770f5eeb2d24be7fc630444de6d6609133a9 llama_webgpu_core_mem64.wasm