@bendyline/gezel-service 1.0.4 → 1.0.5

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.
Files changed (56) hide show
  1. package/dist/bin/gezeld.js +295 -167
  2. package/dist/handboek-content/whats-new/1.26226.md +1 -1
  3. package/dist/index.d.ts +19 -9
  4. package/dist/index.js +295 -167
  5. package/dist/ui/assets/{TerminalCodeEditor-BuMcfTS4.js → TerminalCodeEditor-C_Mvaxqz.js} +2 -2
  6. package/dist/ui/assets/{_.contribution-CZO2XAKt.js → _.contribution-fOcpgyNy.js} +1 -1
  7. package/dist/ui/assets/{cpp.contribution-BJzhk0Zj.js → cpp.contribution-Cx5HvoW7.js} +1 -1
  8. package/dist/ui/assets/{csharp.contribution-BR9K2qKj.js → csharp.contribution-DMuCSvzf.js} +1 -1
  9. package/dist/ui/assets/{css.contribution-CfkVmdah.js → css.contribution-BPXcRoVK.js} +1 -1
  10. package/dist/ui/assets/{cssMode-MMeGUmV2.js → cssMode-BHAnHChA.js} +1 -1
  11. package/dist/ui/assets/{dist-CFOmf7nD.js → dist-DRDFuw7G.js} +1 -1
  12. package/dist/ui/assets/dist-DYn91eSO.js +2 -0
  13. package/dist/ui/assets/{dockerfile.contribution-IZMl57B5.js → dockerfile.contribution-DQAHazBI.js} +1 -1
  14. package/dist/ui/assets/{go.contribution-BxCBwhZs.js → go.contribution-Jq5pYI7r.js} +1 -1
  15. package/dist/ui/assets/{handlebars-CreIkams.js → handlebars-BWC7ZXbe.js} +1 -1
  16. package/dist/ui/assets/{handlebars.contribution-BGlyL-dm.js → handlebars.contribution-BSmxDPeT.js} +2 -2
  17. package/dist/ui/assets/{html-BSrz1IKi.js → html-BzC9B_Os.js} +1 -1
  18. package/dist/ui/assets/{html.contribution-CucOMFQ_.js → html.contribution-CEvtdKHG.js} +2 -2
  19. package/dist/ui/assets/{htmlMode-DRG7XY5Z.js → htmlMode-1qtmM5J4.js} +1 -1
  20. package/dist/ui/assets/{index-Bqu-32S3.js → index-JGn32C5f.js} +7 -7
  21. package/dist/ui/assets/{ini.contribution-CGX5OdXM.js → ini.contribution-BQpzdQzE.js} +1 -1
  22. package/dist/ui/assets/{java.contribution-CVhfJ_us.js → java.contribution-r3T-8LYE.js} +1 -1
  23. package/dist/ui/assets/{javascript-QelFp9t5.js → javascript-DlipM3VT.js} +1 -1
  24. package/dist/ui/assets/{javascript.contribution--no0ijCu.js → javascript.contribution-D4MU3K0o.js} +2 -2
  25. package/dist/ui/assets/{jsonMode-T4Ss3lDu.js → jsonMode-DSXTaEG9.js} +1 -1
  26. package/dist/ui/assets/{kotlin.contribution-DxFbGDYA.js → kotlin.contribution-NI_YvQPr.js} +1 -1
  27. package/dist/ui/assets/{less.contribution-g9R8XRZf.js → less.contribution-BDz7g6GS.js} +1 -1
  28. package/dist/ui/assets/{lua.contribution-YqDsEy8Z.js → lua.contribution-Cr_f17YF.js} +1 -1
  29. package/dist/ui/assets/{markdown.contribution-DboXnPnx.js → markdown.contribution-CeJFrLN_.js} +1 -1
  30. package/dist/ui/assets/{monaco-BdFw56DI.js → monaco-Bv9TxWl_.js} +3 -3
  31. package/dist/ui/assets/{monaco-base-DrP3D13F.js → monaco-base-DD1Wr24S.js} +1 -1
  32. package/dist/ui/assets/{monaco-setup-QyF22y9h.js → monaco-setup-CSa3_fbr.js} +1 -1
  33. package/dist/ui/assets/{monaco.contribution-CMzPFHtO.js → monaco.contribution-DKCJArGP.js} +2 -2
  34. package/dist/ui/assets/{monaco.contribution-XEpc63ty.js → monaco.contribution-QFH9z5g8.js} +2 -2
  35. package/dist/ui/assets/{monaco.contribution-BkqIxESv.js → monaco.contribution-ZD-wInG3.js} +2 -2
  36. package/dist/ui/assets/{monaco.contribution-FA_ESP-W.js → monaco.contribution-tTvEzZ5l.js} +2 -2
  37. package/dist/ui/assets/{php.contribution-rnpik0Kk.js → php.contribution-B310cs3S.js} +1 -1
  38. package/dist/ui/assets/{python-CF7X5t9Q.js → python-CcCNDnkj.js} +1 -1
  39. package/dist/ui/assets/{python.contribution-CyJGCfSq.js → python.contribution-ZHL594qQ.js} +2 -2
  40. package/dist/ui/assets/{ruby.contribution-4ZyPGu2E.js → ruby.contribution-CRsX2xPw.js} +1 -1
  41. package/dist/ui/assets/{rust.contribution-Cl_B3X2G.js → rust.contribution-CfwWiQxD.js} +1 -1
  42. package/dist/ui/assets/{scss.contribution-BO02gVLZ.js → scss.contribution-CJaLNKeq.js} +1 -1
  43. package/dist/ui/assets/{shell.contribution-Dn9Y0uHs.js → shell.contribution-DLPinQHD.js} +1 -1
  44. package/dist/ui/assets/{sql.contribution-Bog_5Rc8.js → sql.contribution-DsZSLfVg.js} +1 -1
  45. package/dist/ui/assets/{swift.contribution-CfiAr7AX.js → swift.contribution-DFBOOFKs.js} +1 -1
  46. package/dist/ui/assets/{terminal-monaco-setup-B-EnkGiy.js → terminal-monaco-setup-B8Xv2NV9.js} +1 -1
  47. package/dist/ui/assets/{tsMode-B2WuLuPL.js → tsMode-DqT2Dz4k.js} +1 -1
  48. package/dist/ui/assets/{typescript-Bv_J1tKT.js → typescript-_R5MS0Lp.js} +1 -1
  49. package/dist/ui/assets/{typescript.contribution-CM0XQCYi.js → typescript.contribution-CHnXQvfG.js} +2 -2
  50. package/dist/ui/assets/{xml-DMV-f4tm.js → xml-CQVIKNxb.js} +1 -1
  51. package/dist/ui/assets/{xml.contribution-QqmOB9gT.js → xml.contribution-HY4GvlWC.js} +2 -2
  52. package/dist/ui/assets/{yaml-Bb6mZXY5.js → yaml-Nt3uLkWC.js} +1 -1
  53. package/dist/ui/assets/{yaml.contribution-DCDnWhHR.js → yaml.contribution-C7dllTyY.js} +2 -2
  54. package/dist/ui/index.html +3 -3
  55. package/package.json +10 -9
  56. package/dist/ui/assets/dist-8uH4DcHx.js +0 -2
package/dist/index.js CHANGED
@@ -9559,7 +9559,7 @@ __export(bootstrap_exports, {
9559
9559
  reconcileSystemToolsetFromDisk: () => reconcileSystemToolsetFromDisk,
9560
9560
  runSystemBootstrap: () => runSystemBootstrap
9561
9561
  });
9562
- import { createHash as createHash38, randomUUID as randomUUID25 } from "crypto";
9562
+ import { createHash as createHash39, randomUUID as randomUUID25 } from "crypto";
9563
9563
  import { existsSync as existsSync23 } from "fs";
9564
9564
  import { mkdir as mkdir51, open as open5, readFile as readFile62, rm as rm34, writeFile as writeFile23 } from "fs/promises";
9565
9565
  import { join as join85 } from "path";
