@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
@@ -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 {
@@ -11758,7 +11758,7 @@ var ChatEventBus = class {
11758
11758
  };
11759
11759
 
11760
11760
  // src/chat/manager.ts
11761
- import { randomUUID as randomUUID7 } from "crypto";
11761
+ import { createHash as createHash12, randomUUID as randomUUID7 } from "crypto";
11762
11762
  import { createRequire } from "module";
11763
11763
  import { join as join28 } from "path";
11764
11764
  import {
@@ -27074,7 +27074,12 @@ var LlamaCppSession = class extends StreamingSessionBase {
27074
27074
  if (toolCalls.length > 0) {
27075
27075
  const normalized2 = normalizeMalformedStructuredToolCalls(
27076
27076
  toolCalls,
27077
- collectKnownToolNames()
27077
+ collectKnownToolNames(),
27078
+ // A malformed write at the output ceiling is not repairable: the
27079
+ // missing JSON tail may also be missing file bytes. Executing the
27080
+ // loose prefix can silently replace a complete file with a
27081
+ // truncated one. Valid, fully parseable calls remain eligible.
27082
+ finishReason !== "length"
27078
27083
  );
27079
27084
  toolCalls = normalized2.toolCalls;
27080
27085
  malformedStructuredCallIds = new Set(normalized2.sanitizedIds);
@@ -27951,7 +27956,7 @@ var ToolCallAccumulator = class {
27951
27956
  }));
27952
27957
  }
27953
27958
  };