@@ -9955,7 +9955,7 @@ async function downloadWithIntegrity(url, dest, integrity, opts = {}) {
9955
9955
  if (!["sha256", "sha384", "sha512"].includes(algo)) {
9956
9956
  throw new Error(`unsupported integrity algorithm: ${algo}`);
9957
9957
  }
9958
- const hash = createHash38(algo);
9958
+ const hash = createHash39(algo);
9959
9959
  const request = await fetchBounded(url, DOWNLOAD_TIMEOUT_MS, opts.signal);
9960
9960
  const handle = await open5(dest, "wx", 384);
9961
9961
  try {
@@ -11749,7 +11749,7 @@ var ChatEventBus = class {
11749
11749
  };
11750
11750
 
11751
11751
  // src/chat/manager.ts
11752
- import { randomUUID as randomUUID7 } from "crypto";
11752
+ import { createHash as createHash12, randomUUID as randomUUID7 } from "crypto";
11753
11753
  import { createRequire } from "module";
11754
11754
  import { join as join28 } from "path";
11755
11755
  import {
@@ -27065,7 +27065,12 @@ var LlamaCppSession = class extends StreamingSessionBase {
27065
27065
  if (toolCalls.length > 0) {
27066
27066
  const normalized2 = normalizeMalformedStructuredToolCalls(
27067
27067
  toolCalls,
27068
- collectKnownToolNames()
27068
+ collectKnownToolNames(),
27069
+ // A malformed write at the output ceiling is not repairable: the
27070
+ // missing JSON tail may also be missing file bytes. Executing the
27071
+ // loose prefix can silently replace a complete file with a
27072
+ // truncated one. Valid, fully parseable calls remain eligible.
27073
+ finishReason !== "length"
27069
27074
  );
27070
27075
  toolCalls = normalized2.toolCalls;
27071
27076
  malformedStructuredCallIds = new Set(normalized2.sanitizedIds);
@@ -27942,7 +27947,7 @@ var ToolCallAccumulator = class {
27942
27947
  }));
27943
27948
  }
27944
27949
  };
27945
- function normalizeMalformedStructuredToolCalls(toolCalls, knownToolNames) {
27950
+ function normalizeMalformedStructuredToolCalls(toolCalls, knownToolNames, allowMalformedWriteRepair = true) {
27946
27951
  const repaired = [];
27947
27952
  const sanitized = [];
27948
27953
  const sanitizedIds = [];
@@ -27953,11 +27958,7 @@ function normalizeMalformedStructuredToolCalls(toolCalls, knownToolNames) {
27953
27958
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return call;
27954
27959
  } catch {
27955
27960
  }
27956
- const repairedArgs = tryRepairMalformedWriteToolArguments(
27957
- call.function.name,
27958
- raw,
27959
- knownToolNames
27960
- );
27961
+ const repairedArgs = allowMalformedWriteRepair ? tryRepairMalformedWriteToolArguments(call.function.name, raw, knownToolNames) : null;
27961
27962
  if (repairedArgs) {
27962
27963
  repaired.push({
27963
27964
  name: call.function.name,
@@ -32119,6 +32120,7 @@ function buildLlamaCppEngineArgs(input) {
32119
32120
  ggufHasMtp,
32120
32121
  installedDraftModelPath,
32121
32122
  reasoningFormat,
32123
+ reasoningPreserve,
32122
32124
  architecture,
32123
32125
  modelId,
32124
32126
  swaFullAutoFits
@@ -32166,6 +32168,7 @@ function buildLlamaCppEngineArgs(input) {
32166
32168
  if (typeof nMax === "number") args.push("--spec-draft-n-max", String(nMax));
32167
32169
  }
32168
32170
  if (reasoningFormat) args.push("--reasoning-format", reasoningFormat);
32171
+ if (reasoningPreserve) args.push("--reasoning-preserve");
32169
32172
  if (config.llamaCppExtraArgs) {
32170
32173
  for (const [rawKey, value] of Object.entries(config.llamaCppExtraArgs)) {
32171
32174
  if (value === false) continue;
@@ -32486,6 +32489,31 @@ function fitsSwaFullInFastMemory(input) {
32486
32489
  return Number.isFinite(required) && Number.isFinite(available) && required <= available;
32487
32490
  }
32488
32491
 
32492
+ // src/providers/llama-cpp/reasoning-launch.ts
32493
+ var POSITIVE_INTEGER = /^[1-9]\d*$/;
32494
+ function parseReasoningPreserveEnv(raw) {
32495
+ const normalized2 = raw?.trim().toLowerCase();
32496
+ return normalized2 === "1" || normalized2 === "true";
32497
+ }
32498
+ function parseReasoningBudgetEnv(raw) {
32499
+ const normalized2 = raw?.trim();
32500
+ if (!normalized2) return void 0;
32501
+ if (!POSITIVE_INTEGER.test(normalized2)) {
32502
+ throw new Error("GEZEL_LLAMA_REASONING_BUDGET_TOKENS must be a positive integer");
32503
+ }
32504
+ const parsed = Number(normalized2);
32505
+ if (!Number.isSafeInteger(parsed)) {
32506
+ throw new Error("GEZEL_LLAMA_REASONING_BUDGET_TOKENS exceeds the safe integer range");
32507
+ }
32508
+ return parsed;
32509
+ }
32510
+ function reasoningLaunchOverridesFromEnv(env = process.env) {
32511
+ return {
32512
+ preserve: parseReasoningPreserveEnv(env.GEZEL_LLAMA_REASONING_PRESERVE),
32513
+ budgetTokens: parseReasoningBudgetEnv(env.GEZEL_LLAMA_REASONING_BUDGET_TOKENS)
32514
+ };
32515
+ }
32516
+
32489
32517
  // src/providers/llama-cpp/spec-draft.ts
32490
32518
  async function resolveSpecDraft(input) {
32491
32519
  const { perModel, configSpecType, configDraftModelPath, resolveDraftPath } = input;
@@ -32544,6 +32572,8 @@ async function buildLlamaCppProvider(opts) {
32544
32572
  const { config, affinity, home } = opts;
32545
32573
  const externalBaseUrl = opts.modelOverride ? void 0 : process.env.GEZEL_LLAMA_SERVER_URL ?? config.llamaCppBaseUrl;
32546
32574
  const binary = process.env.GEZEL_LLAMA_SERVER_BIN;
32575
+ const reasoningLaunchOverrides = reasoningLaunchOverridesFromEnv();
32576
+ const reasoningPreserve = reasoningLaunchOverrides.preserve;
32547
32577
  const defaultModelId = opts.modelOverride?.modelId ?? config.defaultModel?.["llama-cpp"];
32548
32578
  const configuredSlots = config.providerConcurrency?.["llama-cpp"];
32549
32579
  const envNumCtx = (() => {
@@ -32566,6 +32596,7 @@ async function buildLlamaCppProvider(opts) {
32566
32596
  // rate for its own default engine — throughput was reachable only by
32567
32597
  // scraping stdout from the eval harness.
32568
32598
  includeUsageInStream: true,
32599
+ replayReasoningContent: reasoningPreserve,
32569
32600
  // External-baseUrl default; the supervised path overrides this with the
32570
32601
  // auto-sized `slots` computed below (after the model resolves).
32571
32602
  concurrency: configuredSlots ?? 2,
@@ -32756,10 +32787,12 @@ async function buildLlamaCppProvider(opts) {
32756
32787
  const slotSavePath = replicaSuffix ? join18(llamaCacheRoot, llamaFingerprint, replicaSuffix) : join18(llamaCacheRoot, llamaFingerprint);
32757
32788
  await mkdirAsync(slotSavePath, { recursive: true }).catch(() => {
32758
32789
  });
32759
- const reasoningBudgetTokens = opts.catalog ? await resolveCatalogReasoningBudget(
32790
+ const catalogReasoningBudgetTokens = opts.catalog ? await resolveCatalogReasoningBudget(
32760
32791
  opts.catalog,
32761
32792
  opts.modelOverride?.modelId ?? defaultModelId
32762
32793
  ) : void 0;
32794
+ const reasoningBudgetTokens = reasoningLaunchOverrides.budgetTokens ?? catalogReasoningBudgetTokens;
32795
+ const reasoningBudgetSource = reasoningLaunchOverrides.budgetTokens !== void 0 ? "env" : catalogReasoningBudgetTokens !== void 0 ? "catalog" : "unbounded";
32763
32796
  const specDraft = await resolveSpecDraft({
32764
32797
  perModel: manifestEngineConfig,
32765
32798
  configSpecType: config.llamaCppSpecType,
@@ -33149,6 +33182,7 @@ async function buildLlamaCppProvider(opts) {
33149
33182
  // disables llama-server's chat-template output parsing so mangled
33150
33183
  // model output reaches `delta.content` for provider-side salvage.
33151
33184
  reasoningFormat: process.env.GEZEL_LLAMA_REASONING_FORMAT?.trim() || void 0,
33185
+ reasoningPreserve,
33152
33186
  architecture: modelCatalogInfo?.architecture,
33153
33187
  modelId: defaultModelId ?? void 0,
33154
33188
  swaFullAutoFits
@@ -33257,6 +33291,9 @@ async function buildLlamaCppProvider(opts) {
33257
33291
  batchSize: lastArgValue(resolvedAdvancedArgs, "--batch-size") ?? "default",
33258
33292
  ubatchSize: lastArgValue(resolvedAdvancedArgs, "--ubatch-size") ?? "default",
33259
33293
  flashAttention: lastArgValue(resolvedAdvancedArgs, "--flash-attn") ?? "default",
33294
+ reasoningBudgetTokens: reasoningBudgetTokens ?? "unbounded",
33295
+ reasoningBudgetSource,
33296
+ reasoningPreserve,
33260
33297
  cudaGraphs: process.env.GGML_CUDA_DISABLE_GRAPHS ? "disabled-by-env" : "default"
33261
33298
  },
33262
33299
  env: {
@@ -36045,14 +36082,14 @@ async function buildMlxProvider(opts) {
36045
36082
  const cacheBudgetMb = Math.min(config.cacheBudgetMb?.mlx ?? ramAwareDefaultMb, mlxKvHeadroomMb);
36046
36083
  const mlxReplicaSuffix = opts.modelOverride && opts.modelOverride.replicaIdx > 0 ? `replica-${opts.modelOverride.replicaIdx}` : "";
36047
36084
  const cacheRoot = mlxReplicaSuffix ? join21(store.homePath, "engines", "mlx", "cache", mlxReplicaSuffix) : join21(store.homePath, "engines", "mlx", "cache");
36048
- const { createHash: createHash47 } = await import("crypto");
36085
+ const { createHash: createHash48 } = await import("crypto");
36049
36086
  const fingerprintInput = [
36050
36087
  modelCatalogInfo?.id ?? defaultModelId ?? modelDir,
36051
36088
  modelCatalogInfo?.catalogVersion ?? "",
36052
36089
  modelCatalogInfo?.installedAt ?? "",
36053
36090
  modelDir
36054
36091
  ].join("::");
36055
- const modelFingerprint = createHash47("sha256").update(fingerprintInput, "utf8").digest("hex").slice(0, 24);
36092
+ const modelFingerprint = createHash48("sha256").update(fingerprintInput, "utf8").digest("hex").slice(0, 24);
36056
36093
  const diskCacheBudgetMb = config.mlxDiskCacheBudgetMb ?? 8192;
36057
36094
  const mlxIdleMs = config.localEngineIdleTimeoutMs ?? DEFAULT_LOCAL_ENGINE_IDLE_TIMEOUT_MS3;
36058
36095
  const mlxFreezeMs = Math.floor(mlxIdleMs / 2);
@@ -46650,10 +46687,12 @@ var ChatManager = class {
46650
46687
  */
46651
46688
  afterSessionIdle = /* @__PURE__ */ new Map();
46652
46689
  /**
46653
- * One live async file handoff per sender/target/project/path. Models can
46690
+ * One live async file handoff per sender/target/project/path/intent. Models can
46654
46691
  * emit the same `message_gezel` call several times while the sender turn
46655
46692
  * is still active; joining that work prevents a parked-send burst from
46656
- * replaying the same assignment into the recipient session.
46693
+ * replaying the same assignment into the recipient session. A later
46694
+ * validator repair for a file that was originally missing is distinct work
46695
+ * and must never join the older create request.
46657
46696
  */
46658
46697
  inflightFileHandoffs = /* @__PURE__ */ new Map();
46659
46698
  /** Set once {@link shutdown} starts so deferred watchdogs don't fire into a tearing-down manager. */
@@ -48533,7 +48572,8 @@ ${stepArc}
48533
48572
  args.fromSessionId ?? args.fromGezelId,
48534
48573
  target.id,
48535
48574
  projectId,
48536
- normalizeExpectedDeliverablePath(requestedFilePath)
48575
+ normalizeExpectedDeliverablePath(requestedFilePath),
48576
+ fileHandoffIntentKey(args.text)
48537
48577
  ].join("\0") : null;
48538
48578
  const pendingHandoff = fileHandoffKey ? this.inflightFileHandoffs.get(fileHandoffKey) : void 0;
48539
48579
  if (pendingHandoff) return { ...pendingHandoff, deduplicated: true };
@@ -48574,7 +48614,7 @@ ${stepArc}
48574
48614
  const seed = `[Message from ${fromName}]: ${args.text}${deliverableAnnotation}`;
48575
48615
  const failureNotice = { sent: false };
48576
48616
  const resolvedFromSessionId = args.fromSessionId ?? (target.id === args.fromGezelId ? null : await this.ensureOrCreateSession({ gezelId: args.fromGezelId, projectId }).then((s) => s.id).catch(() => null));
48577
- if (resolvedFromSessionId && resolvedFromSessionId !== session.id) {
48617
+ if (!args.suppressReply && resolvedFromSessionId && resolvedFromSessionId !== session.id) {
48578
48618
  this.attachReplyListener({
48579
48619
  targetSessionId: session.id,
48580
48620
  fromSessionId: resolvedFromSessionId,
@@ -50017,20 +50057,36 @@ ${peek.userText}`;
50017
50057
  return this.runFixedFunctionSend(sessionId2, userText, opts);
50018
50058
  }
50019
50059
  }
50060
+ const preflightScope = ffRecord ? {
50061
+ sessionId: sessionId2,
50062
+ gezelId: ffRecord.gezelId,
50063
+ projectId: ffRecord.projectId
50064
+ } : void 0;
50065
+ const coldStartPending = preflightScope && !this.states.get(sessionId2)?.session;
50066
+ if (preflightScope && coldStartPending) {
50067
+ this.events.publish(preflightScope, {
50068
+ type: "user_message_pending",
50069
+ preview: userText.length > 160 ? `${userText.slice(0, 157)}\u2026` : userText
50070
+ });
50071
+ }
50020
50072
  const fail2 = (err) => {
50021
50073
  const message = err instanceof Error ? err.message : String(err);
50022
50074
  log52.error("error:", message);
50075
+ const publish = (event) => {
50076
+ if (preflightScope) this.events.publish(preflightScope, event);
50077
+ else this.events.publishSessionOnly(sessionId2, event);
50078
+ };
50023
50079
  if (inflightTurn.cancelled) {
50024
- this.events.publishSessionOnly(sessionId2, { type: "cancelled" });
50080
+ publish({ type: "cancelled" });
50025
50081
  } else {
50026
50082
  const detail = describeTurnError(err);
50027
- this.events.publishSessionOnly(sessionId2, {
50083
+ publish({
50028
50084
  type: "error",
50029
50085
  error: redactCredentials4(message),
50030
50086
  ...detail ? { errorDetail: detail } : {}
50031
50087
  });
50032
50088
  }
50033
- this.events.publishSessionOnly(sessionId2, { type: "done" });
50089
+ publish({ type: "done" });
50034
50090
  throw err;
50035
50091
  };
50036
50092
  if (ffRecord) {
@@ -56347,6 +56403,14 @@ function messageExpressesModifyIntent(text) {
56347
56403
  )
56348
56404
  );
56349
56405
  }
56406
+ function fileHandoffIntentKey(text) {
56407
+ const repair = messageExpressesModifyIntent(text) || /\[scenario check\]|\b(?:specific failure|signals? that (?:didn't|did not) fire|success criteria (?:aren't|are not) met|repeat miss|gate_full_rewrite|rejected)\b/i.test(
56408
+ text
56409
+ );
56410
+ if (!repair) return "create";
56411
+ const normalized2 = text.toLowerCase().replace(/\s+/g, " ").trim();
56412
+ return `repair:${createHash12("sha256").update(normalized2).digest("hex").slice(0, 16)}`;
56413
+ }
56350
56414
  function isSubstantiveExistingWorkspaceFile(filePath2, content) {
56351
56415
  const trimmed = content.trim();
56352
56416
  if (!trimmed) return false;
@@ -56843,7 +56907,7 @@ function growthSignature(gezel) {
56843
56907
 
56844
56908
  // src/codex-setup/manager.ts
56845
56909
  init_atomic();
56846
- import { createHash as createHash12 } from "crypto";
56910
+ import { createHash as createHash13 } from "crypto";
56847
56911
  import { realpathSync as realpathSync2 } from "fs";
56848
56912
  import { chmod as chmod4, mkdir as mkdir15, readFile as readFile16, rm as rm6 } from "fs/promises";
56849
56913
  import { homedir as homedir3 } from "os";
@@ -57594,7 +57658,7 @@ function canonicalPath(path2) {
57594
57658
  }
57595
57659
  }
57596
57660
  function sha256(value) {
57597
- return createHash12("sha256").update(value).digest("hex");
57661
+ return createHash13("sha256").update(value).digest("hex");
57598
57662
  }
57599
57663
  function catalogModelFor(model) {
57600
57664
  const contextWindow = model.contextWindow ?? 32768;
@@ -58019,7 +58083,7 @@ init_mcp_bridge();
58019
58083
 
58020
58084
  // src/connectors/writer.ts
58021
58085
  init_atomic();
58022
- import { createHash as createHash13 } from "crypto";
58086
+ import { createHash as createHash14 } from "crypto";
58023
58087
  import { mkdir as mkdir16, readFile as readFile17, readdir as readdir9, rm as rm7, stat as stat11 } from "fs/promises";
58024
58088
  import { basename as basename7, join as join30 } from "path";
58025
58089
  import { projectLocalQuarantineDir } from "@bendyline/gezel/paths";
@@ -58292,7 +58356,7 @@ var StaticContentScanner = class {
58292
58356
  var contentScanner = new StaticContentScanner();
58293
58357
 
58294
58358
  // src/connectors/writer.ts
58295
- var sha8 = (s) => createHash13("sha256").update(s).digest("hex").slice(0, 8);
58359
+ var sha8 = (s) => createHash14("sha256").update(s).digest("hex").slice(0, 8);
58296
58360
  function slug(input, max = 48) {
58297
58361
  const s = input.normalize("NFKD").replace(/[^\x20-\x7E]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, max).replace(/-+$/g, "");
58298
58362
  return s || "x";
@@ -58309,7 +58373,7 @@ function contentHash(record) {
58309
58373
  const attachments = (record.attachments ?? []).map((attachment) => ({
58310
58374
  filename: attachment.filename,
58311
58375
  size: attachment.size ?? attachment.content?.byteLength ?? 0,
58312
- sha256: attachment.sha256 ?? createHash13("sha256").update(attachment.content).digest("hex")
58376
+ sha256: attachment.sha256 ?? createHash14("sha256").update(attachment.content).digest("hex")
58313
58377
  }));
58314
58378
  return sha8(
58315
58379
  `${JSON.stringify(sortedFrontmatter)}
@@ -59380,10 +59444,10 @@ var SpectralConnectorAdapter = class {
59380
59444
  };
59381
59445
 
59382
59446
  // src/connectors/oauth.ts
59383
- import { createHash as createHash14, randomBytes as randomBytes3 } from "crypto";
59447
+ import { createHash as createHash15, randomBytes as randomBytes3 } from "crypto";
59384
59448
  function createPkce() {
59385
59449
  const verifier = randomBytes3(32).toString("base64url");
59386
- const challenge = createHash14("sha256").update(verifier).digest("base64url");
59450
+ const challenge = createHash15("sha256").update(verifier).digest("base64url");
59387
59451
  return { verifier, challenge };
59388
59452
  }
59389
59453
  function randomState() {
@@ -64068,7 +64132,7 @@ function registerGitHubPullsAdapters(runtime) {
64068
64132
  }
64069
64133
 
64070
64134
  // src/connectors/natives/github-releases.ts
64071
- import { createHash as createHash15 } from "crypto";
64135
+ import { createHash as createHash16 } from "crypto";
64072
64136
  import { mkdir as mkdir21, mkdtemp as mkdtemp3, open as open2, rm as rm13 } from "fs/promises";
64073
64137
  import { tmpdir as tmpdir3 } from "os";
64074
64138
  import { basename as basename8, join as join35 } from "path";
@@ -64261,7 +64325,7 @@ var GitHubReleasesAdapter = class {
64261
64325
  }
64262
64326
  }
64263
64327
  this.releases = releases;
64264
- this.fingerprint = createHash15("sha256").update(JSON.stringify(releases)).digest("hex");
64328
+ this.fingerprint = createHash16("sha256").update(JSON.stringify(releases)).digest("hex");
64265
64329
  }
64266
64330
  apiHeaders(accept) {
64267
64331
  return {
@@ -64324,7 +64388,7 @@ var GitHubReleasesAdapter = class {
64324
64388
  };
64325
64389
  async function streamResponseToFile(response, path2) {
64326
64390
  const handle = await open2(path2, "wx");
64327
- const hash = createHash15("sha256");
64391
+ const hash = createHash16("sha256");
64328
64392
  let size = 0;
64329
64393
  try {
64330
64394
  for await (const raw of response.body) {
@@ -66704,7 +66768,7 @@ var DebugFlag = class {
66704
66768
 
66705
66769
  // src/digest/generator.ts
66706
66770
  init_atomic();
66707
- import { createHash as createHash16 } from "crypto";
66771
+ import { createHash as createHash17 } from "crypto";
66708
66772
  import { readFile as readFile25 } from "fs/promises";
66709
66773
  import { join as join40 } from "path";
66710
66774
  import {
@@ -69853,7 +69917,7 @@ var ProjectDigestGenerator = class {
69853
69917
  if (commits.length === 0 && sessions.length === 0 && events.length < MIN_EVENTS_FOR_DIGEST) {
69854
69918
  return false;
69855
69919
  }
69856
- const inputHash = createHash16("sha256").update(
69920
+ const inputHash = createHash17("sha256").update(
69857
69921
  [
69858
69922
  week,
69859
69923
  ...commits,
@@ -70010,7 +70074,7 @@ function describe4(err) {
70010
70074
  }
70011
70075
 
70012
70076
  // src/engines/electron-native-reuse.ts
70013
- import { createHash as createHash17 } from "crypto";
70077
+ import { createHash as createHash18 } from "crypto";
70014
70078
  import { createReadStream as createReadStream3 } from "fs";
70015
70079
  import { lstat as lstat2, readdir as readdir13, readlink } from "fs/promises";
70016
70080
  import { basename as basename11, join as join41, posix, relative as relative5, resolve as resolve8, sep as sep5 } from "path";
@@ -71630,7 +71694,7 @@ function enclosingMacApp(path2) {
71630
71694
  var HASH_READ_BUFFER_BYTES = 16 * 1024 * 1024;
71631
71695
  function sha256File2(path2) {
71632
71696
  return new Promise((resolveHash, reject) => {
71633
- const hash = createHash17("sha256");
71697
+ const hash = createHash18("sha256");
71634
71698
  const stream = createReadStream3(path2, { highWaterMark: HASH_READ_BUFFER_BYTES });
71635
71699
  stream.on("data", (chunk2) => hash.update(chunk2));
71636
71700
  stream.on("error", reject);
@@ -71642,7 +71706,7 @@ function sha256File2(path2) {
71642
71706
  import { createLogger as createLogger69 } from "@bendyline/gezel";
71643
71707
 
71644
71708
  // src/engines/resolver.ts
71645
- import { createHash as createHash18 } from "crypto";
71709
+ import { createHash as createHash19 } from "crypto";
71646
71710
  import { createReadStream as createReadStream4, existsSync as existsSync7 } from "fs";
71647
71711
  import { chmod as chmod5, mkdir as mkdir24, readFile as readFile26, rename as rename7, rm as rm16, writeFile as writeFile9 } from "fs/promises";
71648
71712
  import { join as join42 } from "path";
@@ -71766,7 +71830,7 @@ async function* resolveEngine(opts) {
71766
71830
  );
71767
71831
  }
71768
71832
  const sumsBytes = await ghBytes(sumsAsset.url, baseFetch, token);
71769
- const sumsDigest = createHash18("sha256").update(sumsBytes).digest("hex");
71833
+ const sumsDigest = createHash19("sha256").update(sumsBytes).digest("hex");
71770
71834
  if (!unpinned && sumsDigest !== expectedDigest) {
71771
71835
  yield* fail(
71772
71836
  `SHA256SUMS digest mismatch for ${tag}: this build pins ${expectedDigest.slice(0, 16)}\u2026 but the release served ${sumsDigest.slice(0, 16)}\u2026. Refusing \u2014 the release may have been tampered with or re-cut.`
@@ -72016,7 +72080,7 @@ function parseSums(text) {
72016
72080
  }
72017
72081
  var HASH_READ_BUFFER_BYTES2 = 16 * 1024 * 1024;
72018
72082
  async function sha256File3(path2) {
72019
- const hash = createHash18("sha256");
72083
+ const hash = createHash19("sha256");
72020
72084
  await new Promise((resolve18, reject) => {
72021
72085
  const stream = createReadStream4(path2, { highWaterMark: HASH_READ_BUFFER_BYTES2 });
72022
72086
  stream.on("data", (chunk2) => hash.update(chunk2));
@@ -72899,7 +72963,7 @@ function safeBasename(name) {
72899
72963
  }
72900
72964
 
72901
72965
  // src/fs/store.ts
72902
- import { createHash as createHash20, randomUUID as randomUUID10 } from "crypto";
72966
+ import { createHash as createHash21, randomUUID as randomUUID10 } from "crypto";
72903
72967
  import {
72904
72968
  appendFile as appendFile4,
72905
72969
  chmod as chmod7,
@@ -73308,7 +73372,7 @@ function countDiffLines(diff) {
73308
73372
  }
73309
73373
 
73310
73374
  // src/workspace/journal.ts
73311
- import { createHash as createHash19 } from "crypto";
73375
+ import { createHash as createHash20 } from "crypto";
73312
73376
  import { appendFile as appendFile2, mkdir as mkdir27, readFile as readFile29 } from "fs/promises";
73313
73377
  import { dirname as dirname26, join as join43 } from "path";
73314
73378
  import { projectPrivateDir as projectPrivateDir2 } from "@bendyline/gezel/paths";
@@ -73351,7 +73415,7 @@ async function readJournalTail(home, projectId, limit = 100) {
73351
73415
  }
73352
73416
  }
73353
73417
  function sha2562(content) {
73354
- return createHash19("sha256").update(content).digest("hex");
73418
+ return createHash20("sha256").update(content).digest("hex");
73355
73419
  }
73356
73420
 
73357
73421
  // src/workspace/template.ts
@@ -74218,7 +74282,7 @@ function boekwachterIssueFingerprint(path2, issue) {
74218
74282
  issue.category.trim().toLocaleLowerCase(),
74219
74283
  issue.message.trim().toLocaleLowerCase().replace(/\s+/g, " ")
74220
74284
  ].join("\0");
74221
- return createHash20("sha256").update(normalized2).digest("hex");
74285
+ return createHash21("sha256").update(normalized2).digest("hex");
74222
74286
  }
74223
74287
  var ConfigCorruptionError = class extends Error {
74224
74288
  code = "CONFIG_CORRUPT";
@@ -79680,7 +79744,7 @@ import { projectCodeReviewsFile } from "@bendyline/gezel/paths";
79680
79744
  import { createLogger as createLogger77, projectAllowsAmbientWork } from "@bendyline/gezel";
79681
79745
 
79682
79746
  // src/tasks/manager.ts
79683
- import { createHash as createHash21, randomUUID as randomUUID12 } from "crypto";
79747
+ import { createHash as createHash22, randomUUID as randomUUID12 } from "crypto";
79684
79748
  import {
79685
79749
  DEFAULT_NIGHT_SHIFT_WINDOW,
79686
79750
  MANAGED_WORKSPACE_WRITE_SETTING_LABEL as MANAGED_WORKSPACE_WRITE_SETTING_LABEL4,
@@ -81532,7 +81596,7 @@ ${paramLines}` : ""}`,
81532
81596
  if (step.advanceWhen?.file) {
81533
81597
  const content = await (step.advanceWhen.artifact ? this.store.readProjectArtifact(projectId, step.advanceWhen.file) : this.store.readProjectWorkspaceFile(projectId, step.advanceWhen.file)).catch(() => null);
81534
81598
  if (content !== null) {
81535
- contentHash2 = createHash21("sha256").update(content).digest("hex");
81599
+ contentHash2 = createHash22("sha256").update(content).digest("hex");
81536
81600
  }
81537
81601
  }
81538
81602
  if (contentHash2 !== void 0 && step.lastGateReject?.contentHash !== void 0 && step.lastGateReject.contentHash === contentHash2) {
@@ -83199,7 +83263,7 @@ function sumStat(s, key) {
83199
83263
  }
83200
83264
 
83201
83265
  // src/grants/manager.ts
83202
- import { createHash as createHash22, randomBytes as randomBytes5, randomUUID as randomUUID13, timingSafeEqual } from "crypto";
83266
+ import { createHash as createHash23, randomBytes as randomBytes5, randomUUID as randomUUID13, timingSafeEqual } from "crypto";
83203
83267
  import { chmod as chmod8 } from "fs/promises";
83204
83268
  import { pendingGrantsFile as defaultPendingGrantsFile } from "@bendyline/gezel/paths";
83205
83269
  var PENDING_GRANT_TTL_MS = 10 * 6e4;
@@ -83271,7 +83335,7 @@ function generateVerificationCode() {
83271
83335
  return `${raw.slice(0, 3)}-${raw.slice(3)}`;
83272
83336
  }
83273
83337
  function hashVerificationCode(salt, normalizedCode) {
83274
- return createHash22("sha256").update(salt, "base64url").update("\0").update(normalizedCode, "ascii").digest();
83338
+ return createHash23("sha256").update(salt, "base64url").update("\0").update(normalizedCode, "ascii").digest();
83275
83339
  }
83276
83340
  function codeMatches(grant, suppliedCode) {
83277
83341
  const normalized2 = normalizeVerificationCode(suppliedCode);
@@ -85191,7 +85255,7 @@ function tokenize2(question) {
85191
85255
  }
85192
85256
 
85193
85257
  // src/http/cert.ts
85194
- import { createHash as createHash23 } from "crypto";
85258
+ import { createHash as createHash24 } from "crypto";
85195
85259
  import { generate as selfsignedGenerate } from "selfsigned";
85196
85260
  var CERT_VALIDITY_DAYS = 90;
85197
85261
  async function generateLoopbackCert() {
@@ -85228,7 +85292,7 @@ async function generateLoopbackCert() {
85228
85292
  ]
85229
85293
  });
85230
85294
  const der = pemToDer(pems.cert);
85231
- const digest = createHash23("sha256").update(der).digest();
85295
+ const digest = createHash24("sha256").update(der).digest();
85232
85296
  return {
85233
85297
  certPem: pems.cert,
85234
85298
  keyPem: pems.private,
@@ -85242,14 +85306,14 @@ function pemToDer(pem) {
85242
85306
  }
85243
85307
 
85244
85308
  // src/http/codex-bridge-port.ts
85245
- import { createHash as createHash24 } from "crypto";
85309
+ import { createHash as createHash25 } from "crypto";
85246
85310
  import { realpathSync as realpathSync3 } from "fs";
85247
85311
  import { resolve as resolve10 } from "path";
85248
85312
  var CODEX_BRIDGE_PORT_RANGE_START = 2e4;
85249
85313
  var CODEX_BRIDGE_PORT_RANGE_END = 49151;
85250
85314
  var CODEX_BRIDGE_PORT_RANGE_SIZE = CODEX_BRIDGE_PORT_RANGE_END - CODEX_BRIDGE_PORT_RANGE_START + 1;
85251
85315
  function codexBridgePortForHome(home) {
85252
- const digest = createHash24("sha256").update(canonicalPath2(home)).digest();
85316
+ const digest = createHash25("sha256").update(canonicalPath2(home)).digest();
85253
85317
  const bucket = digest.readUInt32BE(0) % CODEX_BRIDGE_PORT_RANGE_SIZE;
85254
85318
  return CODEX_BRIDGE_PORT_RANGE_START + bucket;
85255
85319
  }
@@ -85475,7 +85539,7 @@ async function loadGezelByRef(ref, ctx) {
85475
85539
  import { randomUUID as randomUUID15 } from "crypto";
85476
85540
 
85477
85541
  // src/http/openai-compat/responses-translate.ts
85478
- import { createHash as createHash25 } from "crypto";
85542
+ import { createHash as createHash26 } from "crypto";
85479
85543
  import { z as z11 } from "zod";
85480
85544
 
85481
85545
  // src/http/openai-compat/translate.ts
@@ -85914,7 +85978,7 @@ var CUSTOM_TOOL_INPUT_KEY = "input";
85914
85978
  function flattenResponsesNamespaceToolName(namespace, name) {
85915
85979
  const joined = `${namespace}__${name}`;
85916
85980
  if (joined.length <= MAX_LOCAL_TOOL_NAME_LENGTH) return joined;
85917
- const digest = createHash25("sha256").update(namespace).update("\0").update(name).digest("hex").slice(0, 12);
85981
+ const digest = createHash26("sha256").update(namespace).update("\0").update(name).digest("hex").slice(0, 12);
85918
85982
  const prefixLength = MAX_LOCAL_TOOL_NAME_LENGTH - digest.length - 2;
85919
85983
  return `${joined.slice(0, prefixLength)}__${digest}`;
85920
85984
  }
@@ -87144,7 +87208,7 @@ function mountMachineEngineHints(app) {
87144
87208
  }
87145
87209
 
87146
87210
  // src/http/preview-capability.ts
87147
- import { createHash as createHash26, randomBytes as randomBytes6 } from "crypto";
87211
+ import { createHash as createHash27, randomBytes as randomBytes6 } from "crypto";
87148
87212
  import { posix as posix3 } from "path";
87149
87213
  var DEFAULT_PREVIEW_CAPABILITY_TTL_MS = 10 * 60 * 1e3;
87150
87214
  var DEFAULT_PREVIEW_CAPABILITY_ABSOLUTE_TTL_MS = 2 * 60 * 60 * 1e3;
@@ -87288,7 +87352,7 @@ function pathIsInScope(path2, scopePath) {
87288
87352
  return scopePath === "" || path2 === scopePath || path2.startsWith(`${scopePath}/`);
87289
87353
  }
87290
87354
  function tokenDigest(token) {
87291
- return createHash26("sha256").update(token).digest("base64url");
87355
+ return createHash27("sha256").update(token).digest("base64url");
87292
87356
  }
87293
87357
 
87294
87358
  // src/http/routes/ai.ts
@@ -87657,6 +87721,15 @@ var KOKORO_HF_REPO = "onnx-community/Kokoro-82M-v1.0-ONNX";
87657
87721
  var KOKORO_APPROX_BYTES_BY_ID = {
87658
87722
  [KOKORO_DEFAULT_MODEL_ID]: 95e6
87659
87723
  };
87724
+ function isKokoroRuntimeAvailable(resolveModule = (specifier) => import.meta.resolve(specifier)) {
87725
+ try {
87726
+ resolveModule("kokoro-js");
87727
+ resolveModule("@huggingface/transformers");
87728
+ return true;
87729
+ } catch {
87730
+ return false;
87731
+ }
87732
+ }
87660
87733
  var KOKORO_DEFAULT_VOICES = [
87661
87734
  {
87662
87735
  id: "af_heart",
@@ -87986,7 +88059,7 @@ function parseGender(s) {
87986
88059
  }
87987
88060
 
87988
88061
  // src/providers/audio/whisper-cpp.ts
87989
- import { createHash as createHash27 } from "crypto";
88062
+ import { createHash as createHash28 } from "crypto";
87990
88063
  import { createReadStream as createReadStream5 } from "fs";
87991
88064
  import { mkdir as mkdir37, readFile as readFile39, rename as rename11, rm as rm25, writeFile as writeFile14 } from "fs/promises";
87992
88065
  import { basename as basename12, join as join52 } from "path";
@@ -88281,7 +88354,7 @@ async function* downloadWithSha256(fetchImpl, opts) {
88281
88354
  yield { type: "progress", bytesWritten: writtenAll, totalBytes: totalAllBytes };
88282
88355
  }
88283
88356
  }
88284
- const hasher = createHash27("sha256");
88357
+ const hasher = createHash28("sha256");
88285
88358
  await new Promise((resolve18, reject) => {
88286
88359
  const stream = createReadStream5(tmpPath, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
88287
88360
  stream.on("data", (chunk2) => hasher.update(chunk2));
@@ -88332,6 +88405,41 @@ function machineEngineProxy(ctx, sourcePrefix, targetPrefix, localPaths = [], sh
88332
88405
 
88333
88406
  // src/http/routes/audio.ts
88334
88407
  var log85 = createLogger88("audio");
88408
+ function buildAudioCatalog(options = {}) {
88409
+ const kokoroRuntimeAvailable = options.kokoroRuntimeAvailable ?? isKokoroRuntimeAvailable();
88410
+ return {
88411
+ // All Whisper weights ship under MIT (whisper.cpp / OpenAI Whisper);
88412
+ // Kokoro under Apache 2.0. Both are permissive → "Free, open".
88413
+ stt: WHISPER_MODEL_CATALOG.map((m) => ({
88414
+ id: m.id,
88415
+ name: m.name,
88416
+ description: m.description,
88417
+ approxSizeBytes: m.approxSizeBytes,
88418
+ kind: "stt",
88419
+ license: "MIT",
88420
+ licenseClass: "open",
88421
+ licenseShortName: "MIT",
88422
+ licenseUrl: "https://huggingface.co/ggerganov/whisper.cpp",
88423
+ // The Base (English) variant is the recommended STT default: ~140 MB,
88424
+ // realtime on laptop CPUs. Curated recoScore → ★ badge + auto-pick.
88425
+ ...m.id === "whisper-base.en" ? { recoScore: 20 } : {}
88426
+ })),
88427
+ tts: kokoroRuntimeAvailable ? [
88428
+ {
88429
+ id: KOKORO_DEFAULT_MODEL_ID,
88430
+ name: "Kokoro 82M v1.0",
88431
+ description: "Apache 2.0 TTS \u2014 54+ voices, ~80MB quantized, near-realtime on M1 / modern desktop CPUs.",
88432
+ approxSizeBytes: 95e6,
88433
+ kind: "tts",
88434
+ license: "Apache 2.0",
88435
+ licenseClass: "open",
88436
+ licenseShortName: "Apache 2.0",
88437
+ licenseUrl: "https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX",
88438
+ recoScore: 20
88439
+ }
88440
+ ] : []
88441
+ };
88442
+ }
88335
88443
  function audioRoutes(ctx) {
88336
88444
  const app = new Hono4();
88337
88445
  app.use(
@@ -88453,38 +88561,7 @@ function audioRoutes(ctx) {
88453
88561
  });
88454
88562
  });
88455
88563
  app.get("/catalog", (c) => {
88456
- return c.json({
88457
- // All Whisper weights ship under MIT (whisper.cpp / OpenAI Whisper);
88458
- // Kokoro under Apache 2.0. Both are permissive → "Free, open".
88459
- stt: WHISPER_MODEL_CATALOG.map((m) => ({
88460
- id: m.id,
88461
- name: m.name,
88462
- description: m.description,
88463
- approxSizeBytes: m.approxSizeBytes,
88464
- kind: "stt",
88465
- license: "MIT",
88466
- licenseClass: "open",
88467
- licenseShortName: "MIT",
88468
- licenseUrl: "https://huggingface.co/ggerganov/whisper.cpp",
88469
- // The Base (English) variant is the recommended STT default: ~140 MB,
88470
- // realtime on laptop CPUs. Curated recoScore → ★ badge + auto-pick.
88471
- ...m.id === "whisper-base.en" ? { recoScore: 20 } : {}
88472
- })),
88473
- tts: [
88474
- {
88475
- id: KOKORO_DEFAULT_MODEL_ID,
88476
- name: "Kokoro 82M v1.0",
88477
- description: "Apache 2.0 TTS \u2014 54+ voices, ~80MB quantized, near-realtime on M1 / modern desktop CPUs.",
88478
- approxSizeBytes: 95e6,
88479
- kind: "tts",
88480
- license: "Apache 2.0",
88481
- licenseClass: "open",
88482
- licenseShortName: "Apache 2.0",
88483
- licenseUrl: "https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX",
88484
- recoScore: 20
88485
- }
88486
- ]
88487
- });
88564
+ return c.json(buildAudioCatalog());
88488
88565
  });
88489
88566
  app.get("/stt/models", async (c) => {
88490
88567
  const provider = await ctx.stt.current();
@@ -90456,6 +90533,8 @@ function configRoutes(ctx) {
90456
90533
  autoUpdateChecks: config.autoUpdateChecks !== false,
90457
90534
  quitOnClose: config.quitOnClose === true,
90458
90535
  themePref: config.themePref,
90536
+ cliShowThinking: config.cliShowThinking !== false,
90537
+ cliShowWrites: config.cliShowWrites === true,
90459
90538
  documentExportOptions: config.documentExportOptions,
90460
90539
  sidebarSide: config.sidebarSide,
90461
90540
  homeGreetingCollapsed: config.homeGreetingCollapsed === true,
@@ -90802,6 +90881,8 @@ function configRoutes(ctx) {
90802
90881
  autoUpdateChecks: updated.autoUpdateChecks !== false,
90803
90882
  quitOnClose: updated.quitOnClose === true,
90804
90883
  themePref: updated.themePref,
90884
+ cliShowThinking: updated.cliShowThinking !== false,
90885
+ cliShowWrites: updated.cliShowWrites === true,
90805
90886
  documentExportOptions: updated.documentExportOptions,
90806
90887
  sidebarSide: updated.sidebarSide,
90807
90888
  homeGreetingCollapsed: updated.homeGreetingCollapsed === true,
@@ -92191,7 +92272,11 @@ function ds4Routes(ctx) {
92191
92272
  const catalogId = c.req.param("catalogId");
92192
92273
  const skipShaRaw = c.req.query("skipSha");
92193
92274
  const skipSha = skipShaRaw != null && skipShaRaw !== "" && skipShaRaw !== "0" && skipShaRaw !== "false";
92194
- ctx.chatInstalls.ds4.start(catalogId, { skipSha, includeMmproj: false });
92275
+ ctx.chatInstalls.ds4.start(catalogId, {
92276
+ skipSha,
92277
+ includeMmproj: false,
92278
+ installCompanion: false
92279
+ });
92195
92280
  return streamSSE5(c, (stream) => subscribeToInstallSse(ctx.chatInstalls.ds4, catalogId, stream));
92196
92281
  });
92197
92282
  app.delete("/models/:catalogId/install", (c) => {
@@ -93879,6 +93964,7 @@ function gezelRoutes(ctx) {
93879
93964
  toGezelIdOrName: toId,
93880
93965
  projectId: body.projectId,
93881
93966
  text: body.text,
93967
+ ...body.suppressReply ? { suppressReply: true } : {},
93882
93968
  ...body.expectedDeliverable ? { expectedDeliverable: body.expectedDeliverable } : {}
93883
93969
  });
93884
93970
  return c.json({
@@ -94820,7 +94906,7 @@ import { HandboekRenderModeSchema } from "@bendyline/gezel";
94820
94906
  import { Hono as Hono29 } from "hono";
94821
94907
 
94822
94908
  // src/handboek/narration.ts
94823
- import { createHash as createHash28 } from "crypto";
94909
+ import { createHash as createHash29 } from "crypto";
94824
94910
  import { existsSync as existsSync14 } from "fs";
94825
94911
  import { mkdir as mkdir42, readFile as readFile43, writeFile as writeFile16 } from "fs/promises";
94826
94912
  import { join as join65 } from "path";
@@ -94836,7 +94922,7 @@ function createHandboekNarrator(deps) {
94836
94922
  const pathFor = (hash) => join65(dir, `${hash}.wav`);
94837
94923
  const metaPathFor = (hash) => join65(dir, `${hash}.json`);
94838
94924
  async function ensureSegment(key, synthesize) {
94839
- const hash = createHash28("sha256").update(key).digest("hex");
94925
+ const hash = createHash29("sha256").update(key).digest("hex");
94840
94926
  const metaPath = metaPathFor(hash);
94841
94927
  if (existsSync14(pathFor(hash)) && existsSync14(metaPath)) {
94842
94928
  try {
@@ -95836,9 +95922,15 @@ function llamaCppRoutes(ctx) {
95836
95922
  const catalogId = c.req.param("catalogId");
95837
95923
  const skipShaRaw = c.req.query("skipSha");
95838
95924
  const skipSha = skipShaRaw != null && skipShaRaw !== "" && skipShaRaw !== "0" && skipShaRaw !== "false";
95925
+ const skipCompanionRaw = c.req.query("skipCompanion");
95926
+ const skipCompanion = skipCompanionRaw != null && skipCompanionRaw !== "" && skipCompanionRaw !== "0" && skipCompanionRaw !== "false";
95839
95927
  const config = await ctx.store.readConfig().catch(() => null);
95840
95928
  const includeMmproj = config?.nativeVision?.[catalogId] === true;
95841
- ctx.chatInstalls.llamaCpp.start(catalogId, { skipSha, includeMmproj });
95929
+ ctx.chatInstalls.llamaCpp.start(catalogId, {
95930
+ skipSha,
95931
+ includeMmproj,
95932
+ installCompanion: !skipCompanion
95933
+ });
95842
95934
  return streamSSE9(
95843
95935
  c,
95844
95936
  (stream) => subscribeToInstallSse(ctx.chatInstalls.llamaCpp, catalogId, stream)
@@ -95929,7 +96021,7 @@ function mcpToolRoutes(ctx) {
95929
96021
  import { Hono as Hono36 } from "hono";
95930
96022
 
95931
96023
  // src/meester/status-generator.ts
95932
- import { createHash as createHash29 } from "crypto";
96024
+ import { createHash as createHash30 } from "crypto";
95933
96025
  import {
95934
96026
  MEESTER_STATUS_HEADLINE_MAX,
95935
96027
  MeesterStatusModelOutputSchema,
@@ -96241,7 +96333,7 @@ function localDay4(date) {
96241
96333
  return `${y}-${m}-${d}`;
96242
96334
  }
96243
96335
  function actionKey(projectId, title) {
96244
- return createHash29("sha256").update(`${projectId}
96336
+ return createHash30("sha256").update(`${projectId}
96245
96337
  ${normalizeTitle(title)}`).digest("hex");
96246
96338
  }
96247
96339
  function normalizeTitle(title) {
@@ -96253,7 +96345,7 @@ function hashInput(candidates) {
96253
96345
  ...c.openTasks.map((t) => `${t.ref}:${t.status}`),
96254
96346
  ...c.events.map((e) => e.id)
96255
96347
  ]);
96256
- return createHash29("sha256").update(lines.join("\n")).digest("hex");
96348
+ return createHash30("sha256").update(lines.join("\n")).digest("hex");
96257
96349
  }
96258
96350
  function parseModelOutput(raw) {
96259
96351
  const fence = raw.match(/```(?:json)?\s*\n([\s\S]*?)\n?```/);
@@ -96546,7 +96638,7 @@ import { Hono as Hono39 } from "hono";
96546
96638
  import { z as z20 } from "zod";
96547
96639
 
96548
96640
  // src/models/gezmodel.ts
96549
- import { createHash as createHash30, randomUUID as randomUUID19 } from "crypto";
96641
+ import { createHash as createHash31, randomUUID as randomUUID19 } from "crypto";
96550
96642
  import { createReadStream as createReadStream6, createWriteStream as createWriteStream5 } from "fs";
96551
96643
  import { mkdir as mkdir43, open as open3, readFile as readFile45, readdir as readdir26, rm as rm29, stat as stat26, writeFile as writeFile17 } from "fs/promises";
96552
96644
  import { basename as basename14, dirname as dirname35, extname as extname5, join as join66 } from "path";
@@ -96648,7 +96740,7 @@ var GezmodelManager = class {
96648
96740
  files.push({
96649
96741
  path: path2,
96650
96742
  sizeBytes: content.byteLength,
96651
- sha256: createHash30("sha256").update(content).digest("hex"),
96743
+ sha256: createHash31("sha256").update(content).digest("hex"),
96652
96744
  role: path2 === "manifests/installed.json" ? "installed-manifest" : path2 === "manifests/catalog.json" ? "catalog-manifest" : "catalog-file"
96653
96745
  });
96654
96746
  }
@@ -96854,7 +96946,7 @@ var GezmodelManager = class {
96854
96946
  }
96855
96947
  };
96856
96948
  async function hashFile(path2) {
96857
- const hash = createHash30("sha256");
96949
+ const hash = createHash31("sha256");
96858
96950
  const stream = createReadStream6(path2, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
96859
96951
  for await (const chunk2 of stream) hash.update(chunk2);
96860
96952
  return hash.digest("hex");
@@ -97052,7 +97144,7 @@ function extractOne(archivePath, wanted, dest, expected) {
97052
97144
  zip.openReadStream(entry, (streamErr, stream) => {
97053
97145
  if (streamErr || !stream)
97054
97146
  return fail2(streamErr ?? new Error("could not read ZIP entry"));
97055
- const hash = createHash30("sha256");
97147
+ const hash = createHash31("sha256");
97056
97148
  let bytes = 0;
97057
97149
  const verifier = new Transform({
97058
97150
  transform(chunk2, _encoding, callback) {
@@ -97286,7 +97378,7 @@ import {
97286
97378
  } from "@bendyline/gezel";
97287
97379
 
97288
97380
  // src/providers/mlx/models.ts
97289
- import { createHash as createHash31 } from "crypto";
97381
+ import { createHash as createHash32 } from "crypto";
97290
97382
  import { createReadStream as createReadStream7 } from "fs";
97291
97383
  import { mkdir as mkdir44, readFile as readFile47, rename as rename12, rm as rm30, stat as stat27, writeFile as writeFile18 } from "fs/promises";
97292
97384
  import { join as join68, resolve as resolvePath2 } from "path";
@@ -97848,7 +97940,7 @@ var MlxModelManager = class {
97848
97940
  }
97849
97941
  }
97850
97942
  push({ type: "verifying", file: file.name });
97851
- const hasher = createHash31("sha256");
97943
+ const hasher = createHash32("sha256");
97852
97944
  await new Promise((resolve18, reject) => {
97853
97945
  const stream = createReadStream7(tmpPath, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
97854
97946
  stream.on("data", (chunk2) => hasher.update(chunk2));
@@ -99688,7 +99780,7 @@ function describeHostCadence(args) {
99688
99780
  }
99689
99781
 
99690
99782
  // src/project-type/craftbooks.ts
99691
- import { createHash as createHash32 } from "crypto";
99783
+ import { createHash as createHash33 } from "crypto";
99692
99784
  import {
99693
99785
  craftbookFromDoc as craftbookFromDoc3,
99694
99786
  createLogger as createLogger109,
@@ -99712,7 +99804,7 @@ function craftbookContentHash(book) {
99712
99804
  command: book.command ?? null,
99713
99805
  requirements: book.requirements ?? null
99714
99806
  };
99715
- return `sha256:${createHash32("sha256").update(JSON.stringify(canonical)).digest("hex")}`;
99807
+ return `sha256:${createHash33("sha256").update(JSON.stringify(canonical)).digest("hex")}`;
99716
99808
  }
99717
99809
  async function resolveTypeCraftbook(catalog, input, id, now) {
99718
99810
  const embedded = await catalog.readItemFile(
@@ -100420,7 +100512,7 @@ function pageInvokeRoutes(ctx) {
100420
100512
  }
100421
100513
 
100422
100514
  // src/http/routes/page-read.ts
100423
- import { createHash as createHash33 } from "crypto";
100515
+ import { createHash as createHash34 } from "crypto";
100424
100516
  import { readFile as readFile50, readdir as readdir29, stat as stat28 } from "fs/promises";
100425
100517
  import { PageReadRequestSchema, createLogger as createLogger113 } from "@bendyline/gezel";
100426
100518
  import { Hono as Hono48 } from "hono";
@@ -100429,7 +100521,7 @@ var PAGE_READ_MAX_BYTES = 2 * 1024 * 1024;
100429
100521
  var RATE_WINDOW_MS3 = 6e4;
100430
100522
  var RATE_MAX_READS = 600;
100431
100523
  function etagOf(size, mtimeMs) {
100432
- return createHash33("sha256").update(`${size}:${Math.trunc(mtimeMs)}`).digest("base64url").slice(0, 16);
100524
+ return createHash34("sha256").update(`${size}:${Math.trunc(mtimeMs)}`).digest("base64url").slice(0, 16);
100433
100525
  }
100434
100526
  function pageReadRoutes(ctx) {
100435
100527
  const app = new Hono48();
@@ -100479,7 +100571,7 @@ function pageReadRoutes(ctx) {
100479
100571
  return `${entry.name}:${entry.isDirectory() ? "dir" : "file"}:${Math.trunc(child?.mtimeMs ?? 0)}`;
100480
100572
  })
100481
100573
  );
100482
- const digest = createHash33("sha256").update(listed.sort().join("\n")).digest("base64url").slice(0, 16);
100574
+ const digest = createHash34("sha256").update(listed.sort().join("\n")).digest("base64url").slice(0, 16);
100483
100575
  return c.json({ op: "stat", etag: digest, mtime: stats.mtimeMs });
100484
100576
  }
100485
100577
  return c.json({
@@ -100504,7 +100596,7 @@ function pageReadRoutes(ctx) {
100504
100596
  };
100505
100597
  })
100506
100598
  )).filter((entry) => entry !== null);
100507
- const digest = createHash33("sha256").update(
100599
+ const digest = createHash34("sha256").update(
100508
100600
  listed.map((e) => `${e.name}:${e.kind}:${Math.trunc(e.mtime)}`).sort().join("\n")
100509
100601
  ).digest("base64url").slice(0, 16);
100510
100602
  return c.json({ op: "list", entries: listed, etag: digest, mtime: stats.mtimeMs });
@@ -101218,7 +101310,7 @@ init_ensure();
101218
101310
  init_install();
101219
101311
 
101220
101312
  // src/workspace/instruction-scanner.ts
101221
- import { createHash as createHash34 } from "crypto";
101313
+ import { createHash as createHash35 } from "crypto";
101222
101314
  import { readFile as readFile52, stat as stat30 } from "fs/promises";
101223
101315
  import { join as join73 } from "path";
101224
101316
  var MAX_CONTENT_CHARS = 64e3;
@@ -101263,7 +101355,7 @@ ${i.content.trim()}`).join("\n\n---\n\n");
101263
101355
  return { content: chosen.content, sourceFile: chosen.source, hash: chosen.hash };
101264
101356
  }
101265
101357
  function sha2563(s) {
101266
- return createHash34("sha256").update(s).digest("hex");
101358
+ return createHash35("sha256").update(s).digest("hex");
101267
101359
  }
101268
101360
 
101269
101361
  // src/workspace/skill-script-translator.ts
@@ -103148,7 +103240,7 @@ async function recoverTypedProjectCreations(store) {
103148
103240
  }
103149
103241
 
103150
103242
  // src/project-type/gzl.ts
103151
- import { createHash as createHash35 } from "crypto";
103243
+ import { createHash as createHash36 } from "crypto";
103152
103244
  import { mkdir as mkdir48, writeFile as writeFile21 } from "fs/promises";
103153
103245
  import { dirname as dirname40 } from "path";
103154
103246
  import {
@@ -103166,7 +103258,7 @@ function shard(id) {
103166
103258
  return id.slice(0, 2).toLowerCase();
103167
103259
  }
103168
103260
  function hashItemFiles(files) {
103169
- const hash = createHash35("sha256");
103261
+ const hash = createHash36("sha256");
103170
103262
  for (const { rel, content } of [...files].sort((a, b) => a.rel < b.rel ? -1 : 1)) {
103171
103263
  hash.update(rel);
103172
103264
  hash.update("\0");
@@ -103314,7 +103406,7 @@ async function importGzlBundle(deps, buffer, opts = {}) {
103314
103406
 
103315
103407
  // src/workspace/command-approvals.ts
103316
103408
  init_atomic();
103317
- import { createHash as createHash36 } from "crypto";
103409
+ import { createHash as createHash37 } from "crypto";
103318
103410
  import { existsSync as existsSync18 } from "fs";
103319
103411
  import { mkdir as mkdir49, readFile as readFile57 } from "fs/promises";
103320
103412
  import { dirname as dirname41, join as join79 } from "path";
@@ -103322,7 +103414,7 @@ import { projectPrivateDir as projectPrivateDir5 } from "@bendyline/gezel/paths"
103322
103414
  function hashCommandInvocation(body, args, inputFiles = []) {
103323
103415
  const files = [...inputFiles].map(({ path: path2, sha256: sha2565 }) => ({ path: path2, sha256: sha2565 })).sort((a, b) => a.path.localeCompare(b.path) || a.sha256.localeCompare(b.sha256));
103324
103416
  const payload = JSON.stringify({ version: 2, body: body ?? null, args, files });
103325
- return createHash36("sha256").update("gezel-command-invocation\0").update(payload).digest("hex");
103417
+ return createHash37("sha256").update("gezel-command-invocation\0").update(payload).digest("hex");
103326
103418
  }
103327
103419
  function approvalsPath(home, projectId) {
103328
103420
  return join79(projectPrivateDir5(home, projectId), "command-approvals.json");
@@ -103548,20 +103640,20 @@ import {
103548
103640
  } from "@bendyline/gezel";
103549
103641
  import { projectPrivateDir as projectPrivateDir6 } from "@bendyline/gezel/paths";
103550
103642
  var SHIPPED_ALLOWLIST = [
103551
- { package: "zod", allowedVersions: ["^3", "^4"] },
103552
- { package: "chalk", allowedVersions: ["^5"] },
103553
- { package: "commander", allowedVersions: ["^12", "^13"] },
103554
- { package: "date-fns", allowedVersions: ["^3", "^4"] },
103555
- { package: "yaml", allowedVersions: ["^2"] },
103556
- { package: "cheerio", allowedVersions: ["^1"] },
103557
- { package: "mime-types", allowedVersions: ["^2", "^3"] },
103558
- { package: "marked", allowedVersions: ["^12", "^13", "^14", "^15"] },
103559
- { package: "nanoid", allowedVersions: ["^5"] },
103560
- { package: "pino", allowedVersions: ["^9"] },
103561
- { package: "playwright-core", allowedVersions: ["^1"] },
103562
- { package: "tsx", allowedVersions: ["^4"] },
103563
- { package: "typescript", allowedVersions: ["^5"] },
103564
- { package: "undici", allowedVersions: ["^6", "^7"] }
103643
+ { package: "zod", allowedVersions: ["^3", "^4"], defaultVersion: "^4" },
103644
+ { package: "chalk", allowedVersions: ["^5"], defaultVersion: "^5" },
103645
+ { package: "commander", allowedVersions: ["^12", "^13"], defaultVersion: "^13" },
103646
+ { package: "date-fns", allowedVersions: ["^3", "^4"], defaultVersion: "^4" },
103647
+ { package: "yaml", allowedVersions: ["^2"], defaultVersion: "^2" },
103648
+ { package: "cheerio", allowedVersions: ["^1"], defaultVersion: "^1" },
103649
+ { package: "mime-types", allowedVersions: ["^2", "^3"], defaultVersion: "^3" },
103650
+ { package: "marked", allowedVersions: ["^12", "^13", "^14", "^15"], defaultVersion: "^15" },
103651
+ { package: "nanoid", allowedVersions: ["^5"], defaultVersion: "^5" },
103652
+ { package: "pino", allowedVersions: ["^9"], defaultVersion: "^9" },
103653
+ { package: "playwright-core", allowedVersions: ["^1"], defaultVersion: "^1" },
103654
+ { package: "tsx", allowedVersions: ["^4"], defaultVersion: "^4" },
103655
+ { package: "typescript", allowedVersions: ["^5"], defaultVersion: "^5" },
103656
+ { package: "undici", allowedVersions: ["^6", "^7"], defaultVersion: "^7" }
103565
103657
  ];
103566
103658
  function projectAllowlistPath(home, projectId) {
103567
103659
  return join81(projectPrivateDir6(home, projectId), "npm-allowlist.json");
@@ -103592,6 +103684,9 @@ function matchesAllowlist(pkg, version) {
103592
103684
  }
103593
103685
  return false;
103594
103686
  }
103687
+ function shippedDefaultVersion(pkg) {
103688
+ return SHIPPED_ALLOWLIST.find((entry) => entry.package === pkg)?.defaultVersion;
103689
+ }
103595
103690
  function matchesProjectApproval(allowlist, pkg, version) {
103596
103691
  return allowlist.approved.some((e) => e.package === pkg && e.version === version);
103597
103692
  }
@@ -103721,7 +103816,9 @@ function dedupRequests(raw) {
103721
103816
  const out = [];
103722
103817
  for (const r of raw) {
103723
103818
  const pkg = NpmPackageNameSchema.parse(r.package);
103724
- const version = NpmRegistryVersionSchema.parse(r.version ?? "latest");
103819
+ const version = NpmRegistryVersionSchema.parse(
103820
+ r.version ?? shippedDefaultVersion(pkg) ?? "latest"
103821
+ );
103725
103822
  const key = keyOf(pkg, version);
103726
103823
  if (seen.has(key)) continue;
103727
103824
  seen.add(key);
@@ -103891,7 +103988,7 @@ import { join as join82 } from "path";
103891
103988
  import { nowIso as nowIso14 } from "@bendyline/gezel";
103892
103989
 
103893
103990
  // src/workspace/command-inputs.ts
103894
- import { createHash as createHash37 } from "crypto";
103991
+ import { createHash as createHash38 } from "crypto";
103895
103992
  import { createReadStream as createReadStream8 } from "fs";
103896
103993
  import { readFile as readFile59, realpath as realpath7, stat as stat35 } from "fs/promises";
103897
103994
  import { dirname as dirname43, extname as extname6, isAbsolute as isAbsolute10, relative as relative10, resolve as resolve13, sep as sep9 } from "path";
@@ -103964,7 +104061,7 @@ function portableRelative(root, file) {
103964
104061
  return relative10(root, file).split(sep9).join("/");
103965
104062
  }
103966
104063
  async function sha256File4(file) {
103967
- const hash = createHash37("sha256");
104064
+ const hash = createHash38("sha256");
103968
104065
  await new Promise((resolveStream, reject) => {
103969
104066
  const stream = createReadStream8(file);
103970
104067
  stream.on("data", (chunk2) => hash.update(chunk2));
@@ -107869,7 +107966,7 @@ async function readProjectScriptRun(home, projectId, runId) {
107869
107966
  }
107870
107967
 
107871
107968
  // src/scripts/sdk.ts
107872
- import { createHash as createHash39 } from "crypto";
107969
+ import { createHash as createHash40 } from "crypto";
107873
107970
  import { readFile as readFile67 } from "fs/promises";
107874
107971
  import { dirname as dirname45, join as join87, relative as relative11 } from "path";
107875
107972
  import { fileURLToPath as fileURLToPath7 } from "url";
@@ -107935,7 +108032,7 @@ async function readSdkTypes() {
107935
108032
  });
107936
108033
  } catch {
107937
108034
  }
107938
- const hash = createHash39("sha256");
108035
+ const hash = createHash40("sha256");
107939
108036
  for (const f of files) hash.update(f.name).update("\0").update(f.content);
107940
108037
  cachedTypes = { version: hash.digest("hex"), files };
107941
108038
  return cachedTypes;
@@ -110749,9 +110846,13 @@ async function grepWorkspace(opts) {
110749
110846
  const plan = normalizePlan(opts);
110750
110847
  const target = await resolveSearchTarget(opts.workspaceDir, opts.path);
110751
110848
  const requestedEngine = opts.engine ?? "auto";
110752
- const ripgrepPath = requestedEngine === "javascript" ? null : await resolveExecutableOnPath("rg", target.workspaceDir, Math.min(plan.timeoutMs, 2e3));
110849
+ const ripgrepPath = requestedEngine === "javascript" ? null : await resolveRipgrepExecutable(target.workspaceDir, Math.min(plan.timeoutMs, 2e3));
110753
110850
  if (requestedEngine === "ripgrep" && !ripgrepPath) {
110754
- throw new WorkspaceGrepError("ripgrep is not installed on this machine", 500, "rg-unavailable");
110851
+ throw new WorkspaceGrepError(
110852
+ "ripgrep is unavailable (the bundled platform package is missing and rg is not on PATH)",
110853
+ 500,
110854
+ "rg-unavailable"
110855
+ );
110755
110856
  }
110756
110857
  let raw;
110757
110858
  let engine;
@@ -111255,6 +111356,16 @@ async function resolveExecutableOnPath(command, forbiddenRoot, timeoutMs) {
111255
111356
  if (timer) clearTimeout(timer);
111256
111357
  }
111257
111358
  }
111359
+ async function resolveRipgrepExecutable(forbiddenRoot, timeoutMs) {
111360
+ const onPath = await resolveExecutableOnPath("rg", forbiddenRoot, timeoutMs);
111361
+ if (onPath) return onPath;
111362
+ try {
111363
+ const { rgPath } = await import("@vscode/ripgrep");
111364
+ return await validateExecutable(rgPath, forbiddenRoot);
111365
+ } catch {
111366
+ return null;
111367
+ }
111368
+ }
111258
111369
  async function findExecutableOnPath(command, forbiddenRoot) {
111259
111370
  const pathValue = process.env.PATH;
111260
111371
  if (!pathValue) return null;
@@ -111263,22 +111374,28 @@ async function findExecutableOnPath(command, forbiddenRoot) {
111263
111374
  const entry = rawEntry.replace(/^"|"$/g, "");
111264
111375
  if (!entry || !isAbsolute11(entry)) continue;
111265
111376
  for (const suffix of suffixes) {
111266
- try {
111267
- const executable = await realpath10(join89(entry, `${command}${suffix}`));
111268
- if (pathIsInside(forbiddenRoot, executable)) continue;
111269
- const executableStat = await stat39(executable);
111270
- if (!executableStat.isFile()) continue;
111271
- await access3(
111272
- executable,
111273
- process.platform === "win32" ? fsConstants.F_OK : fsConstants.X_OK
111274
- );
111275
- return executable;
111276
- } catch {
111277
- }
111377
+ const executable = await validateExecutable(
111378
+ join89(entry, `${command}${suffix}`),
111379
+ forbiddenRoot
111380
+ );
111381
+ if (executable) return executable;
111278
111382
  }
111279
111383
  }
111280
111384
  return null;
111281
111385
  }
111386
+ async function validateExecutable(candidate, forbiddenRoot) {
111387
+ if (!isAbsolute11(candidate)) return null;
111388
+ try {
111389
+ const executable = await realpath10(candidate);
111390
+ if (pathIsInside(forbiddenRoot, executable)) return null;
111391
+ const executableStat = await stat39(executable);
111392
+ if (!executableStat.isFile()) return null;
111393
+ await access3(executable, process.platform === "win32" ? fsConstants.F_OK : fsConstants.X_OK);
111394
+ return executable;
111395
+ } catch {
111396
+ return null;
111397
+ }
111398
+ }
111282
111399
  function pathIsInside(root, candidate) {
111283
111400
  const rel = relative12(root, candidate);
111284
111401
  return rel === "" || rel !== ".." && !rel.startsWith(`..${sep10}`) && !isAbsolute11(rel);
@@ -118883,7 +119000,7 @@ function indexShadowBody(store, file, body) {
118883
119000
  }
118884
119001
 
118885
119002
  // src/index-store/area-pass.ts
118886
- import { createHash as createHash40 } from "crypto";
119003
+ import { createHash as createHash41 } from "crypto";
118887
119004
  var ARCHITECTURE_KEY = "::project";
118888
119005
  var MIN_AREA_FILES = 2;
118889
119006
  var AREA_INPUT_CAP = 6e3;
@@ -118945,7 +119062,7 @@ async function runAreaPass(index, deps) {
118945
119062
  return result;
118946
119063
  }
118947
119064
  function hashLines(lines) {
118948
- return createHash40("sha256").update([...lines].sort().join("\n")).digest("hex");
119065
+ return createHash41("sha256").update([...lines].sort().join("\n")).digest("hex");
118949
119066
  }
118950
119067
  function buildAreaPrompt(area, entries) {
118951
119068
  let body = "";
@@ -119135,9 +119252,9 @@ function triv(kind) {
119135
119252
  }
119136
119253
 
119137
119254
  // src/index-store/hash.ts
119138
- import { createHash as createHash41 } from "crypto";
119255
+ import { createHash as createHash42 } from "crypto";
119139
119256
  function sha2564(data) {
119140
- return createHash41("sha256").update(data).digest("hex");
119257
+ return createHash42("sha256").update(data).digest("hex");
119141
119258
  }
119142
119259
 
119143
119260
  // src/index-store/artifacts-indexer.ts
@@ -124048,7 +124165,7 @@ ${body}\r
124048
124165
  }
124049
124166
 
124050
124167
  // src/mail/mime.ts
124051
- import { createHash as createHash42 } from "crypto";
124168
+ import { createHash as createHash43 } from "crypto";
124052
124169
  import { simpleParser } from "mailparser";
124053
124170
 
124054
124171
  // src/mail/html.ts
@@ -124163,7 +124280,7 @@ function normalizeReferences(refs) {
124163
124280
  }
124164
124281
  function synthesizeMessageId(parsed, ctx) {
124165
124282
  const basis = `${addressText(parsed.from)}|${parsed.subject ?? ""}|${parsed.date?.toISOString() ?? ctx.fallbackDate ?? ""}|${ctx.id}`;
124166
- return `<${createHash42("sha256").update(basis).digest("hex").slice(0, 32)}@gezel.local>`;
124283
+ return `<${createHash43("sha256").update(basis).digest("hex").slice(0, 32)}@gezel.local>`;
124167
124284
  }
124168
124285
  async function parseRawMessage(raw, ctx) {
124169
124286
  const parsed = await simpleParser(raw);
@@ -124786,7 +124903,7 @@ async function migrateOversightTask(store, num) {
124786
124903
 
124787
124904
  // src/memory/compaction.ts
124788
124905
  init_atomic();
124789
- import { createHash as createHash43 } from "crypto";
124906
+ import { createHash as createHash44 } from "crypto";
124790
124907
  import { readFile as readFile77 } from "fs/promises";
124791
124908
  import { join as join101 } from "path";
124792
124909
  import { createLogger as createLogger160, isProactiveAllowed as isProactiveAllowed5 } from "@bendyline/gezel";
@@ -124998,7 +125115,7 @@ var MemoryCompactor = class {
124998
125115
  }
124999
125116
  }
125000
125117
  if (entries.length < minEntries) return false;
125001
- const inputHash = createHash43("sha256").update(eligibleDays.map((d) => `${d}
125118
+ const inputHash = createHash44("sha256").update(eligibleDays.map((d) => `${d}
125002
125119
  ${dayContents.get(d)}`).join("\n")).digest("hex");
125003
125120
  const state = await this.readState(scope, id);
125004
125121
  if (state.inputHash === inputHash) return false;
@@ -125104,7 +125221,7 @@ ${dayContents.get(d)}`).join("\n")).digest("hex");
125104
125221
  const notes = await this.memory.getRecent("gezel", gezelId, lookbackDays);
125105
125222
  if (!notes.trim()) return;
125106
125223
  const current = await this.store.readMemoryLessons(gezelId);
125107
- const lessonsInputHash = createHash43("sha256").update(`${notes}
125224
+ const lessonsInputHash = createHash44("sha256").update(`${notes}
125108
125225
  ---
125109
125226
  ${current}`).digest("hex");
125110
125227
  const state = await this.readState("gezel", gezelId);
@@ -125874,6 +125991,7 @@ var LlamaVisionProvider = class {
125874
125991
  await mkdir57(itemDir, { recursive: true });
125875
125992
  const totalAllBytes = spec.files.reduce((n, f) => n + f.approxSizeBytes, 0);
125876
125993
  let writtenAll = 0;
125994
+ const verifiedDigests = {};
125877
125995
  for (const file of spec.files) {
125878
125996
  const result = yield* downloadWithSha256(this.fetchImpl, {
125879
125997
  url: file.downloadUrl,
@@ -125889,8 +126007,9 @@ var LlamaVisionProvider = class {
125889
126007
  return;
125890
126008
  }
125891
126009
  writtenAll = result.writtenAll;
126010
+ verifiedDigests[file.filename] = file.sha256.toLowerCase();
125892
126011
  }
125893
- const fileSha256 = await hashModelPayloadFiles(itemDir);
126012
+ const fileSha256 = await hashModelPayloadFiles(itemDir, verifiedDigests);
125894
126013
  await writeFile26(
125895
126014
  join104(itemDir, "manifest.json"),
125896
126015
  `${JSON.stringify(
@@ -126310,7 +126429,7 @@ async function* runGgufInstallWithCompanion(catalogId, o, deps) {
126310
126429
  yield event;
126311
126430
  }
126312
126431
  if (!finished) return;
126313
- yield* companionRecognitionEvents(catalogId, deps);
126432
+ if (o.installCompanion) yield* companionRecognitionEvents(catalogId, deps);
126314
126433
  yield finished;
126315
126434
  }
126316
126435
  async function* companionRecognitionEvents(catalogId, deps) {
@@ -127618,7 +127737,7 @@ function makeActionable(message) {
127618
127737
  }
127619
127738
 
127620
127739
  // src/providers/image/sd-cpp.ts
127621
- import { createHash as createHash44 } from "crypto";
127740
+ import { createHash as createHash45 } from "crypto";
127622
127741
  import { createReadStream as createReadStream10 } from "fs";
127623
127742
  import { mkdir as mkdir60, readFile as readFile81, rename as rename15, rm as rm41, writeFile as writeFile29 } from "fs/promises";
127624
127743
  import { join as join110 } from "path";
@@ -127957,7 +128076,7 @@ var StableDiffusionCppProvider = class {
127957
128076
  }
127958
128077
  }
127959
128078
  const partialPath = `${destPath}.partial`;
127960
- const hasher = createHash44("sha256");
128079
+ const hasher = createHash45("sha256");
127961
128080
  await new Promise((resolve18, reject) => {
127962
128081
  const stream = createReadStream10(partialPath, {
127963
128082
  highWaterMark: MODEL_HASH_READ_BUFFER_BYTES
@@ -128476,7 +128595,7 @@ function isMachineImageProvider(config, env) {
128476
128595
  }
128477
128596
 
128478
128597
  // src/providers/recognition/store.ts
128479
- import { createHash as createHash45 } from "crypto";
128598
+ import { createHash as createHash46 } from "crypto";
128480
128599
  import { mkdir as mkdir61, readFile as readFile82, rename as rename16, rm as rm42, writeFile as writeFile30 } from "fs/promises";
128481
128600
  import { join as join112 } from "path";
128482
128601
  import { ImageRecognitionSchema, createLogger as createLogger172 } from "@bendyline/gezel";
@@ -128488,8 +128607,8 @@ var RecognitionCache = class {
128488
128607
  this.root = join112(opts.home, "recognition");
128489
128608
  }
128490
128609
  keyFor(input) {
128491
- const imageHash = createHash45("sha256").update(input.bytes).digest("hex");
128492
- return createHash45("sha256").update(`${imageHash}\0${input.mode}\0${input.modelId}\0v${PROMPT_VERSION}`).digest("hex");
128610
+ const imageHash = createHash46("sha256").update(input.bytes).digest("hex");
128611
+ return createHash46("sha256").update(`${imageHash}\0${input.mode}\0${input.modelId}\0v${PROMPT_VERSION}`).digest("hex");
128493
128612
  }
128494
128613
  pathFor(key) {
128495
128614
  return join112(this.root, key.slice(0, 2), `${key}.json`);
@@ -128934,7 +129053,7 @@ var MockVideoProvider = class {
128934
129053
  };
128935
129054
 
128936
129055
  // src/providers/video/models.ts
128937
- import { createHash as createHash46 } from "crypto";
129056
+ import { createHash as createHash47 } from "crypto";
128938
129057
  import { createReadStream as createReadStream11 } from "fs";
128939
129058
  import { mkdir as mkdir62, readFile as readFile83, rename as rename17, rm as rm43, writeFile as writeFile31 } from "fs/promises";
128940
129059
  import { dirname as dirname50, join as join113 } from "path";
@@ -129207,7 +129326,7 @@ var VideoModelManager = class {
129207
129326
  }
129208
129327
  }
129209
129328
  push({ type: "verifying", file: file.name });
129210
- const hasher = createHash46("sha256");
129329
+ const hasher = createHash47("sha256");
129211
129330
  await new Promise((resolve18, reject) => {
129212
129331
  const stream = createReadStream11(tmpPath, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
129213
129332
  stream.on("data", (chunk2) => hasher.update(chunk2));
@@ -133480,11 +133599,18 @@ var TaskRunner = class {
133480
133599
  /** Run one serialized dispatch pass now, sharing the interval's overlap guard. */
133481
133600
  async wake() {
133482
133601
  if (this.tickInFlight) return this.tickInFlight;
133483
- this.tickInFlight = this.tick().finally(() => {
133602
+ this.tickInFlight = this.tickOnce().finally(() => {
133484
133603
  this.tickInFlight = null;
133485
133604
  });
133486
133605
  return this.tickInFlight;
133487
133606
  }
133607
+ /**
133608
+ * Public test/operator entry point. Keep it serialized with the interval:
133609
+ * callers may drive a real, already-started service whose ticker is active.
133610
+ */
133611
+ async tick() {
133612
+ return this.wake();
133613
+ }
133488
133614
  /**
133489
133615
  * Scan every `active` task and enqueue a handoff for any whose
133490
133616
  * current step has an effective gezel owner. Call on service boot and
@@ -133531,9 +133657,9 @@ var TaskRunner = class {
133531
133657
  /**
133532
133658
  * One dispatch pass. Walks pending in FIFO order; dispatches any
133533
133659
  * whose target provider has a free slot; skips items for tasks
133534
- * that are no longer active. Public for test-driven ticks.
133660
+ * that are no longer active.
133535
133661
  */
133536
- async tick() {
133662
+ async tickOnce() {
133537
133663
  await this.pruneActiveDispatches();
133538
133664
  if (this.pending.length === 0) {
133539
133665
  this.holdReason = void 0;
@@ -133545,6 +133671,7 @@ var TaskRunner = class {
133545
133671
  return;
133546
133672
  }
133547
133673
  const snapshot = this.pending.slice();
133674
+ const snapshotIds = new Set(snapshot.map((handoff) => handoff.id));
133548
133675
  const keep = [];
133549
133676
  const inTickDispatches = /* @__PURE__ */ new Map();
133550
133677
  const nightShiftOn = this.isNightShiftActive();
@@ -133633,8 +133760,9 @@ var TaskRunner = class {
133633
133760
  );
133634
133761
  }
133635
133762
  }
133763
+ const enqueuedDuringTick = this.pending.filter((handoff) => !snapshotIds.has(handoff.id));
133636
133764
  this.pending.length = 0;
133637
- this.pending.push(...keep);
133765
+ this.pending.push(...keep, ...enqueuedDuringTick);
133638
133766
  this.holdReason = keep.some((handoff) => handoff.heldFor === "provider-busy") ? "provider-busy" : void 0;
133639
133767
  }
133640
133768
  async pruneActiveDispatches() {