27954
- function normalizeMalformedStructuredToolCalls(toolCalls, knownToolNames) {
27959
+ function normalizeMalformedStructuredToolCalls(toolCalls, knownToolNames, allowMalformedWriteRepair = true) {
27955
27960
  const repaired = [];
27956
27961
  const sanitized = [];
27957
27962
  const sanitizedIds = [];
@@ -27962,11 +27967,7 @@ function normalizeMalformedStructuredToolCalls(toolCalls, knownToolNames) {
27962
27967
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return call;
27963
27968
  } catch {
27964
27969
  }
27965
- const repairedArgs = tryRepairMalformedWriteToolArguments(
27966
- call.function.name,
27967
- raw,
27968
- knownToolNames
27969
- );
27970
+ const repairedArgs = allowMalformedWriteRepair ? tryRepairMalformedWriteToolArguments(call.function.name, raw, knownToolNames) : null;
27970
27971
  if (repairedArgs) {
27971
27972
  repaired.push({
27972
27973
  name: call.function.name,
@@ -32128,6 +32129,7 @@ function buildLlamaCppEngineArgs(input) {
32128
32129
  ggufHasMtp,
32129
32130
  installedDraftModelPath,
32130
32131
  reasoningFormat,
32132
+ reasoningPreserve,
32131
32133
  architecture,
32132
32134
  modelId,
32133
32135
  swaFullAutoFits
@@ -32175,6 +32177,7 @@ function buildLlamaCppEngineArgs(input) {
32175
32177
  if (typeof nMax === "number") args.push("--spec-draft-n-max", String(nMax));
32176
32178
  }
32177
32179
  if (reasoningFormat) args.push("--reasoning-format", reasoningFormat);
32180
+ if (reasoningPreserve) args.push("--reasoning-preserve");
32178
32181
  if (config.llamaCppExtraArgs) {
32179
32182
  for (const [rawKey, value] of Object.entries(config.llamaCppExtraArgs)) {
32180
32183
  if (value === false) continue;
@@ -32495,6 +32498,31 @@ function fitsSwaFullInFastMemory(input) {
32495
32498
  return Number.isFinite(required) && Number.isFinite(available) && required <= available;
32496
32499
  }
32497
32500
 
32501
+ // src/providers/llama-cpp/reasoning-launch.ts
32502
+ var POSITIVE_INTEGER = /^[1-9]\d*$/;
32503
+ function parseReasoningPreserveEnv(raw) {
32504
+ const normalized2 = raw?.trim().toLowerCase();
32505
+ return normalized2 === "1" || normalized2 === "true";
32506
+ }
32507
+ function parseReasoningBudgetEnv(raw) {
32508
+ const normalized2 = raw?.trim();
32509
+ if (!normalized2) return void 0;
32510
+ if (!POSITIVE_INTEGER.test(normalized2)) {
32511
+ throw new Error("GEZEL_LLAMA_REASONING_BUDGET_TOKENS must be a positive integer");
32512
+ }
32513
+ const parsed = Number(normalized2);
32514
+ if (!Number.isSafeInteger(parsed)) {
32515
+ throw new Error("GEZEL_LLAMA_REASONING_BUDGET_TOKENS exceeds the safe integer range");
32516
+ }
32517
+ return parsed;
32518
+ }
32519
+ function reasoningLaunchOverridesFromEnv(env = process.env) {
32520
+ return {
32521
+ preserve: parseReasoningPreserveEnv(env.GEZEL_LLAMA_REASONING_PRESERVE),
32522
+ budgetTokens: parseReasoningBudgetEnv(env.GEZEL_LLAMA_REASONING_BUDGET_TOKENS)
32523
+ };
32524
+ }
32525
+
32498
32526
  // src/providers/llama-cpp/spec-draft.ts
32499
32527
  async function resolveSpecDraft(input) {
32500
32528
  const { perModel, configSpecType, configDraftModelPath, resolveDraftPath } = input;
@@ -32553,6 +32581,8 @@ async function buildLlamaCppProvider(opts) {
32553
32581
  const { config, affinity, home } = opts;
32554
32582
  const externalBaseUrl = opts.modelOverride ? void 0 : process.env.GEZEL_LLAMA_SERVER_URL ?? config.llamaCppBaseUrl;
32555
32583
  const binary = process.env.GEZEL_LLAMA_SERVER_BIN;
32584
+ const reasoningLaunchOverrides = reasoningLaunchOverridesFromEnv();
32585
+ const reasoningPreserve = reasoningLaunchOverrides.preserve;
32556
32586
  const defaultModelId = opts.modelOverride?.modelId ?? config.defaultModel?.["llama-cpp"];
32557
32587
  const configuredSlots = config.providerConcurrency?.["llama-cpp"];
32558
32588
  const envNumCtx = (() => {
@@ -32575,6 +32605,7 @@ async function buildLlamaCppProvider(opts) {
32575
32605
  // rate for its own default engine — throughput was reachable only by
32576
32606
  // scraping stdout from the eval harness.
32577
32607
  includeUsageInStream: true,
32608
+ replayReasoningContent: reasoningPreserve,
32578
32609
  // External-baseUrl default; the supervised path overrides this with the
32579
32610
  // auto-sized `slots` computed below (after the model resolves).
32580
32611
  concurrency: configuredSlots ?? 2,
@@ -32765,10 +32796,12 @@ async function buildLlamaCppProvider(opts) {
32765
32796
  const slotSavePath = replicaSuffix ? join18(llamaCacheRoot, llamaFingerprint, replicaSuffix) : join18(llamaCacheRoot, llamaFingerprint);
32766
32797
  await mkdirAsync(slotSavePath, { recursive: true }).catch(() => {
32767
32798
  });
32768
- const reasoningBudgetTokens = opts.catalog ? await resolveCatalogReasoningBudget(
32799
+ const catalogReasoningBudgetTokens = opts.catalog ? await resolveCatalogReasoningBudget(
32769
32800
  opts.catalog,
32770
32801
  opts.modelOverride?.modelId ?? defaultModelId
32771
32802
  ) : void 0;
32803
+ const reasoningBudgetTokens = reasoningLaunchOverrides.budgetTokens ?? catalogReasoningBudgetTokens;
32804
+ const reasoningBudgetSource = reasoningLaunchOverrides.budgetTokens !== void 0 ? "env" : catalogReasoningBudgetTokens !== void 0 ? "catalog" : "unbounded";
32772
32805
  const specDraft = await resolveSpecDraft({
32773
32806
  perModel: manifestEngineConfig,
32774
32807
  configSpecType: config.llamaCppSpecType,
@@ -33158,6 +33191,7 @@ async function buildLlamaCppProvider(opts) {
33158
33191
  // disables llama-server's chat-template output parsing so mangled
33159
33192
  // model output reaches `delta.content` for provider-side salvage.
33160
33193
  reasoningFormat: process.env.GEZEL_LLAMA_REASONING_FORMAT?.trim() || void 0,
33194
+ reasoningPreserve,
33161
33195
  architecture: modelCatalogInfo?.architecture,
33162
33196
  modelId: defaultModelId ?? void 0,
33163
33197
  swaFullAutoFits
@@ -33266,6 +33300,9 @@ async function buildLlamaCppProvider(opts) {
33266
33300
  batchSize: lastArgValue(resolvedAdvancedArgs, "--batch-size") ?? "default",
33267
33301
  ubatchSize: lastArgValue(resolvedAdvancedArgs, "--ubatch-size") ?? "default",
33268
33302
  flashAttention: lastArgValue(resolvedAdvancedArgs, "--flash-attn") ?? "default",
33303
+ reasoningBudgetTokens: reasoningBudgetTokens ?? "unbounded",
33304
+ reasoningBudgetSource,
33305
+ reasoningPreserve,
33269
33306
  cudaGraphs: process.env.GGML_CUDA_DISABLE_GRAPHS ? "disabled-by-env" : "default"
33270
33307
  },
33271
33308
  env: {
@@ -36054,14 +36091,14 @@ async function buildMlxProvider(opts) {
36054
36091
  const cacheBudgetMb = Math.min(config.cacheBudgetMb?.mlx ?? ramAwareDefaultMb, mlxKvHeadroomMb);
36055
36092
  const mlxReplicaSuffix = opts.modelOverride && opts.modelOverride.replicaIdx > 0 ? `replica-${opts.modelOverride.replicaIdx}` : "";
36056
36093
  const cacheRoot = mlxReplicaSuffix ? join21(store.homePath, "engines", "mlx", "cache", mlxReplicaSuffix) : join21(store.homePath, "engines", "mlx", "cache");
36057
- const { createHash: createHash47 } = await import("crypto");
36094
+ const { createHash: createHash48 } = await import("crypto");
36058
36095
  const fingerprintInput = [
36059
36096
  modelCatalogInfo?.id ?? defaultModelId ?? modelDir,
36060
36097
  modelCatalogInfo?.catalogVersion ?? "",
36061
36098
  modelCatalogInfo?.installedAt ?? "",
36062
36099
  modelDir
36063
36100
  ].join("::");
36064
- const modelFingerprint = createHash47("sha256").update(fingerprintInput, "utf8").digest("hex").slice(0, 24);
36101
+ const modelFingerprint = createHash48("sha256").update(fingerprintInput, "utf8").digest("hex").slice(0, 24);
36065
36102
  const diskCacheBudgetMb = config.mlxDiskCacheBudgetMb ?? 8192;
36066
36103
  const mlxIdleMs = config.localEngineIdleTimeoutMs ?? DEFAULT_LOCAL_ENGINE_IDLE_TIMEOUT_MS3;
36067
36104
  const mlxFreezeMs = Math.floor(mlxIdleMs / 2);
@@ -46659,10 +46696,12 @@ var ChatManager = class {
46659
46696
  */
46660
46697
  afterSessionIdle = /* @__PURE__ */ new Map();
46661
46698
  /**
46662
- * One live async file handoff per sender/target/project/path. Models can
46699
+ * One live async file handoff per sender/target/project/path/intent. Models can
46663
46700
  * emit the same `message_gezel` call several times while the sender turn
46664
46701
  * is still active; joining that work prevents a parked-send burst from
46665
- * replaying the same assignment into the recipient session.
46702
+ * replaying the same assignment into the recipient session. A later
46703
+ * validator repair for a file that was originally missing is distinct work
46704
+ * and must never join the older create request.
46666
46705
  */
46667
46706
  inflightFileHandoffs = /* @__PURE__ */ new Map();
46668
46707
  /** Set once {@link shutdown} starts so deferred watchdogs don't fire into a tearing-down manager. */
@@ -48542,7 +48581,8 @@ ${stepArc}
48542
48581
  args.fromSessionId ?? args.fromGezelId,
48543
48582
  target.id,
48544
48583
  projectId,
48545
- normalizeExpectedDeliverablePath(requestedFilePath)
48584
+ normalizeExpectedDeliverablePath(requestedFilePath),
48585
+ fileHandoffIntentKey(args.text)
48546
48586
  ].join("\0") : null;
48547
48587
  const pendingHandoff = fileHandoffKey ? this.inflightFileHandoffs.get(fileHandoffKey) : void 0;
48548
48588
  if (pendingHandoff) return { ...pendingHandoff, deduplicated: true };
@@ -48583,7 +48623,7 @@ ${stepArc}
48583
48623
  const seed = `[Message from ${fromName}]: ${args.text}${deliverableAnnotation}`;
48584
48624
  const failureNotice = { sent: false };
48585
48625
  const resolvedFromSessionId = args.fromSessionId ?? (target.id === args.fromGezelId ? null : await this.ensureOrCreateSession({ gezelId: args.fromGezelId, projectId }).then((s) => s.id).catch(() => null));
48586
- if (resolvedFromSessionId && resolvedFromSessionId !== session.id) {
48626
+ if (!args.suppressReply && resolvedFromSessionId && resolvedFromSessionId !== session.id) {
48587
48627
  this.attachReplyListener({
48588
48628
  targetSessionId: session.id,
48589
48629
  fromSessionId: resolvedFromSessionId,
@@ -50026,20 +50066,36 @@ ${peek.userText}`;
50026
50066
  return this.runFixedFunctionSend(sessionId2, userText, opts);
50027
50067
  }
50028
50068
  }
50069
+ const preflightScope = ffRecord ? {
50070
+ sessionId: sessionId2,
50071
+ gezelId: ffRecord.gezelId,
50072
+ projectId: ffRecord.projectId
50073
+ } : void 0;
50074
+ const coldStartPending = preflightScope && !this.states.get(sessionId2)?.session;
50075
+ if (preflightScope && coldStartPending) {
50076
+ this.events.publish(preflightScope, {
50077
+ type: "user_message_pending",
50078
+ preview: userText.length > 160 ? `${userText.slice(0, 157)}\u2026` : userText
50079
+ });
50080
+ }
50029
50081
  const fail2 = (err) => {
50030
50082
  const message = err instanceof Error ? err.message : String(err);
50031
50083
  log52.error("error:", message);
50084
+ const publish = (event) => {
50085
+ if (preflightScope) this.events.publish(preflightScope, event);
50086
+ else this.events.publishSessionOnly(sessionId2, event);
50087
+ };
50032
50088
  if (inflightTurn.cancelled) {
50033
- this.events.publishSessionOnly(sessionId2, { type: "cancelled" });
50089
+ publish({ type: "cancelled" });
50034
50090
  } else {
50035
50091
  const detail = describeTurnError(err);
50036
- this.events.publishSessionOnly(sessionId2, {
50092
+ publish({
50037
50093
  type: "error",
50038
50094
  error: redactCredentials4(message),
50039
50095
  ...detail ? { errorDetail: detail } : {}
50040
50096
  });
50041
50097
  }
50042
- this.events.publishSessionOnly(sessionId2, { type: "done" });
50098
+ publish({ type: "done" });
50043
50099
  throw err;
50044
50100
  };
50045
50101
  if (ffRecord) {
@@ -56356,6 +56412,14 @@ function messageExpressesModifyIntent(text) {
56356
56412
  )
56357
56413
  );
56358
56414
  }
56415
+ function fileHandoffIntentKey(text) {
56416
+ 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(
56417
+ text
56418
+ );
56419
+ if (!repair) return "create";
56420
+ const normalized2 = text.toLowerCase().replace(/\s+/g, " ").trim();
56421
+ return `repair:${createHash12("sha256").update(normalized2).digest("hex").slice(0, 16)}`;
56422
+ }
56359
56423
  function isSubstantiveExistingWorkspaceFile(filePath2, content) {
56360
56424
  const trimmed = content.trim();
56361
56425
  if (!trimmed) return false;
@@ -56852,7 +56916,7 @@ function growthSignature(gezel) {
56852
56916
 
56853
56917
  // src/codex-setup/manager.ts
56854
56918
  init_atomic();
56855
- import { createHash as createHash12 } from "crypto";
56919
+ import { createHash as createHash13 } from "crypto";
56856
56920
  import { realpathSync as realpathSync2 } from "fs";
56857
56921
  import { chmod as chmod4, mkdir as mkdir15, readFile as readFile16, rm as rm6 } from "fs/promises";
56858
56922
  import { homedir as homedir3 } from "os";
@@ -57603,7 +57667,7 @@ function canonicalPath(path2) {
57603
57667
  }
57604
57668
  }
57605
57669
  function sha256(value) {
57606
- return createHash12("sha256").update(value).digest("hex");
57670
+ return createHash13("sha256").update(value).digest("hex");
57607
57671
  }
57608
57672
  function catalogModelFor(model) {
57609
57673
  const contextWindow = model.contextWindow ?? 32768;
@@ -58028,7 +58092,7 @@ init_mcp_bridge();
58028
58092
 
58029
58093
  // src/connectors/writer.ts
58030
58094
  init_atomic();
58031
- import { createHash as createHash13 } from "crypto";
58095
+ import { createHash as createHash14 } from "crypto";
58032
58096
  import { mkdir as mkdir16, readFile as readFile17, readdir as readdir9, rm as rm7, stat as stat11 } from "fs/promises";
58033
58097
  import { basename as basename7, join as join30 } from "path";
58034
58098
  import { projectLocalQuarantineDir } from "@bendyline/gezel/paths";
@@ -58301,7 +58365,7 @@ var StaticContentScanner = class {
58301
58365
  var contentScanner = new StaticContentScanner();
58302
58366
 
58303
58367
  // src/connectors/writer.ts
58304
- var sha8 = (s) => createHash13("sha256").update(s).digest("hex").slice(0, 8);
58368
+ var sha8 = (s) => createHash14("sha256").update(s).digest("hex").slice(0, 8);
58305
58369
  function slug(input, max = 48) {
58306
58370
  const s = input.normalize("NFKD").replace(/[^\x20-\x7E]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, max).replace(/-+$/g, "");
58307
58371
  return s || "x";
@@ -58318,7 +58382,7 @@ function contentHash(record) {
58318
58382
  const attachments = (record.attachments ?? []).map((attachment) => ({
58319
58383
  filename: attachment.filename,
58320
58384
  size: attachment.size ?? attachment.content?.byteLength ?? 0,
58321
- sha256: attachment.sha256 ?? createHash13("sha256").update(attachment.content).digest("hex")
58385
+ sha256: attachment.sha256 ?? createHash14("sha256").update(attachment.content).digest("hex")
58322
58386
  }));
58323
58387
  return sha8(
58324
58388
  `${JSON.stringify(sortedFrontmatter)}
@@ -59389,10 +59453,10 @@ var SpectralConnectorAdapter = class {
59389
59453
  };
59390
59454
 
59391
59455
  // src/connectors/oauth.ts
59392
- import { createHash as createHash14, randomBytes as randomBytes3 } from "crypto";
59456
+ import { createHash as createHash15, randomBytes as randomBytes3 } from "crypto";
59393
59457
  function createPkce() {
59394
59458
  const verifier = randomBytes3(32).toString("base64url");
59395
- const challenge = createHash14("sha256").update(verifier).digest("base64url");
59459
+ const challenge = createHash15("sha256").update(verifier).digest("base64url");
59396
59460
  return { verifier, challenge };
59397
59461
  }
59398
59462
  function randomState() {
@@ -64077,7 +64141,7 @@ function registerGitHubPullsAdapters(runtime) {
64077
64141
  }
64078
64142
 
64079
64143
  // src/connectors/natives/github-releases.ts
64080
- import { createHash as createHash15 } from "crypto";
64144
+ import { createHash as createHash16 } from "crypto";
64081
64145
  import { mkdir as mkdir21, mkdtemp as mkdtemp3, open as open2, rm as rm13 } from "fs/promises";
64082
64146
  import { tmpdir as tmpdir3 } from "os";
64083
64147
  import { basename as basename8, join as join35 } from "path";
@@ -64270,7 +64334,7 @@ var GitHubReleasesAdapter = class {
64270
64334
  }
64271
64335
  }
64272
64336
  this.releases = releases;
64273
- this.fingerprint = createHash15("sha256").update(JSON.stringify(releases)).digest("hex");
64337
+ this.fingerprint = createHash16("sha256").update(JSON.stringify(releases)).digest("hex");
64274
64338
  }
64275
64339
  apiHeaders(accept) {
64276
64340
  return {
@@ -64333,7 +64397,7 @@ var GitHubReleasesAdapter = class {
64333
64397
  };
64334
64398
  async function streamResponseToFile(response, path2) {
64335
64399
  const handle = await open2(path2, "wx");
64336
- const hash = createHash15("sha256");
64400
+ const hash = createHash16("sha256");
64337
64401
  let size = 0;
64338
64402
  try {
64339
64403
  for await (const raw of response.body) {
@@ -66713,7 +66777,7 @@ var DebugFlag = class {
66713
66777
 
66714
66778
  // src/digest/generator.ts
66715
66779
  init_atomic();
66716
- import { createHash as createHash16 } from "crypto";
66780
+ import { createHash as createHash17 } from "crypto";
66717
66781
  import { readFile as readFile25 } from "fs/promises";
66718
66782
  import { join as join40 } from "path";
66719
66783
  import {
@@ -69862,7 +69926,7 @@ var ProjectDigestGenerator = class {
69862
69926
  if (commits.length === 0 && sessions.length === 0 && events.length < MIN_EVENTS_FOR_DIGEST) {
69863
69927
  return false;
69864
69928
  }
69865
- const inputHash = createHash16("sha256").update(
69929
+ const inputHash = createHash17("sha256").update(
69866
69930
  [
69867
69931
  week,
69868
69932
  ...commits,
@@ -70019,7 +70083,7 @@ function describe4(err) {
70019
70083
  }
70020
70084
 
70021
70085
  // src/engines/electron-native-reuse.ts
70022
- import { createHash as createHash17 } from "crypto";
70086
+ import { createHash as createHash18 } from "crypto";
70023
70087
  import { createReadStream as createReadStream3 } from "fs";
70024
70088
  import { lstat as lstat2, readdir as readdir13, readlink } from "fs/promises";
70025
70089
  import { basename as basename11, join as join41, posix, relative as relative5, resolve as resolve8, sep as sep5 } from "path";
@@ -71639,7 +71703,7 @@ function enclosingMacApp(path2) {
71639
71703
  var HASH_READ_BUFFER_BYTES = 16 * 1024 * 1024;
71640
71704
  function sha256File2(path2) {
71641
71705
  return new Promise((resolveHash, reject) => {
71642
- const hash = createHash17("sha256");
71706
+ const hash = createHash18("sha256");
71643
71707
  const stream = createReadStream3(path2, { highWaterMark: HASH_READ_BUFFER_BYTES });
71644
71708
  stream.on("data", (chunk2) => hash.update(chunk2));
71645
71709
  stream.on("error", reject);
@@ -71651,7 +71715,7 @@ function sha256File2(path2) {
71651
71715
  import { createLogger as createLogger69 } from "@bendyline/gezel";
71652
71716
 
71653
71717
  // src/engines/resolver.ts
71654
- import { createHash as createHash18 } from "crypto";
71718
+ import { createHash as createHash19 } from "crypto";
71655
71719
  import { createReadStream as createReadStream4, existsSync as existsSync7 } from "fs";
71656
71720
  import { chmod as chmod5, mkdir as mkdir24, readFile as readFile26, rename as rename7, rm as rm16, writeFile as writeFile9 } from "fs/promises";
71657
71721
  import { join as join42 } from "path";
@@ -71775,7 +71839,7 @@ async function* resolveEngine(opts) {
71775
71839
  );
71776
71840
  }
71777
71841
  const sumsBytes = await ghBytes(sumsAsset.url, baseFetch, token);
71778
- const sumsDigest = createHash18("sha256").update(sumsBytes).digest("hex");
71842
+ const sumsDigest = createHash19("sha256").update(sumsBytes).digest("hex");
71779
71843
  if (!unpinned && sumsDigest !== expectedDigest) {
71780
71844
  yield* fail(
71781
71845
  `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.`
@@ -72025,7 +72089,7 @@ function parseSums(text) {
72025
72089
  }
72026
72090
  var HASH_READ_BUFFER_BYTES2 = 16 * 1024 * 1024;
72027
72091
  async function sha256File3(path2) {
72028
- const hash = createHash18("sha256");
72092
+ const hash = createHash19("sha256");
72029
72093
  await new Promise((resolve19, reject) => {
72030
72094
  const stream = createReadStream4(path2, { highWaterMark: HASH_READ_BUFFER_BYTES2 });
72031
72095
  stream.on("data", (chunk2) => hash.update(chunk2));
@@ -72908,7 +72972,7 @@ function safeBasename(name) {
72908
72972
  }
72909
72973
 
72910
72974
  // src/fs/store.ts
72911
- import { createHash as createHash20, randomUUID as randomUUID10 } from "crypto";
72975
+ import { createHash as createHash21, randomUUID as randomUUID10 } from "crypto";
72912
72976
  import {
72913
72977
  appendFile as appendFile4,
72914
72978
  chmod as chmod7,
@@ -73317,7 +73381,7 @@ function countDiffLines(diff) {
73317
73381
  }
73318
73382
 
73319
73383
  // src/workspace/journal.ts
73320
- import { createHash as createHash19 } from "crypto";
73384
+ import { createHash as createHash20 } from "crypto";
73321
73385
  import { appendFile as appendFile2, mkdir as mkdir27, readFile as readFile29 } from "fs/promises";
73322
73386
  import { dirname as dirname26, join as join43 } from "path";
73323
73387
  import { projectPrivateDir as projectPrivateDir2 } from "@bendyline/gezel/paths";
@@ -73360,7 +73424,7 @@ async function readJournalTail(home, projectId, limit = 100) {
73360
73424
  }
73361
73425
  }
73362
73426
  function sha2562(content) {
73363
- return createHash19("sha256").update(content).digest("hex");
73427
+ return createHash20("sha256").update(content).digest("hex");
73364
73428
  }
73365
73429
 
73366
73430
  // src/workspace/template.ts
@@ -74227,7 +74291,7 @@ function boekwachterIssueFingerprint(path2, issue) {
74227
74291
  issue.category.trim().toLocaleLowerCase(),
74228
74292
  issue.message.trim().toLocaleLowerCase().replace(/\s+/g, " ")
74229
74293
  ].join("\0");
74230
- return createHash20("sha256").update(normalized2).digest("hex");
74294
+ return createHash21("sha256").update(normalized2).digest("hex");
74231
74295
  }
74232
74296
  var ConfigCorruptionError = class extends Error {
74233
74297
  code = "CONFIG_CORRUPT";
@@ -79689,7 +79753,7 @@ import { projectCodeReviewsFile } from "@bendyline/gezel/paths";
79689
79753
  import { createLogger as createLogger77, projectAllowsAmbientWork } from "@bendyline/gezel";
79690
79754
 
79691
79755
  // src/tasks/manager.ts
79692
- import { createHash as createHash21, randomUUID as randomUUID12 } from "crypto";
79756
+ import { createHash as createHash22, randomUUID as randomUUID12 } from "crypto";
79693
79757
  import {
79694
79758
  DEFAULT_NIGHT_SHIFT_WINDOW,
79695
79759
  MANAGED_WORKSPACE_WRITE_SETTING_LABEL as MANAGED_WORKSPACE_WRITE_SETTING_LABEL4,
@@ -81541,7 +81605,7 @@ ${paramLines}` : ""}`,
81541
81605
  if (step.advanceWhen?.file) {
81542
81606
  const content = await (step.advanceWhen.artifact ? this.store.readProjectArtifact(projectId, step.advanceWhen.file) : this.store.readProjectWorkspaceFile(projectId, step.advanceWhen.file)).catch(() => null);
81543
81607
  if (content !== null) {
81544
- contentHash2 = createHash21("sha256").update(content).digest("hex");
81608
+ contentHash2 = createHash22("sha256").update(content).digest("hex");
81545
81609
  }
81546
81610
  }
81547
81611
  if (contentHash2 !== void 0 && step.lastGateReject?.contentHash !== void 0 && step.lastGateReject.contentHash === contentHash2) {
@@ -83208,7 +83272,7 @@ function sumStat(s, key) {
83208
83272
  }
83209
83273
 
83210
83274
  // src/grants/manager.ts
83211
- import { createHash as createHash22, randomBytes as randomBytes5, randomUUID as randomUUID13, timingSafeEqual } from "crypto";
83275
+ import { createHash as createHash23, randomBytes as randomBytes5, randomUUID as randomUUID13, timingSafeEqual } from "crypto";
83212
83276
  import { chmod as chmod8 } from "fs/promises";
83213
83277
  import { pendingGrantsFile as defaultPendingGrantsFile } from "@bendyline/gezel/paths";
83214
83278
  var PENDING_GRANT_TTL_MS = 10 * 6e4;
@@ -83280,7 +83344,7 @@ function generateVerificationCode() {
83280
83344
  return `${raw.slice(0, 3)}-${raw.slice(3)}`;
83281
83345
  }
83282
83346
  function hashVerificationCode(salt, normalizedCode) {
83283
- return createHash22("sha256").update(salt, "base64url").update("\0").update(normalizedCode, "ascii").digest();
83347
+ return createHash23("sha256").update(salt, "base64url").update("\0").update(normalizedCode, "ascii").digest();
83284
83348
  }
83285
83349
  function codeMatches(grant, suppliedCode) {
83286
83350
  const normalized2 = normalizeVerificationCode(suppliedCode);
@@ -85200,7 +85264,7 @@ function tokenize2(question) {
85200
85264
  }
85201
85265
 
85202
85266
  // src/http/cert.ts
85203
- import { createHash as createHash23 } from "crypto";
85267
+ import { createHash as createHash24 } from "crypto";
85204
85268
  import { generate as selfsignedGenerate } from "selfsigned";
85205
85269
  var CERT_VALIDITY_DAYS = 90;
85206
85270
  async function generateLoopbackCert() {
@@ -85237,7 +85301,7 @@ async function generateLoopbackCert() {
85237
85301
  ]
85238
85302
  });
85239
85303
  const der = pemToDer(pems.cert);
85240
- const digest = createHash23("sha256").update(der).digest();
85304
+ const digest = createHash24("sha256").update(der).digest();
85241
85305
  return {
85242
85306
  certPem: pems.cert,
85243
85307
  keyPem: pems.private,
@@ -85251,14 +85315,14 @@ function pemToDer(pem) {
85251
85315
  }
85252
85316
 
85253
85317
  // src/http/codex-bridge-port.ts
85254
- import { createHash as createHash24 } from "crypto";
85318
+ import { createHash as createHash25 } from "crypto";
85255
85319
  import { realpathSync as realpathSync3 } from "fs";
85256
85320
  import { resolve as resolve10 } from "path";
85257
85321
  var CODEX_BRIDGE_PORT_RANGE_START = 2e4;
85258
85322
  var CODEX_BRIDGE_PORT_RANGE_END = 49151;
85259
85323
  var CODEX_BRIDGE_PORT_RANGE_SIZE = CODEX_BRIDGE_PORT_RANGE_END - CODEX_BRIDGE_PORT_RANGE_START + 1;
85260
85324
  function codexBridgePortForHome(home) {
85261
- const digest = createHash24("sha256").update(canonicalPath2(home)).digest();
85325
+ const digest = createHash25("sha256").update(canonicalPath2(home)).digest();
85262
85326
  const bucket = digest.readUInt32BE(0) % CODEX_BRIDGE_PORT_RANGE_SIZE;
85263
85327
  return CODEX_BRIDGE_PORT_RANGE_START + bucket;
85264
85328
  }
@@ -85484,7 +85548,7 @@ async function loadGezelByRef(ref, ctx) {
85484
85548
  import { randomUUID as randomUUID15 } from "crypto";
85485
85549
 
85486
85550
  // src/http/openai-compat/responses-translate.ts
85487
- import { createHash as createHash25 } from "crypto";
85551
+ import { createHash as createHash26 } from "crypto";
85488
85552
  import { z as z11 } from "zod";
85489
85553
 
85490
85554
  // src/http/openai-compat/translate.ts
@@ -85923,7 +85987,7 @@ var CUSTOM_TOOL_INPUT_KEY = "input";
85923
85987
  function flattenResponsesNamespaceToolName(namespace, name) {
85924
85988
  const joined = `${namespace}__${name}`;
85925
85989
  if (joined.length <= MAX_LOCAL_TOOL_NAME_LENGTH) return joined;
85926
- const digest = createHash25("sha256").update(namespace).update("\0").update(name).digest("hex").slice(0, 12);
85990
+ const digest = createHash26("sha256").update(namespace).update("\0").update(name).digest("hex").slice(0, 12);
85927
85991
  const prefixLength = MAX_LOCAL_TOOL_NAME_LENGTH - digest.length - 2;
85928
85992
  return `${joined.slice(0, prefixLength)}__${digest}`;
85929
85993
  }
@@ -87153,7 +87217,7 @@ function mountMachineEngineHints(app) {
87153
87217
  }
87154
87218
 
87155
87219
  // src/http/preview-capability.ts
87156
- import { createHash as createHash26, randomBytes as randomBytes6 } from "crypto";
87220
+ import { createHash as createHash27, randomBytes as randomBytes6 } from "crypto";
87157
87221
  import { posix as posix3 } from "path";
87158
87222
  var DEFAULT_PREVIEW_CAPABILITY_TTL_MS = 10 * 60 * 1e3;
87159
87223
  var DEFAULT_PREVIEW_CAPABILITY_ABSOLUTE_TTL_MS = 2 * 60 * 60 * 1e3;
@@ -87297,7 +87361,7 @@ function pathIsInScope(path2, scopePath) {
87297
87361
  return scopePath === "" || path2 === scopePath || path2.startsWith(`${scopePath}/`);
87298
87362
  }
87299
87363
  function tokenDigest(token) {
87300
- return createHash26("sha256").update(token).digest("base64url");
87364
+ return createHash27("sha256").update(token).digest("base64url");
87301
87365
  }
87302
87366
 
87303
87367
  // src/http/routes/ai.ts
@@ -87666,6 +87730,15 @@ var KOKORO_HF_REPO = "onnx-community/Kokoro-82M-v1.0-ONNX";
87666
87730
  var KOKORO_APPROX_BYTES_BY_ID = {
87667
87731
  [KOKORO_DEFAULT_MODEL_ID]: 95e6
87668
87732
  };
87733
+ function isKokoroRuntimeAvailable(resolveModule = (specifier) => import.meta.resolve(specifier)) {
87734
+ try {
87735
+ resolveModule("kokoro-js");
87736
+ resolveModule("@huggingface/transformers");
87737
+ return true;
87738
+ } catch {
87739
+ return false;
87740
+ }
87741
+ }
87669
87742
  var KOKORO_DEFAULT_VOICES = [
87670
87743
  {
87671
87744
  id: "af_heart",
@@ -87995,7 +88068,7 @@ function parseGender(s) {
87995
88068
  }
87996
88069
 
87997
88070
  // src/providers/audio/whisper-cpp.ts
87998
- import { createHash as createHash27 } from "crypto";
88071
+ import { createHash as createHash28 } from "crypto";
87999
88072
  import { createReadStream as createReadStream5 } from "fs";
88000
88073
  import { mkdir as mkdir37, readFile as readFile39, rename as rename11, rm as rm25, writeFile as writeFile14 } from "fs/promises";
88001
88074
  import { basename as basename12, join as join52 } from "path";
@@ -88290,7 +88363,7 @@ async function* downloadWithSha256(fetchImpl, opts) {
88290
88363
  yield { type: "progress", bytesWritten: writtenAll, totalBytes: totalAllBytes };
88291
88364
  }
88292
88365
  }
88293
- const hasher = createHash27("sha256");
88366
+ const hasher = createHash28("sha256");
88294
88367
  await new Promise((resolve19, reject) => {
88295
88368
  const stream = createReadStream5(tmpPath, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
88296
88369
  stream.on("data", (chunk2) => hasher.update(chunk2));
@@ -88341,6 +88414,41 @@ function machineEngineProxy(ctx, sourcePrefix, targetPrefix, localPaths = [], sh
88341
88414
 
88342
88415
  // src/http/routes/audio.ts
88343
88416
  var log85 = createLogger88("audio");
88417
+ function buildAudioCatalog(options = {}) {
88418
+ const kokoroRuntimeAvailable = options.kokoroRuntimeAvailable ?? isKokoroRuntimeAvailable();
88419
+ return {
88420
+ // All Whisper weights ship under MIT (whisper.cpp / OpenAI Whisper);
88421
+ // Kokoro under Apache 2.0. Both are permissive → "Free, open".
88422
+ stt: WHISPER_MODEL_CATALOG.map((m) => ({
88423
+ id: m.id,
88424
+ name: m.name,
88425
+ description: m.description,
88426
+ approxSizeBytes: m.approxSizeBytes,
88427
+ kind: "stt",
88428
+ license: "MIT",
88429
+ licenseClass: "open",
88430
+ licenseShortName: "MIT",
88431
+ licenseUrl: "https://huggingface.co/ggerganov/whisper.cpp",
88432
+ // The Base (English) variant is the recommended STT default: ~140 MB,
88433
+ // realtime on laptop CPUs. Curated recoScore → ★ badge + auto-pick.
88434
+ ...m.id === "whisper-base.en" ? { recoScore: 20 } : {}
88435
+ })),
88436
+ tts: kokoroRuntimeAvailable ? [
88437
+ {
88438
+ id: KOKORO_DEFAULT_MODEL_ID,
88439
+ name: "Kokoro 82M v1.0",
88440
+ description: "Apache 2.0 TTS \u2014 54+ voices, ~80MB quantized, near-realtime on M1 / modern desktop CPUs.",
88441
+ approxSizeBytes: 95e6,
88442
+ kind: "tts",
88443
+ license: "Apache 2.0",
88444
+ licenseClass: "open",
88445
+ licenseShortName: "Apache 2.0",
88446
+ licenseUrl: "https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX",
88447
+ recoScore: 20
88448
+ }
88449
+ ] : []
88450
+ };
88451
+ }
88344
88452
  function audioRoutes(ctx) {
88345
88453
  const app = new Hono4();
88346
88454
  app.use(
@@ -88462,38 +88570,7 @@ function audioRoutes(ctx) {
88462
88570
  });
88463
88571
  });
88464
88572
  app.get("/catalog", (c) => {
88465
- return c.json({
88466
- // All Whisper weights ship under MIT (whisper.cpp / OpenAI Whisper);
88467
- // Kokoro under Apache 2.0. Both are permissive → "Free, open".
88468
- stt: WHISPER_MODEL_CATALOG.map((m) => ({
88469
- id: m.id,
88470
- name: m.name,
88471
- description: m.description,
88472
- approxSizeBytes: m.approxSizeBytes,
88473
- kind: "stt",
88474
- license: "MIT",
88475
- licenseClass: "open",
88476
- licenseShortName: "MIT",
88477
- licenseUrl: "https://huggingface.co/ggerganov/whisper.cpp",
88478
- // The Base (English) variant is the recommended STT default: ~140 MB,
88479
- // realtime on laptop CPUs. Curated recoScore → ★ badge + auto-pick.
88480
- ...m.id === "whisper-base.en" ? { recoScore: 20 } : {}
88481
- })),
88482
- tts: [
88483
- {
88484
- id: KOKORO_DEFAULT_MODEL_ID,
88485
- name: "Kokoro 82M v1.0",
88486
- description: "Apache 2.0 TTS \u2014 54+ voices, ~80MB quantized, near-realtime on M1 / modern desktop CPUs.",
88487
- approxSizeBytes: 95e6,
88488
- kind: "tts",
88489
- license: "Apache 2.0",
88490
- licenseClass: "open",
88491
- licenseShortName: "Apache 2.0",
88492
- licenseUrl: "https://huggingface.co/onnx-community/Kokoro-82M-v1.0-ONNX",
88493
- recoScore: 20
88494
- }
88495
- ]
88496
- });
88573
+ return c.json(buildAudioCatalog());
88497
88574
  });
88498
88575
  app.get("/stt/models", async (c) => {
88499
88576
  const provider = await ctx.stt.current();
@@ -90465,6 +90542,8 @@ function configRoutes(ctx) {
90465
90542
  autoUpdateChecks: config.autoUpdateChecks !== false,
90466
90543
  quitOnClose: config.quitOnClose === true,
90467
90544
  themePref: config.themePref,
90545
+ cliShowThinking: config.cliShowThinking !== false,
90546
+ cliShowWrites: config.cliShowWrites === true,
90468
90547
  documentExportOptions: config.documentExportOptions,
90469
90548
  sidebarSide: config.sidebarSide,
90470
90549
  homeGreetingCollapsed: config.homeGreetingCollapsed === true,
@@ -90811,6 +90890,8 @@ function configRoutes(ctx) {
90811
90890
  autoUpdateChecks: updated.autoUpdateChecks !== false,
90812
90891
  quitOnClose: updated.quitOnClose === true,
90813
90892
  themePref: updated.themePref,
90893
+ cliShowThinking: updated.cliShowThinking !== false,
90894
+ cliShowWrites: updated.cliShowWrites === true,
90814
90895
  documentExportOptions: updated.documentExportOptions,
90815
90896
  sidebarSide: updated.sidebarSide,
90816
90897
  homeGreetingCollapsed: updated.homeGreetingCollapsed === true,
@@ -92200,7 +92281,11 @@ function ds4Routes(ctx) {
92200
92281
  const catalogId = c.req.param("catalogId");
92201
92282
  const skipShaRaw = c.req.query("skipSha");
92202
92283
  const skipSha = skipShaRaw != null && skipShaRaw !== "" && skipShaRaw !== "0" && skipShaRaw !== "false";
92203
- ctx.chatInstalls.ds4.start(catalogId, { skipSha, includeMmproj: false });
92284
+ ctx.chatInstalls.ds4.start(catalogId, {
92285
+ skipSha,
92286
+ includeMmproj: false,
92287
+ installCompanion: false
92288
+ });
92204
92289
  return streamSSE5(c, (stream) => subscribeToInstallSse(ctx.chatInstalls.ds4, catalogId, stream));
92205
92290
  });
92206
92291
  app.delete("/models/:catalogId/install", (c) => {
@@ -93888,6 +93973,7 @@ function gezelRoutes(ctx) {
93888
93973
  toGezelIdOrName: toId,
93889
93974
  projectId: body.projectId,
93890
93975
  text: body.text,
93976
+ ...body.suppressReply ? { suppressReply: true } : {},
93891
93977
  ...body.expectedDeliverable ? { expectedDeliverable: body.expectedDeliverable } : {}
93892
93978
  });
93893
93979
  return c.json({
@@ -94829,7 +94915,7 @@ import { HandboekRenderModeSchema } from "@bendyline/gezel";
94829
94915
  import { Hono as Hono29 } from "hono";
94830
94916
 
94831
94917
  // src/handboek/narration.ts
94832
- import { createHash as createHash28 } from "crypto";
94918
+ import { createHash as createHash29 } from "crypto";
94833
94919
  import { existsSync as existsSync14 } from "fs";
94834
94920
  import { mkdir as mkdir42, readFile as readFile43, writeFile as writeFile16 } from "fs/promises";
94835
94921
  import { join as join65 } from "path";
@@ -94845,7 +94931,7 @@ function createHandboekNarrator(deps) {
94845
94931
  const pathFor = (hash) => join65(dir, `${hash}.wav`);
94846
94932
  const metaPathFor = (hash) => join65(dir, `${hash}.json`);
94847
94933
  async function ensureSegment(key, synthesize) {
94848
- const hash = createHash28("sha256").update(key).digest("hex");
94934
+ const hash = createHash29("sha256").update(key).digest("hex");
94849
94935
  const metaPath = metaPathFor(hash);
94850
94936
  if (existsSync14(pathFor(hash)) && existsSync14(metaPath)) {
94851
94937
  try {
@@ -95845,9 +95931,15 @@ function llamaCppRoutes(ctx) {
95845
95931
  const catalogId = c.req.param("catalogId");
95846
95932
  const skipShaRaw = c.req.query("skipSha");
95847
95933
  const skipSha = skipShaRaw != null && skipShaRaw !== "" && skipShaRaw !== "0" && skipShaRaw !== "false";
95934
+ const skipCompanionRaw = c.req.query("skipCompanion");
95935
+ const skipCompanion = skipCompanionRaw != null && skipCompanionRaw !== "" && skipCompanionRaw !== "0" && skipCompanionRaw !== "false";
95848
95936
  const config = await ctx.store.readConfig().catch(() => null);
95849
95937
  const includeMmproj = config?.nativeVision?.[catalogId] === true;
95850
- ctx.chatInstalls.llamaCpp.start(catalogId, { skipSha, includeMmproj });
95938
+ ctx.chatInstalls.llamaCpp.start(catalogId, {
95939
+ skipSha,
95940
+ includeMmproj,
95941
+ installCompanion: !skipCompanion
95942
+ });
95851
95943
  return streamSSE9(
95852
95944
  c,
95853
95945
  (stream) => subscribeToInstallSse(ctx.chatInstalls.llamaCpp, catalogId, stream)
@@ -95938,7 +96030,7 @@ function mcpToolRoutes(ctx) {
95938
96030
  import { Hono as Hono36 } from "hono";
95939
96031
 
95940
96032
  // src/meester/status-generator.ts
95941
- import { createHash as createHash29 } from "crypto";
96033
+ import { createHash as createHash30 } from "crypto";
95942
96034
  import {
95943
96035
  MEESTER_STATUS_HEADLINE_MAX,
95944
96036
  MeesterStatusModelOutputSchema,
@@ -96250,7 +96342,7 @@ function localDay4(date) {
96250
96342
  return `${y}-${m}-${d}`;
96251
96343
  }
96252
96344
  function actionKey(projectId, title) {
96253
- return createHash29("sha256").update(`${projectId}
96345
+ return createHash30("sha256").update(`${projectId}
96254
96346
  ${normalizeTitle(title)}`).digest("hex");
96255
96347
  }
96256
96348
  function normalizeTitle(title) {
@@ -96262,7 +96354,7 @@ function hashInput(candidates) {
96262
96354
  ...c.openTasks.map((t) => `${t.ref}:${t.status}`),
96263
96355
  ...c.events.map((e) => e.id)
96264
96356
  ]);
96265
- return createHash29("sha256").update(lines.join("\n")).digest("hex");
96357
+ return createHash30("sha256").update(lines.join("\n")).digest("hex");
96266
96358
  }
96267
96359
  function parseModelOutput(raw) {
96268
96360
  const fence = raw.match(/```(?:json)?\s*\n([\s\S]*?)\n?```/);
@@ -96555,7 +96647,7 @@ import { Hono as Hono39 } from "hono";
96555
96647
  import { z as z20 } from "zod";
96556
96648
 
96557
96649
  // src/models/gezmodel.ts
96558
- import { createHash as createHash30, randomUUID as randomUUID19 } from "crypto";
96650
+ import { createHash as createHash31, randomUUID as randomUUID19 } from "crypto";
96559
96651
  import { createReadStream as createReadStream6, createWriteStream as createWriteStream5 } from "fs";
96560
96652
  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";
96561
96653
  import { basename as basename14, dirname as dirname35, extname as extname5, join as join66 } from "path";
@@ -96657,7 +96749,7 @@ var GezmodelManager = class {
96657
96749
  files.push({
96658
96750
  path: path2,
96659
96751
  sizeBytes: content.byteLength,
96660
- sha256: createHash30("sha256").update(content).digest("hex"),
96752
+ sha256: createHash31("sha256").update(content).digest("hex"),
96661
96753
  role: path2 === "manifests/installed.json" ? "installed-manifest" : path2 === "manifests/catalog.json" ? "catalog-manifest" : "catalog-file"
96662
96754
  });
96663
96755
  }
@@ -96863,7 +96955,7 @@ var GezmodelManager = class {
96863
96955
  }
96864
96956
  };
96865
96957
  async function hashFile(path2) {
96866
- const hash = createHash30("sha256");
96958
+ const hash = createHash31("sha256");
96867
96959
  const stream = createReadStream6(path2, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
96868
96960
  for await (const chunk2 of stream) hash.update(chunk2);
96869
96961
  return hash.digest("hex");
@@ -97061,7 +97153,7 @@ function extractOne(archivePath, wanted, dest, expected) {
97061
97153
  zip.openReadStream(entry, (streamErr, stream) => {
97062
97154
  if (streamErr || !stream)
97063
97155
  return fail2(streamErr ?? new Error("could not read ZIP entry"));
97064
- const hash = createHash30("sha256");
97156
+ const hash = createHash31("sha256");
97065
97157
  let bytes = 0;
97066
97158
  const verifier = new Transform({
97067
97159
  transform(chunk2, _encoding, callback) {
@@ -97295,7 +97387,7 @@ import {
97295
97387
  } from "@bendyline/gezel";
97296
97388
 
97297
97389
  // src/providers/mlx/models.ts
97298
- import { createHash as createHash31 } from "crypto";
97390
+ import { createHash as createHash32 } from "crypto";
97299
97391
  import { createReadStream as createReadStream7 } from "fs";
97300
97392
  import { mkdir as mkdir44, readFile as readFile47, rename as rename12, rm as rm30, stat as stat27, writeFile as writeFile18 } from "fs/promises";
97301
97393
  import { join as join68, resolve as resolvePath2 } from "path";
@@ -97857,7 +97949,7 @@ var MlxModelManager = class {
97857
97949
  }
97858
97950
  }
97859
97951
  push({ type: "verifying", file: file.name });
97860
- const hasher = createHash31("sha256");
97952
+ const hasher = createHash32("sha256");
97861
97953
  await new Promise((resolve19, reject) => {
97862
97954
  const stream = createReadStream7(tmpPath, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
97863
97955
  stream.on("data", (chunk2) => hasher.update(chunk2));
@@ -99697,7 +99789,7 @@ function describeHostCadence(args) {
99697
99789
  }
99698
99790
 
99699
99791
  // src/project-type/craftbooks.ts
99700
- import { createHash as createHash32 } from "crypto";
99792
+ import { createHash as createHash33 } from "crypto";
99701
99793
  import {
99702
99794
  craftbookFromDoc as craftbookFromDoc3,
99703
99795
  createLogger as createLogger109,
@@ -99721,7 +99813,7 @@ function craftbookContentHash(book) {
99721
99813
  command: book.command ?? null,
99722
99814
  requirements: book.requirements ?? null
99723
99815
  };
99724
- return `sha256:${createHash32("sha256").update(JSON.stringify(canonical)).digest("hex")}`;
99816
+ return `sha256:${createHash33("sha256").update(JSON.stringify(canonical)).digest("hex")}`;
99725
99817
  }
99726
99818
  async function resolveTypeCraftbook(catalog, input, id, now) {
99727
99819
  const embedded = await catalog.readItemFile(
@@ -100429,7 +100521,7 @@ function pageInvokeRoutes(ctx) {
100429
100521
  }
100430
100522
 
100431
100523
  // src/http/routes/page-read.ts
100432
- import { createHash as createHash33 } from "crypto";
100524
+ import { createHash as createHash34 } from "crypto";
100433
100525
  import { readFile as readFile50, readdir as readdir29, stat as stat28 } from "fs/promises";
100434
100526
  import { PageReadRequestSchema, createLogger as createLogger113 } from "@bendyline/gezel";
100435
100527
  import { Hono as Hono48 } from "hono";
@@ -100438,7 +100530,7 @@ var PAGE_READ_MAX_BYTES = 2 * 1024 * 1024;
100438
100530
  var RATE_WINDOW_MS3 = 6e4;
100439
100531
  var RATE_MAX_READS = 600;
100440
100532
  function etagOf(size, mtimeMs) {
100441
- return createHash33("sha256").update(`${size}:${Math.trunc(mtimeMs)}`).digest("base64url").slice(0, 16);
100533
+ return createHash34("sha256").update(`${size}:${Math.trunc(mtimeMs)}`).digest("base64url").slice(0, 16);
100442
100534
  }
100443
100535
  function pageReadRoutes(ctx) {
100444
100536
  const app = new Hono48();
@@ -100488,7 +100580,7 @@ function pageReadRoutes(ctx) {
100488
100580
  return `${entry.name}:${entry.isDirectory() ? "dir" : "file"}:${Math.trunc(child?.mtimeMs ?? 0)}`;
100489
100581
  })
100490
100582
  );
100491
- const digest = createHash33("sha256").update(listed.sort().join("\n")).digest("base64url").slice(0, 16);
100583
+ const digest = createHash34("sha256").update(listed.sort().join("\n")).digest("base64url").slice(0, 16);
100492
100584
  return c.json({ op: "stat", etag: digest, mtime: stats.mtimeMs });
100493
100585
  }
100494
100586
  return c.json({
@@ -100513,7 +100605,7 @@ function pageReadRoutes(ctx) {
100513
100605
  };
100514
100606
  })
100515
100607
  )).filter((entry) => entry !== null);
100516
- const digest = createHash33("sha256").update(
100608
+ const digest = createHash34("sha256").update(
100517
100609
  listed.map((e) => `${e.name}:${e.kind}:${Math.trunc(e.mtime)}`).sort().join("\n")
100518
100610
  ).digest("base64url").slice(0, 16);
100519
100611
  return c.json({ op: "list", entries: listed, etag: digest, mtime: stats.mtimeMs });
@@ -101227,7 +101319,7 @@ init_ensure();
101227
101319
  init_install();
101228
101320
 
101229
101321
  // src/workspace/instruction-scanner.ts
101230
- import { createHash as createHash34 } from "crypto";
101322
+ import { createHash as createHash35 } from "crypto";
101231
101323
  import { readFile as readFile52, stat as stat30 } from "fs/promises";
101232
101324
  import { join as join73 } from "path";
101233
101325
  var MAX_CONTENT_CHARS = 64e3;
@@ -101272,7 +101364,7 @@ ${i.content.trim()}`).join("\n\n---\n\n");
101272
101364
  return { content: chosen.content, sourceFile: chosen.source, hash: chosen.hash };
101273
101365
  }
101274
101366
  function sha2563(s) {
101275
- return createHash34("sha256").update(s).digest("hex");
101367
+ return createHash35("sha256").update(s).digest("hex");
101276
101368
  }
101277
101369
 
101278
101370
  // src/workspace/skill-script-translator.ts
@@ -103157,7 +103249,7 @@ async function recoverTypedProjectCreations(store) {
103157
103249
  }
103158
103250
 
103159
103251
  // src/project-type/gzl.ts
103160
- import { createHash as createHash35 } from "crypto";
103252
+ import { createHash as createHash36 } from "crypto";
103161
103253
  import { mkdir as mkdir48, writeFile as writeFile21 } from "fs/promises";
103162
103254
  import { dirname as dirname40 } from "path";
103163
103255
  import {
@@ -103175,7 +103267,7 @@ function shard(id) {
103175
103267
  return id.slice(0, 2).toLowerCase();
103176
103268
  }
103177
103269
  function hashItemFiles(files) {
103178
- const hash = createHash35("sha256");
103270
+ const hash = createHash36("sha256");
103179
103271
  for (const { rel, content } of [...files].sort((a, b) => a.rel < b.rel ? -1 : 1)) {
103180
103272
  hash.update(rel);
103181
103273
  hash.update("\0");
@@ -103323,7 +103415,7 @@ async function importGzlBundle(deps, buffer, opts = {}) {
103323
103415
 
103324
103416
  // src/workspace/command-approvals.ts
103325
103417
  init_atomic();
103326
- import { createHash as createHash36 } from "crypto";
103418
+ import { createHash as createHash37 } from "crypto";
103327
103419
  import { existsSync as existsSync18 } from "fs";
103328
103420
  import { mkdir as mkdir49, readFile as readFile57 } from "fs/promises";
103329
103421
  import { dirname as dirname41, join as join79 } from "path";
@@ -103331,7 +103423,7 @@ import { projectPrivateDir as projectPrivateDir5 } from "@bendyline/gezel/paths"
103331
103423
  function hashCommandInvocation(body, args, inputFiles = []) {
103332
103424
  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));
103333
103425
  const payload = JSON.stringify({ version: 2, body: body ?? null, args, files });
103334
- return createHash36("sha256").update("gezel-command-invocation\0").update(payload).digest("hex");
103426
+ return createHash37("sha256").update("gezel-command-invocation\0").update(payload).digest("hex");
103335
103427
  }
103336
103428
  function approvalsPath(home, projectId) {
103337
103429
  return join79(projectPrivateDir5(home, projectId), "command-approvals.json");
@@ -103557,20 +103649,20 @@ import {
103557
103649
  } from "@bendyline/gezel";
103558
103650
  import { projectPrivateDir as projectPrivateDir6 } from "@bendyline/gezel/paths";
103559
103651
  var SHIPPED_ALLOWLIST = [
103560
- { package: "zod", allowedVersions: ["^3", "^4"] },
103561
- { package: "chalk", allowedVersions: ["^5"] },
103562
- { package: "commander", allowedVersions: ["^12", "^13"] },
103563
- { package: "date-fns", allowedVersions: ["^3", "^4"] },
103564
- { package: "yaml", allowedVersions: ["^2"] },
103565
- { package: "cheerio", allowedVersions: ["^1"] },
103566
- { package: "mime-types", allowedVersions: ["^2", "^3"] },
103567
- { package: "marked", allowedVersions: ["^12", "^13", "^14", "^15"] },
103568
- { package: "nanoid", allowedVersions: ["^5"] },
103569
- { package: "pino", allowedVersions: ["^9"] },
103570
- { package: "playwright-core", allowedVersions: ["^1"] },
103571
- { package: "tsx", allowedVersions: ["^4"] },
103572
- { package: "typescript", allowedVersions: ["^5"] },
103573
- { package: "undici", allowedVersions: ["^6", "^7"] }
103652
+ { package: "zod", allowedVersions: ["^3", "^4"], defaultVersion: "^4" },
103653
+ { package: "chalk", allowedVersions: ["^5"], defaultVersion: "^5" },
103654
+ { package: "commander", allowedVersions: ["^12", "^13"], defaultVersion: "^13" },
103655
+ { package: "date-fns", allowedVersions: ["^3", "^4"], defaultVersion: "^4" },
103656
+ { package: "yaml", allowedVersions: ["^2"], defaultVersion: "^2" },
103657
+ { package: "cheerio", allowedVersions: ["^1"], defaultVersion: "^1" },
103658
+ { package: "mime-types", allowedVersions: ["^2", "^3"], defaultVersion: "^3" },
103659
+ { package: "marked", allowedVersions: ["^12", "^13", "^14", "^15"], defaultVersion: "^15" },
103660
+ { package: "nanoid", allowedVersions: ["^5"], defaultVersion: "^5" },
103661
+ { package: "pino", allowedVersions: ["^9"], defaultVersion: "^9" },
103662
+ { package: "playwright-core", allowedVersions: ["^1"], defaultVersion: "^1" },
103663
+ { package: "tsx", allowedVersions: ["^4"], defaultVersion: "^4" },
103664
+ { package: "typescript", allowedVersions: ["^5"], defaultVersion: "^5" },
103665
+ { package: "undici", allowedVersions: ["^6", "^7"], defaultVersion: "^7" }
103574
103666
  ];
103575
103667
  function projectAllowlistPath(home, projectId) {
103576
103668
  return join81(projectPrivateDir6(home, projectId), "npm-allowlist.json");
@@ -103601,6 +103693,9 @@ function matchesAllowlist(pkg, version) {
103601
103693
  }
103602
103694
  return false;
103603
103695
  }
103696
+ function shippedDefaultVersion(pkg) {
103697
+ return SHIPPED_ALLOWLIST.find((entry) => entry.package === pkg)?.defaultVersion;
103698
+ }
103604
103699
  function matchesProjectApproval(allowlist, pkg, version) {
103605
103700
  return allowlist.approved.some((e) => e.package === pkg && e.version === version);
103606
103701
  }
@@ -103730,7 +103825,9 @@ function dedupRequests(raw) {
103730
103825
  const out = [];
103731
103826
  for (const r of raw) {
103732
103827
  const pkg = NpmPackageNameSchema.parse(r.package);
103733
- const version = NpmRegistryVersionSchema.parse(r.version ?? "latest");
103828
+ const version = NpmRegistryVersionSchema.parse(
103829
+ r.version ?? shippedDefaultVersion(pkg) ?? "latest"
103830
+ );
103734
103831
  const key = keyOf(pkg, version);
103735
103832
  if (seen.has(key)) continue;
103736
103833
  seen.add(key);
@@ -103900,7 +103997,7 @@ import { join as join82 } from "path";
103900
103997
  import { nowIso as nowIso14 } from "@bendyline/gezel";
103901
103998
 
103902
103999
  // src/workspace/command-inputs.ts
103903
- import { createHash as createHash37 } from "crypto";
104000
+ import { createHash as createHash38 } from "crypto";
103904
104001
  import { createReadStream as createReadStream8 } from "fs";
103905
104002
  import { readFile as readFile59, realpath as realpath7, stat as stat35 } from "fs/promises";
103906
104003
  import { dirname as dirname43, extname as extname6, isAbsolute as isAbsolute10, relative as relative10, resolve as resolve13, sep as sep9 } from "path";
@@ -103973,7 +104070,7 @@ function portableRelative(root, file) {
103973
104070
  return relative10(root, file).split(sep9).join("/");
103974
104071
  }
103975
104072
  async function sha256File4(file) {
103976
- const hash = createHash37("sha256");
104073
+ const hash = createHash38("sha256");
103977
104074
  await new Promise((resolveStream, reject) => {
103978
104075
  const stream = createReadStream8(file);
103979
104076
  stream.on("data", (chunk2) => hash.update(chunk2));
@@ -107878,7 +107975,7 @@ async function readProjectScriptRun(home, projectId, runId) {
107878
107975
  }
107879
107976
 
107880
107977
  // src/scripts/sdk.ts
107881
- import { createHash as createHash39 } from "crypto";
107978
+ import { createHash as createHash40 } from "crypto";
107882
107979
  import { readFile as readFile67 } from "fs/promises";
107883
107980
  import { dirname as dirname45, join as join87, relative as relative11 } from "path";
107884
107981
  import { fileURLToPath as fileURLToPath7 } from "url";
@@ -107944,7 +108041,7 @@ async function readSdkTypes() {
107944
108041
  });
107945
108042
  } catch {
107946
108043
  }
107947
- const hash = createHash39("sha256");
108044
+ const hash = createHash40("sha256");
107948
108045
  for (const f of files) hash.update(f.name).update("\0").update(f.content);
107949
108046
  cachedTypes = { version: hash.digest("hex"), files };
107950
108047
  return cachedTypes;
@@ -110758,9 +110855,13 @@ async function grepWorkspace(opts) {
110758
110855
  const plan = normalizePlan(opts);
110759
110856
  const target = await resolveSearchTarget(opts.workspaceDir, opts.path);
110760
110857
  const requestedEngine = opts.engine ?? "auto";
110761
- const ripgrepPath = requestedEngine === "javascript" ? null : await resolveExecutableOnPath("rg", target.workspaceDir, Math.min(plan.timeoutMs, 2e3));
110858
+ const ripgrepPath = requestedEngine === "javascript" ? null : await resolveRipgrepExecutable(target.workspaceDir, Math.min(plan.timeoutMs, 2e3));
110762
110859
  if (requestedEngine === "ripgrep" && !ripgrepPath) {
110763
- throw new WorkspaceGrepError("ripgrep is not installed on this machine", 500, "rg-unavailable");
110860
+ throw new WorkspaceGrepError(
110861
+ "ripgrep is unavailable (the bundled platform package is missing and rg is not on PATH)",
110862
+ 500,
110863
+ "rg-unavailable"
110864
+ );
110764
110865
  }
110765
110866
  let raw;
110766
110867
  let engine;
@@ -111264,6 +111365,16 @@ async function resolveExecutableOnPath(command, forbiddenRoot, timeoutMs) {
111264
111365
  if (timer) clearTimeout(timer);
111265
111366
  }
111266
111367
  }
111368
+ async function resolveRipgrepExecutable(forbiddenRoot, timeoutMs) {
111369
+ const onPath = await resolveExecutableOnPath("rg", forbiddenRoot, timeoutMs);
111370
+ if (onPath) return onPath;
111371
+ try {
111372
+ const { rgPath } = await import("@vscode/ripgrep");
111373
+ return await validateExecutable(rgPath, forbiddenRoot);
111374
+ } catch {
111375
+ return null;
111376
+ }
111377
+ }
111267
111378
  async function findExecutableOnPath(command, forbiddenRoot) {
111268
111379
  const pathValue = process.env.PATH;
111269
111380
  if (!pathValue) return null;
@@ -111272,22 +111383,28 @@ async function findExecutableOnPath(command, forbiddenRoot) {
111272
111383
  const entry = rawEntry.replace(/^"|"$/g, "");
111273
111384
  if (!entry || !isAbsolute11(entry)) continue;
111274
111385
  for (const suffix of suffixes) {
111275
- try {
111276
- const executable = await realpath10(join89(entry, `${command}${suffix}`));
111277
- if (pathIsInside(forbiddenRoot, executable)) continue;
111278
- const executableStat = await stat39(executable);
111279
- if (!executableStat.isFile()) continue;
111280
- await access3(
111281
- executable,
111282
- process.platform === "win32" ? fsConstants.F_OK : fsConstants.X_OK
111283
- );
111284
- return executable;
111285
- } catch {
111286
- }
111386
+ const executable = await validateExecutable(
111387
+ join89(entry, `${command}${suffix}`),
111388
+ forbiddenRoot
111389
+ );
111390
+ if (executable) return executable;
111287
111391
  }
111288
111392
  }
111289
111393
  return null;
111290
111394
  }
111395
+ async function validateExecutable(candidate, forbiddenRoot) {
111396
+ if (!isAbsolute11(candidate)) return null;
111397
+ try {
111398
+ const executable = await realpath10(candidate);
111399
+ if (pathIsInside(forbiddenRoot, executable)) return null;
111400
+ const executableStat = await stat39(executable);
111401
+ if (!executableStat.isFile()) return null;
111402
+ await access3(executable, process.platform === "win32" ? fsConstants.F_OK : fsConstants.X_OK);
111403
+ return executable;
111404
+ } catch {
111405
+ return null;
111406
+ }
111407
+ }
111291
111408
  function pathIsInside(root, candidate) {
111292
111409
  const rel = relative12(root, candidate);
111293
111410
  return rel === "" || rel !== ".." && !rel.startsWith(`..${sep10}`) && !isAbsolute11(rel);
@@ -118892,7 +119009,7 @@ function indexShadowBody(store, file, body) {
118892
119009
  }
118893
119010
 
118894
119011
  // src/index-store/area-pass.ts
118895
- import { createHash as createHash40 } from "crypto";
119012
+ import { createHash as createHash41 } from "crypto";
118896
119013
  var ARCHITECTURE_KEY = "::project";
118897
119014
  var MIN_AREA_FILES = 2;
118898
119015
  var AREA_INPUT_CAP = 6e3;
@@ -118954,7 +119071,7 @@ async function runAreaPass(index, deps) {
118954
119071
  return result;
118955
119072
  }
118956
119073
  function hashLines(lines) {
118957
- return createHash40("sha256").update([...lines].sort().join("\n")).digest("hex");
119074
+ return createHash41("sha256").update([...lines].sort().join("\n")).digest("hex");
118958
119075
  }
118959
119076
  function buildAreaPrompt(area, entries) {
118960
119077
  let body = "";
@@ -119144,9 +119261,9 @@ function triv(kind) {
119144
119261
  }
119145
119262
 
119146
119263
  // src/index-store/hash.ts
119147
- import { createHash as createHash41 } from "crypto";
119264
+ import { createHash as createHash42 } from "crypto";
119148
119265
  function sha2564(data) {
119149
- return createHash41("sha256").update(data).digest("hex");
119266
+ return createHash42("sha256").update(data).digest("hex");
119150
119267
  }
119151
119268
 
119152
119269
  // src/index-store/artifacts-indexer.ts
@@ -124057,7 +124174,7 @@ ${body}\r
124057
124174
  }
124058
124175
 
124059
124176
  // src/mail/mime.ts
124060
- import { createHash as createHash42 } from "crypto";
124177
+ import { createHash as createHash43 } from "crypto";
124061
124178
  import { simpleParser } from "mailparser";
124062
124179
 
124063
124180
  // src/mail/html.ts
@@ -124172,7 +124289,7 @@ function normalizeReferences(refs) {
124172
124289
  }
124173
124290
  function synthesizeMessageId(parsed, ctx) {
124174
124291
  const basis = `${addressText(parsed.from)}|${parsed.subject ?? ""}|${parsed.date?.toISOString() ?? ctx.fallbackDate ?? ""}|${ctx.id}`;
124175
- return `<${createHash42("sha256").update(basis).digest("hex").slice(0, 32)}@gezel.local>`;
124292
+ return `<${createHash43("sha256").update(basis).digest("hex").slice(0, 32)}@gezel.local>`;
124176
124293
  }
124177
124294
  async function parseRawMessage(raw, ctx) {
124178
124295
  const parsed = await simpleParser(raw);
@@ -124795,7 +124912,7 @@ async function migrateOversightTask(store, num) {
124795
124912
 
124796
124913
  // src/memory/compaction.ts
124797
124914
  init_atomic();
124798
- import { createHash as createHash43 } from "crypto";
124915
+ import { createHash as createHash44 } from "crypto";
124799
124916
  import { readFile as readFile77 } from "fs/promises";
124800
124917
  import { join as join101 } from "path";
124801
124918
  import { createLogger as createLogger160, isProactiveAllowed as isProactiveAllowed5 } from "@bendyline/gezel";
@@ -125007,7 +125124,7 @@ var MemoryCompactor = class {
125007
125124
  }
125008
125125
  }
125009
125126
  if (entries.length < minEntries) return false;
125010
- const inputHash = createHash43("sha256").update(eligibleDays.map((d) => `${d}
125127
+ const inputHash = createHash44("sha256").update(eligibleDays.map((d) => `${d}
125011
125128
  ${dayContents.get(d)}`).join("\n")).digest("hex");
125012
125129
  const state = await this.readState(scope, id);
125013
125130
  if (state.inputHash === inputHash) return false;
@@ -125113,7 +125230,7 @@ ${dayContents.get(d)}`).join("\n")).digest("hex");
125113
125230
  const notes = await this.memory.getRecent("gezel", gezelId, lookbackDays);
125114
125231
  if (!notes.trim()) return;
125115
125232
  const current = await this.store.readMemoryLessons(gezelId);
125116
- const lessonsInputHash = createHash43("sha256").update(`${notes}
125233
+ const lessonsInputHash = createHash44("sha256").update(`${notes}
125117
125234
  ---
125118
125235
  ${current}`).digest("hex");
125119
125236
  const state = await this.readState("gezel", gezelId);
@@ -125883,6 +126000,7 @@ var LlamaVisionProvider = class {
125883
126000
  await mkdir57(itemDir, { recursive: true });
125884
126001
  const totalAllBytes = spec.files.reduce((n, f) => n + f.approxSizeBytes, 0);
125885
126002
  let writtenAll = 0;
126003
+ const verifiedDigests = {};
125886
126004
  for (const file of spec.files) {
125887
126005
  const result = yield* downloadWithSha256(this.fetchImpl, {
125888
126006
  url: file.downloadUrl,
@@ -125898,8 +126016,9 @@ var LlamaVisionProvider = class {
125898
126016
  return;
125899
126017
  }
125900
126018
  writtenAll = result.writtenAll;
126019
+ verifiedDigests[file.filename] = file.sha256.toLowerCase();
125901
126020
  }
125902
- const fileSha256 = await hashModelPayloadFiles(itemDir);
126021
+ const fileSha256 = await hashModelPayloadFiles(itemDir, verifiedDigests);
125903
126022
  await writeFile26(
125904
126023
  join104(itemDir, "manifest.json"),
125905
126024
  `${JSON.stringify(
@@ -126319,7 +126438,7 @@ async function* runGgufInstallWithCompanion(catalogId, o, deps) {
126319
126438
  yield event;
126320
126439
  }
126321
126440
  if (!finished) return;
126322
- yield* companionRecognitionEvents(catalogId, deps);
126441
+ if (o.installCompanion) yield* companionRecognitionEvents(catalogId, deps);
126323
126442
  yield finished;
126324
126443
  }
126325
126444
  async function* companionRecognitionEvents(catalogId, deps) {
@@ -127627,7 +127746,7 @@ function makeActionable(message) {
127627
127746
  }
127628
127747
 
127629
127748
  // src/providers/image/sd-cpp.ts
127630
- import { createHash as createHash44 } from "crypto";
127749
+ import { createHash as createHash45 } from "crypto";
127631
127750
  import { createReadStream as createReadStream10 } from "fs";
127632
127751
  import { mkdir as mkdir60, readFile as readFile81, rename as rename15, rm as rm41, writeFile as writeFile29 } from "fs/promises";
127633
127752
  import { join as join110 } from "path";
@@ -127966,7 +128085,7 @@ var StableDiffusionCppProvider = class {
127966
128085
  }
127967
128086
  }
127968
128087
  const partialPath = `${destPath}.partial`;
127969
- const hasher = createHash44("sha256");
128088
+ const hasher = createHash45("sha256");
127970
128089
  await new Promise((resolve19, reject) => {
127971
128090
  const stream = createReadStream10(partialPath, {
127972
128091
  highWaterMark: MODEL_HASH_READ_BUFFER_BYTES
@@ -128485,7 +128604,7 @@ function isMachineImageProvider(config, env) {
128485
128604
  }
128486
128605
 
128487
128606
  // src/providers/recognition/store.ts
128488
- import { createHash as createHash45 } from "crypto";
128607
+ import { createHash as createHash46 } from "crypto";
128489
128608
  import { mkdir as mkdir61, readFile as readFile82, rename as rename16, rm as rm42, writeFile as writeFile30 } from "fs/promises";
128490
128609
  import { join as join112 } from "path";
128491
128610
  import { ImageRecognitionSchema, createLogger as createLogger172 } from "@bendyline/gezel";
@@ -128497,8 +128616,8 @@ var RecognitionCache = class {
128497
128616
  this.root = join112(opts.home, "recognition");
128498
128617
  }
128499
128618
  keyFor(input) {
128500
- const imageHash = createHash45("sha256").update(input.bytes).digest("hex");
128501
- return createHash45("sha256").update(`${imageHash}\0${input.mode}\0${input.modelId}\0v${PROMPT_VERSION}`).digest("hex");
128619
+ const imageHash = createHash46("sha256").update(input.bytes).digest("hex");
128620
+ return createHash46("sha256").update(`${imageHash}\0${input.mode}\0${input.modelId}\0v${PROMPT_VERSION}`).digest("hex");
128502
128621
  }
128503
128622
  pathFor(key) {
128504
128623
  return join112(this.root, key.slice(0, 2), `${key}.json`);
@@ -128943,7 +129062,7 @@ var MockVideoProvider = class {
128943
129062
  };
128944
129063
 
128945
129064
  // src/providers/video/models.ts
128946
- import { createHash as createHash46 } from "crypto";
129065
+ import { createHash as createHash47 } from "crypto";
128947
129066
  import { createReadStream as createReadStream11 } from "fs";
128948
129067
  import { mkdir as mkdir62, readFile as readFile83, rename as rename17, rm as rm43, writeFile as writeFile31 } from "fs/promises";
128949
129068
  import { dirname as dirname50, join as join113 } from "path";
@@ -129216,7 +129335,7 @@ var VideoModelManager = class {
129216
129335
  }
129217
129336
  }
129218
129337
  push({ type: "verifying", file: file.name });
129219
- const hasher = createHash46("sha256");
129338
+ const hasher = createHash47("sha256");
129220
129339
  await new Promise((resolve19, reject) => {
129221
129340
  const stream = createReadStream11(tmpPath, { highWaterMark: MODEL_HASH_READ_BUFFER_BYTES });
129222
129341
  stream.on("data", (chunk2) => hasher.update(chunk2));
@@ -133489,11 +133608,18 @@ var TaskRunner = class {
133489
133608
  /** Run one serialized dispatch pass now, sharing the interval's overlap guard. */
133490
133609
  async wake() {
133491
133610
  if (this.tickInFlight) return this.tickInFlight;
133492
- this.tickInFlight = this.tick().finally(() => {
133611
+ this.tickInFlight = this.tickOnce().finally(() => {
133493
133612
  this.tickInFlight = null;
133494
133613
  });
133495
133614
  return this.tickInFlight;
133496
133615
  }
133616
+ /**
133617
+ * Public test/operator entry point. Keep it serialized with the interval:
133618
+ * callers may drive a real, already-started service whose ticker is active.
133619
+ */
133620
+ async tick() {
133621
+ return this.wake();
133622
+ }
133497
133623
  /**
133498
133624
  * Scan every `active` task and enqueue a handoff for any whose
133499
133625
  * current step has an effective gezel owner. Call on service boot and
@@ -133540,9 +133666,9 @@ var TaskRunner = class {
133540
133666
  /**
133541
133667
  * One dispatch pass. Walks pending in FIFO order; dispatches any
133542
133668
  * whose target provider has a free slot; skips items for tasks
133543
- * that are no longer active. Public for test-driven ticks.
133669
+ * that are no longer active.
133544
133670
  */
133545
- async tick() {
133671
+ async tickOnce() {
133546
133672
  await this.pruneActiveDispatches();
133547
133673
  if (this.pending.length === 0) {
133548
133674
  this.holdReason = void 0;
@@ -133554,6 +133680,7 @@ var TaskRunner = class {
133554
133680
  return;
133555
133681
  }
133556
133682
  const snapshot = this.pending.slice();
133683
+ const snapshotIds = new Set(snapshot.map((handoff) => handoff.id));
133557
133684
  const keep = [];
133558
133685
  const inTickDispatches = /* @__PURE__ */ new Map();
133559
133686
  const nightShiftOn = this.isNightShiftActive();
@@ -133642,8 +133769,9 @@ var TaskRunner = class {
133642
133769
  );
133643
133770
  }
133644
133771
  }
133772
+ const enqueuedDuringTick = this.pending.filter((handoff) => !snapshotIds.has(handoff.id));
133645
133773
  this.pending.length = 0;
133646
- this.pending.push(...keep);
133774
+ this.pending.push(...keep, ...enqueuedDuringTick);
133647
133775
  this.holdReason = keep.some((handoff) => handoff.heldFor === "provider-busy") ? "provider-busy" : void 0;
133648
133776
  }
133649
133777
  async pruneActiveDispatches() {