mixdog 1.1.0 → 1.1.2

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 (174) hide show
  1. package/README.md +13 -6
  2. package/package.json +1 -2
  3. package/scripts/latest-guard.mjs +63 -0
  4. package/scripts/lib/run-node-tests.mjs +103 -27
  5. package/scripts/lib/test-failure-summary.mjs +7 -2
  6. package/scripts/merge-mac-update-feed.mjs +107 -0
  7. package/scripts/mobile-release.mjs +210 -0
  8. package/scripts/post-release-check.mjs +353 -0
  9. package/scripts/publish-asset-release.mjs +43 -0
  10. package/scripts/release-guard.mjs +63 -0
  11. package/scripts/release-paths.mjs +39 -2
  12. package/scripts/test.mjs +29 -7
  13. package/src/defaults/shipped-history.json +2 -0
  14. package/src/defaults/skills/computer-use/SKILL.md +1 -1
  15. package/src/defaults/skills/setup/references/actions.md +1 -0
  16. package/src/headless-role.mjs +2 -2
  17. package/src/lib/keychain-cjs.cjs +582 -17
  18. package/src/lib/rules-builder.cjs +0 -23
  19. package/src/rules/lead/LEAD.md +2 -2
  20. package/src/runtime/agent/orchestrator/config-storage.mjs +32 -4
  21. package/src/runtime/agent/orchestrator/config.mjs +18 -0
  22. package/src/runtime/agent/orchestrator/context/instruction-files.mjs +130 -0
  23. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +4 -0
  24. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +11 -0
  25. package/src/runtime/agent/orchestrator/providers/lib/open-login-url.mjs +9 -0
  26. package/src/runtime/agent/orchestrator/providers/mimo-oauth-login.mjs +254 -0
  27. package/src/runtime/agent/orchestrator/providers/mimo-oauth-profile.mjs +218 -0
  28. package/src/runtime/agent/orchestrator/providers/mimo-oauth-tokens.mjs +239 -0
  29. package/src/runtime/agent/orchestrator/providers/mimo-oauth.mjs +233 -0
  30. package/src/runtime/agent/orchestrator/providers/muse-code-oauth-login.mjs +247 -0
  31. package/src/runtime/agent/orchestrator/providers/muse-code-oauth-tokens.mjs +225 -0
  32. package/src/runtime/agent/orchestrator/providers/muse-code-oauth.mjs +542 -0
  33. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +25 -0
  34. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +4 -1
  35. package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +13 -0
  36. package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +14 -6
  37. package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog-store.mjs +99 -0
  38. package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +4 -8
  39. package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +2 -7
  40. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +8 -0
  41. package/src/runtime/agent/orchestrator/providers/registry.mjs +4 -0
  42. package/src/runtime/agent/orchestrator/runtime-core/effort.mjs +2 -0
  43. package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +15 -1
  44. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +1 -5
  45. package/src/runtime/agent/orchestrator/session/context-utils.mjs +12 -14
  46. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +11 -1
  47. package/src/runtime/agent/orchestrator/session/loop/tool-call-ids.mjs +90 -0
  48. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +19 -11
  49. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +1 -0
  50. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +28 -0
  51. package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +8 -0
  52. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +3 -0
  53. package/src/runtime/agent/orchestrator/session/manager.mjs +1 -5
  54. package/src/runtime/agent/orchestrator/session/read-dedup.mjs +0 -1
  55. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +3 -0
  56. package/src/runtime/agent/orchestrator/session/tool-batch/finalize.mjs +2 -0
  57. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +2 -0
  58. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +23 -0
  59. package/src/runtime/agent/orchestrator/session/turn-effort.mjs +18 -0
  60. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +11 -8
  61. package/src/runtime/agent/orchestrator/tools/builtin/atomic-write.mjs +9 -4
  62. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +245 -0
  63. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/command-preflight.mjs +13 -1
  64. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +3 -1
  65. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/invocation-plan.mjs +2 -2
  66. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +49 -0
  67. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +3 -3
  68. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +9 -7
  69. package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +61 -8
  70. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +28 -3
  71. package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +73 -1
  72. package/src/runtime/agent/orchestrator/tools/builtin/read-single-guards.mjs +2 -2
  73. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +3 -1
  74. package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +17 -6
  75. package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +23 -5
  76. package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +93 -43
  77. package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +32 -6
  78. package/src/runtime/agent/orchestrator/tools/builtin.mjs +9 -2
  79. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +3 -1
  80. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +12 -15
  81. package/src/runtime/agent/orchestrator/tools/lib/shell-run-background.mjs +2 -2
  82. package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +4 -2
  83. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +124 -91
  84. package/src/runtime/agent/orchestrator/tools/shell-exec-policy.mjs +19 -4
  85. package/src/runtime/channels/index.mjs +1 -5
  86. package/src/runtime/channels/lib/runtime-paths.mjs +8 -23
  87. package/src/runtime/channels/lib/tool-dispatch.mjs +1 -13
  88. package/src/runtime/channels/lib/worker-ipc.mjs +2 -2
  89. package/src/runtime/channels/lib/worker-main.mjs +4 -34
  90. package/src/runtime/computer-bridge/client.mjs +25 -1
  91. package/src/runtime/computer-bridge/linux-action-capabilities.mjs +84 -0
  92. package/src/runtime/computer-bridge/linux-readiness.d.mts +52 -0
  93. package/src/runtime/computer-bridge/linux-readiness.mjs +411 -0
  94. package/src/runtime/computer-bridge/test-linux-display.mjs +5 -0
  95. package/src/runtime/effort-judge/compact-tokenizer.mjs +13 -8
  96. package/src/runtime/effort-judge/judge-input.mjs +5 -2
  97. package/src/runtime/effort-judge/model-install.mjs +9 -3
  98. package/src/runtime/effort-judge/model-manifest.json +7 -7
  99. package/src/runtime/memory/lib/embedding-worker.mjs +9 -3
  100. package/src/runtime/memory/lib/pg/supervisor.mjs +3 -0
  101. package/src/runtime/shared/config.mjs +50 -2
  102. package/src/runtime/shared/developer-options.mjs +7 -0
  103. package/src/runtime/shared/instruction-files-mode.mjs +9 -0
  104. package/src/runtime/shared/llm/model-catalog.mjs +2 -1
  105. package/src/runtime/shared/llm/openai-daybreak.mjs +79 -0
  106. package/src/runtime/shared/pristine-execution-contract.json +9 -0
  107. package/src/runtime/shared/pristine-execution.mjs +1 -1
  108. package/src/runtime/shared/provider-accounts.mjs +2 -0
  109. package/src/runtime/shared/resource-admission.mjs +10 -3
  110. package/src/runtime/shared/schedule-model-ref.mjs +11 -0
  111. package/src/runtime/shared/semver.d.mts +1 -0
  112. package/src/runtime/shared/semver.mjs +57 -0
  113. package/src/runtime/shared/session-approval-wait.mjs +35 -0
  114. package/src/runtime/shared/shell-display.mjs +4 -2
  115. package/src/runtime/shared/tool-surface.mjs +2 -2
  116. package/src/runtime/shared/turn-worktree-snapshot.mjs +11 -10
  117. package/src/runtime/shared/update-checker.mjs +2 -31
  118. package/src/session-runtime/boot/apis.mjs +5 -0
  119. package/src/session-runtime/boot/begin.mjs +0 -2
  120. package/src/session-runtime/boot/tools.mjs +5 -4
  121. package/src/session-runtime/model-recency.mjs +3 -0
  122. package/src/session-runtime/provider-auth/login.mjs +10 -10
  123. package/src/session-runtime/provider-auth/setup.mjs +22 -2
  124. package/src/session-runtime/provider-models/row-hydration.mjs +12 -4
  125. package/src/session-runtime/provider-readiness.mjs +4 -0
  126. package/src/session-runtime/resource-mcp-api.mjs +7 -3
  127. package/src/session-runtime/runtime-bootstrap.mjs +0 -4
  128. package/src/session-runtime/runtime-facade.mjs +5 -0
  129. package/src/session-runtime/runtime-paths.mjs +0 -1
  130. package/src/session-runtime/schedule-session-run.mjs +3 -1
  131. package/src/session-runtime/services/agent-tool/index-write-queue.mjs +55 -14
  132. package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +15 -3
  133. package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +2 -0
  134. package/src/session-runtime/services/agent-tool/worker-index/approval-wait.mjs +97 -0
  135. package/src/session-runtime/services/agent-tool/worker-index/mutation-batch.mjs +4 -2
  136. package/src/session-runtime/services/agent-tool/worker-index/row-liveness.mjs +8 -2
  137. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +3 -0
  138. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +58 -2
  139. package/src/session-runtime/services/agent-tool/worker-index.mjs +69 -15
  140. package/src/session-runtime/services/agent-tool/worker-rows.mjs +2 -0
  141. package/src/session-runtime/services/channel-admin.mjs +4 -2
  142. package/src/session-runtime/services/channel-worker.mjs +1 -1
  143. package/src/session-runtime/services/provider-admin.mjs +80 -17
  144. package/src/session-runtime/services/seeds.mjs +7 -10
  145. package/src/session-runtime/services/usage-dashboard-model.mjs +6 -0
  146. package/src/session-runtime/settings-builtin-tools-api.mjs +15 -0
  147. package/src/session-runtime/settings-profile-api.mjs +27 -2
  148. package/src/session-runtime/setup-tool/executor.mjs +5 -0
  149. package/src/session-runtime/setup-tool/tool-defs.mjs +8 -0
  150. package/src/session-runtime/starter-guide-state.mjs +62 -0
  151. package/src/session-runtime/tool-policy-refresh.mjs +3 -0
  152. package/src/session-runtime/webhook-session-run.mjs +3 -1
  153. package/src/session-runtime/workflow-agents-api/onboarding.mjs +3 -2
  154. package/src/standalone/channel-binding.mjs +1 -2
  155. package/src/standalone/channel-transport/call-dispatch.mjs +4 -10
  156. package/src/standalone/daemon-channels-loader.mjs +2 -3
  157. package/src/standalone/local-session-runtime.mjs +2 -78
  158. package/src/standalone/session-protocol.mjs +2 -0
  159. package/src/tui/app/model-options.mjs +13 -1
  160. package/src/tui/app/model-picker/route-selection/fast-parameters.mjs +10 -4
  161. package/src/tui/app/provider-setup/oauth-actions.mjs +5 -0
  162. package/src/tui/dist/index.mjs +84 -34
  163. package/src/tui/session/context-state.mjs +2 -0
  164. package/src/tui/session/live-share/owner.mjs +17 -0
  165. package/src/tui/session/oauth-flows.mjs +2 -0
  166. package/src/tui/session/session-api/extensions.mjs +12 -8
  167. package/src/tui/session/session-api/integrations.mjs +9 -8
  168. package/src/tui/session/session-api/routes.mjs +2 -2
  169. package/src/tui/session/session-api/settings.mjs +1 -0
  170. package/src/tui/session/session-api/shared.mjs +10 -6
  171. package/src/tui/session/tool-card-results/grouped-result.mjs +11 -2
  172. package/src/tui/session/transcript-spill/spill-dir.mjs +22 -6
  173. package/src/tui/spinner-meta.mjs +26 -10
  174. package/src/runtime/channels/tool-defs.mjs +0 -17
@@ -41514,7 +41514,7 @@ function describeError(value) {
41514
41514
  const { raw, message, status, code } = unwrap(value);
41515
41515
  const rejected429 = isRejected429(value);
41516
41516
  const details = safeErrorDetails(raw);
41517
- const clean2 = safeErrorDetails(message).replace(/^(?:Error invoking remote method ['"][^'"]+['"]:\s*)?(?:Error:\s*)?/i, "").trim();
41517
+ const clean3 = safeErrorDetails(message).replace(/^(?:Error invoking remote method ['"][^'"]+['"]:\s*)?(?:Error:\s*)?/i, "").trim();
41518
41518
  let kind = "unknown";
41519
41519
  let summary = "";
41520
41520
  let recovery = "";
@@ -41523,21 +41523,21 @@ function describeError(value) {
41523
41523
  kind = "reauth";
41524
41524
  summary = "Sign-in expired.";
41525
41525
  recovery = "Sign in again from Providers.";
41526
- } else if (status === 401 || status === 403 || /\b(?:invalid|expired)\s+(?:api[ _-]?key|access token|credentials?)\b|Provider authentication failed/i.test(clean2)) {
41526
+ } else if (status === 401 || status === 403 || /\b(?:invalid|expired)\s+(?:api[ _-]?key|access token|credentials?)\b|Provider authentication failed/i.test(clean3)) {
41527
41527
  kind = "authentication";
41528
41528
  summary = "Provider authentication failed";
41529
41529
  recovery = "Check your sign-in or API key, then try again.";
41530
41530
  } else if (/image.*dimensions.*exceed|image.*(?:too large|maximum.*(?:size|dimension))|many-image requests|An attached image exceeds the provider limit/i.test(
41531
- clean2
41531
+ clean3
41532
41532
  )) {
41533
41533
  kind = "image-size";
41534
41534
  summary = "An attached image exceeds the provider limit.";
41535
41535
  recovery = "Reduce the image dimensions or number of images, then try again.";
41536
- } else if (status === 413 || /payload too large|request (?:body )?too large|The request exceeds the size limit/i.test(clean2)) {
41536
+ } else if (status === 413 || /payload too large|request (?:body )?too large|The request exceeds the size limit/i.test(clean3)) {
41537
41537
  kind = "payload-size";
41538
41538
  summary = "The request exceeds the size limit.";
41539
41539
  recovery = "Reduce the attachments or request size, then try again.";
41540
- } else if (!rejected429 && (status === 429 || /rate[_ -]?limit|quota.*(?:hit|exceed)|too many requests|The provider usage limit was reached/i.test(clean2))) {
41540
+ } else if (!rejected429 && (status === 429 || /rate[_ -]?limit|quota.*(?:hit|exceed)|too many requests|The provider usage limit was reached/i.test(clean3))) {
41541
41541
  kind = "rate-limit";
41542
41542
  summary = "The provider usage limit was reached.";
41543
41543
  recovery = "Wait for the limit to reset or choose another account.";
@@ -41545,12 +41545,12 @@ function describeError(value) {
41545
41545
  kind = "connection";
41546
41546
  summary = transport.replace(/\.$/, "");
41547
41547
  recovery = "Check the connection, then try again.";
41548
- } else if (rejected429 || status === 400 || status === 422 || code === "invalid_request_error" || clean2 === "The provider rejected this request.") {
41548
+ } else if (rejected429 || status === 400 || status === 422 || code === "invalid_request_error" || clean3 === "The provider rejected this request.") {
41549
41549
  kind = "request";
41550
41550
  summary = "The provider rejected this request.";
41551
41551
  recovery = "Review the request details before trying again.";
41552
41552
  } else {
41553
- const lines = clean2.split("\n").map((line) => line.trim()).filter(Boolean);
41553
+ const lines = clean3.split("\n").map((line) => line.trim()).filter(Boolean);
41554
41554
  const first = lines.find((line) => !/^at\s|^\{|^<!doctype|^<html/i.test(line)) || "";
41555
41555
  summary = first && !/^[{[]|^<|(?:API|HTTP)\s+[45]\d\d.*[<{]/i.test(first) ? first : "Something went wrong.";
41556
41556
  }
@@ -48421,16 +48421,22 @@ function formatSpinnerTokens(value) {
48421
48421
  if (tokens >= 1e3) return compactNumberFormatter.format(tokens).toLowerCase();
48422
48422
  return String(Math.round(tokens));
48423
48423
  }
48424
- function effortSuffix(effort) {
48424
+ function effortLevel(effort) {
48425
48425
  const level = String(effort || "").trim().toLowerCase();
48426
48426
  if (!level || level === "auto" || level === "default" || level === "off" || level === "none") return "";
48427
- return ` (${level})`;
48427
+ return level;
48428
48428
  }
48429
- function spinnerThinkingLabel({ thinking = false, thinkingSince = 0, thinkingMs = 0, effort = "" } = {}) {
48430
- if (thinking || Number(thinkingSince) > 0) return `thinking${effortSuffix(effort)}`;
48429
+ function spinnerThinkingParts({ thinking = false, thinkingSince = 0, thinkingMs = 0, effort = "" } = {}) {
48430
+ if (thinking || Number(thinkingSince) > 0) return { kind: "thinking", effort: effortLevel(effort) };
48431
48431
  const ms = Math.max(0, Number(thinkingMs) || 0);
48432
- if (ms >= 1e3) return `thought for ${Math.max(1, Math.round(ms / 1e3))}s`;
48433
- return "";
48432
+ if (ms >= 1e3) return { kind: "thought", seconds: Math.max(1, Math.round(ms / 1e3)) };
48433
+ return null;
48434
+ }
48435
+ function spinnerThinkingLabel(options = {}) {
48436
+ const parts = spinnerThinkingParts(options);
48437
+ if (!parts) return "";
48438
+ if (parts.kind === "thinking") return `thinking${parts.effort ? ` (${parts.effort})` : ""}`;
48439
+ return `thought for ${parts.seconds}s`;
48434
48440
  }
48435
48441
  function buildSpinnerMeta({
48436
48442
  elapsedMs: _elapsedMs = 0,
@@ -48442,8 +48448,12 @@ function buildSpinnerMeta({
48442
48448
  verbose: _verbose = false
48443
48449
  } = {}) {
48444
48450
  const tokens = Math.max(0, Number(outputTokens) || 0);
48451
+ const thinkingParts = spinnerThinkingParts({ thinking, thinkingSince, thinkingMs, effort });
48445
48452
  const thinkingText = spinnerThinkingLabel({ thinking, thinkingSince, thinkingMs, effort });
48446
48453
  return {
48454
+ // Structured twins of tokensText / thinkingText for surfaces that translate them.
48455
+ tokensCount: tokens > 0 ? formatSpinnerTokens(tokens) : "",
48456
+ thinkingParts,
48447
48457
  tokensText: tokens > 0 ? `${formatSpinnerTokens(tokens)} tokens` : "",
48448
48458
  // The count appears with the FIRST token (user: 30초가 아니라 바로).
48449
48459
  // Elapsed was never gated, so the byline used to grow a second field
@@ -55140,7 +55150,7 @@ function createThemeEffortPickers({
55140
55150
  setProviderPrompt,
55141
55151
  setSettingsPrompt,
55142
55152
  closeUsagePanel,
55143
- clean: clean2
55153
+ clean: clean3
55144
55154
  }) {
55145
55155
  const openThemePicker = (options = {}) => {
55146
55156
  const returnTo = typeof options.returnTo === "function" ? options.returnTo : null;
@@ -55247,7 +55257,7 @@ function createThemeEffortPickers({
55247
55257
  ...item,
55248
55258
  marker: item?.value === current ? "\u2713" : "",
55249
55259
  markerColor: theme.success,
55250
- description: clean2(item?.description).toLowerCase() === "current" ? "" : item?.description
55260
+ description: clean3(item?.description).toLowerCase() === "current" ? "" : item?.description
55251
55261
  }));
55252
55262
  own.paint({
55253
55263
  title: "Effort",
@@ -55696,7 +55706,7 @@ var pluginDetailItems = (p) => [
55696
55706
  ];
55697
55707
  function createPluginsPickers({
55698
55708
  store,
55699
- clean: clean2,
55709
+ clean: clean3,
55700
55710
  copyToClipboard: copyToClipboard2,
55701
55711
  surface,
55702
55712
  setProviderPrompt,
@@ -55712,7 +55722,7 @@ function createPluginsPickers({
55712
55722
  const own = surface.claim();
55713
55723
  own.paint({
55714
55724
  title: p.title || p.name,
55715
- description: clean2(p.description) || "Update, MCP, or uninstall this plugin.",
55725
+ description: clean3(p.description) || "Update, MCP, or uninstall this plugin.",
55716
55726
  items: pluginDetailItems(p),
55717
55727
  onSelect: (_detailValue, detail) => {
55718
55728
  own.paint(null);
@@ -55899,7 +55909,7 @@ function createProjectSkillsPicker({
55899
55909
  // src/tui/app/extension-pickers/skills-pickers/skill-detail.mjs
55900
55910
  function createSkillDetailPickers({
55901
55911
  store,
55902
- clean: clean2,
55912
+ clean: clean3,
55903
55913
  surface,
55904
55914
  setSettingsPrompt,
55905
55915
  getDisabledSkills,
@@ -55922,7 +55932,7 @@ function createSkillDetailPickers({
55922
55932
  const openSkillDetailPicker = (skill) => {
55923
55933
  const own = surface.claim();
55924
55934
  const disabled = getDisabledSkills().has(skill.name);
55925
- const summary = [clean2(skill.description), clean2(skill.whenToUse)].filter(Boolean).join(" \u2014 ");
55935
+ const summary = [clean3(skill.description), clean3(skill.whenToUse)].filter(Boolean).join(" \u2014 ");
55926
55936
  own.paint({
55927
55937
  title: `Skill \xB7 ${skill.name}`,
55928
55938
  description: summary || "Enable, disable, or run this skill.",
@@ -55972,7 +55982,7 @@ function createSkillDetailPickers({
55972
55982
  function createSkillsPickers({
55973
55983
  store,
55974
55984
  theme: theme2,
55975
- clean: clean2,
55985
+ clean: clean3,
55976
55986
  surface,
55977
55987
  setProviderPrompt,
55978
55988
  setSettingsPrompt,
@@ -56029,7 +56039,7 @@ function createSkillsPickers({
56029
56039
  };
56030
56040
  const { openSkillDetailPicker } = createSkillDetailPickers({
56031
56041
  store,
56032
- clean: clean2,
56042
+ clean: clean3,
56033
56043
  surface,
56034
56044
  setSettingsPrompt,
56035
56045
  getDisabledSkills,
@@ -56051,7 +56061,7 @@ function createSkillsPickers({
56051
56061
  function createExtensionPickers({
56052
56062
  store,
56053
56063
  theme: theme2,
56054
- clean: clean2,
56064
+ clean: clean3,
56055
56065
  copyToClipboard: copyToClipboard2,
56056
56066
  surface,
56057
56067
  getPicker,
@@ -56064,7 +56074,7 @@ function createExtensionPickers({
56064
56074
  const skills = createSkillsPickers({
56065
56075
  store,
56066
56076
  theme: theme2,
56067
- clean: clean2,
56077
+ clean: clean3,
56068
56078
  surface,
56069
56079
  setProviderPrompt,
56070
56080
  setSettingsPrompt,
@@ -56073,7 +56083,7 @@ function createExtensionPickers({
56073
56083
  });
56074
56084
  const plugins = createPluginsPickers({
56075
56085
  store,
56076
- clean: clean2,
56086
+ clean: clean3,
56077
56087
  copyToClipboard: copyToClipboard2,
56078
56088
  surface,
56079
56089
  setProviderPrompt,
@@ -56667,6 +56677,25 @@ function isRollingModelAlias(id) {
56667
56677
  return /-latest$/i.test(String(id || "").trim());
56668
56678
  }
56669
56679
 
56680
+ // src/runtime/shared/llm/openai-daybreak.mjs
56681
+ var DAYBREAK_PROVIDER = "openai-oauth";
56682
+ var DAYBREAK_PARAMETER_ID = "daybreak";
56683
+ var DAYBREAK_ON = "on";
56684
+ var DAYBREAK_OFF = "off";
56685
+ var DAYBREAK_PARAMETER_OPTION = Object.freeze({
56686
+ id: DAYBREAK_PARAMETER_ID,
56687
+ label: "Daybreak Blue",
56688
+ kind: "boolean",
56689
+ options: Object.freeze([
56690
+ Object.freeze({ value: DAYBREAK_OFF, label: "Off" }),
56691
+ Object.freeze({ value: DAYBREAK_ON, label: "On" })
56692
+ ])
56693
+ });
56694
+ var clean2 = (value) => String(value ?? "").trim();
56695
+ function daybreakBlueOn(modelParameters) {
56696
+ return clean2(modelParameters?.[DAYBREAK_PARAMETER_ID]).toLowerCase() === DAYBREAK_ON;
56697
+ }
56698
+
56670
56699
  // src/tui/app/model-options.mjs
56671
56700
  var parsedModelVersion = (id) => {
56672
56701
  const text = String(id || "").toLowerCase();
@@ -56799,6 +56828,8 @@ var PROVIDER_DISPLAY_NAMES = /* @__PURE__ */ new Map([
56799
56828
  ["openai-oauth", "OpenAI OAuth"],
56800
56829
  ["anthropic-oauth", "Anthropic OAuth"],
56801
56830
  ["grok-oauth", "Grok OAuth"],
56831
+ ["muse-code-oauth", "Muse Code"],
56832
+ ["mimo-oauth", "MiMo"],
56802
56833
  ["cursor-oauth", "Cursor OAuth"],
56803
56834
  ["antigravity-oauth", "Antigravity OAuth"],
56804
56835
  ["openai", "OpenAI API"],
@@ -56822,6 +56853,8 @@ var PROVIDER_DISPLAY_RANKS = {
56822
56853
  "openai-oauth": 10,
56823
56854
  "anthropic-oauth": 20,
56824
56855
  "grok-oauth": 30,
56856
+ "muse-code-oauth": 33,
56857
+ "mimo-oauth": 34,
56825
56858
  "antigravity-oauth": 31,
56826
56859
  "cursor-oauth": 32,
56827
56860
  "opencode-go": 35,
@@ -56850,7 +56883,10 @@ var effortDisplayLabel = (value) => {
56850
56883
  var fastDisplayLabel = (enabled = true) => `Fast ${enabled ? "On" : "Off"}`;
56851
56884
  var modelDescription = (m) => [String(m?.description || "").trim(), m.fastCapable ? "Fast Available" : ""].filter(Boolean).join(" \xB7 ");
56852
56885
  var modelRecordDisplayName = (model) => displayModelName(model?.id, model?.provider, model?.display || model?.name);
56853
- var routeModelDisplayName = (route) => displayModelName(route?.model, route?.provider, route?.modelDisplay || "");
56886
+ var routeModelDisplayName = (route) => [
56887
+ displayModelName(route?.model, route?.provider, route?.modelDisplay || ""),
56888
+ route?.provider === DAYBREAK_PROVIDER && daybreakBlueOn(route?.modelParameters) ? "Blue" : ""
56889
+ ].filter(Boolean).join(" ");
56854
56890
  var groupModelsByProvider = (models) => {
56855
56891
  const providers = /* @__PURE__ */ new Map();
56856
56892
  for (const model of models) {
@@ -57612,6 +57648,11 @@ function beginInteractiveOAuthLogin(flow, providerItem, login) {
57612
57648
  `browser opened for ${providerName}; paste code/redirect here if callback does not finish`,
57613
57649
  "info"
57614
57650
  );
57651
+ } else if (started?.userCode) {
57652
+ flow.store.pushNotice(
57653
+ `${providerName}: enter code ${started.userCode} in the browser to finish signing in`,
57654
+ "info"
57655
+ );
57615
57656
  } else {
57616
57657
  flow.store.pushNotice(`browser opened for ${providerName}; finish signing in there`, "info");
57617
57658
  }
@@ -58074,6 +58115,7 @@ function createContextSelection({ state, currentRoute, isCurrentRoute, isStateRo
58074
58115
  }
58075
58116
 
58076
58117
  // src/tui/app/model-picker/route-selection/fast-parameters.mjs
58118
+ var TOGGLE_PARAMETER_IDS = /* @__PURE__ */ new Set(["thinking", DAYBREAK_PARAMETER_ID]);
58077
58119
  function createFastParameterSelection({ state, currentRoute, isCurrentRoute, isStateRoute, getSelectedEffort }) {
58078
58120
  const selectedFast = /* @__PURE__ */ new Map();
58079
58121
  const selectedModelParameters = /* @__PURE__ */ new Map();
@@ -58138,9 +58180,11 @@ function createFastParameterSelection({ state, currentRoute, isCurrentRoute, isS
58138
58180
  return true;
58139
58181
  };
58140
58182
  const cycleThinking = (model) => {
58141
- const wanted = "thinking";
58142
- const definition = (model.modelParameterOptions || []).find((parameter) => parameter.id === wanted);
58183
+ const definition = (model.modelParameterOptions || []).find(
58184
+ (parameter) => TOGGLE_PARAMETER_IDS.has(parameter.id)
58185
+ );
58143
58186
  if (!definition?.options?.length) return false;
58187
+ const wanted = definition.id;
58144
58188
  const parameters = modelParametersFor(model);
58145
58189
  const current = Math.max(
58146
58190
  0,
@@ -58431,7 +58475,7 @@ function createAgentsPicker({
58431
58475
  setProviderPrompt,
58432
58476
  setSettingsPrompt,
58433
58477
  closeUsagePanel,
58434
- clean: clean2,
58478
+ clean: clean3,
58435
58479
  agentModelParts: agentModelParts2,
58436
58480
  agentModelProfile: agentModelProfile2,
58437
58481
  openModelPicker
@@ -58515,7 +58559,7 @@ function createAgentsPicker({
58515
58559
  }
58516
58560
  const refreshModels = options.refreshModels === true;
58517
58561
  const routeOverrides = options.routeOverrides && typeof options.routeOverrides === "object" ? options.routeOverrides : {};
58518
- const initialAgentId = clean2(options.initialAgentId || "");
58562
+ const initialAgentId = clean3(options.initialAgentId || "");
58519
58563
  const items = agents.map((agent) => ({
58520
58564
  value: agent.id,
58521
58565
  label: agent.label,
@@ -58729,7 +58773,7 @@ function createRoutePickers({
58729
58773
  setProviderPrompt,
58730
58774
  setSettingsPrompt,
58731
58775
  closeUsagePanel,
58732
- clean: clean2,
58776
+ clean: clean3,
58733
58777
  routeLabel: routeLabel2,
58734
58778
  agentModelParts: agentModelParts2,
58735
58779
  agentModelProfile: agentModelProfile2,
@@ -58773,7 +58817,7 @@ function createRoutePickers({
58773
58817
  const panelDeps = { store, surface, setProviderPrompt, setSettingsPrompt, closeUsagePanel };
58774
58818
  return {
58775
58819
  openWebSearchPicker,
58776
- ...createAgentsPicker({ ...panelDeps, clean: clean2, agentModelParts: agentModelParts2, agentModelProfile: agentModelProfile2, openModelPicker }),
58820
+ ...createAgentsPicker({ ...panelDeps, clean: clean3, agentModelParts: agentModelParts2, agentModelProfile: agentModelProfile2, openModelPicker }),
58777
58821
  ...createWorkflowPicker({ ...panelDeps, workflowSwitchNotice: workflowSwitchNotice2 }),
58778
58822
  ...createOutputStylePicker(panelDeps)
58779
58823
  };
@@ -59017,7 +59061,13 @@ var {
59017
59061
  getSecret: _getSecret,
59018
59062
  setSecret: _setSecret,
59019
59063
  deleteSecret: _deleteSecret,
59020
- hasSecret: _hasSecret
59064
+ hasSecret: _hasSecret,
59065
+ setSecretAsync: _setSecretAsyncImpl,
59066
+ deleteSecretAsync: _deleteSecretAsyncImpl,
59067
+ keychainStatus: _keychainStatus,
59068
+ retryKeychain: _retryKeychain,
59069
+ refreshKeychainStatus: _refreshKeychainStatus,
59070
+ onKeychainRecovered: _onKeychainRecovered
59021
59071
  } = _require("../../lib/keychain-cjs.cjs");
59022
59072
  function configPath() {
59023
59073
  return join11(resolvePluginData(), "mixdog-config.json");
@@ -60869,13 +60919,13 @@ function useTerminalChrome({ stdout: stdout2, isRawModeSupported, setResizeState
60869
60919
  import { useCallback as useCallback21, useEffect as useEffect25, useLayoutEffect as useLayoutEffect8 } from "react";
60870
60920
 
60871
60921
  // src/tui/session/transcript-spill.mjs
60872
- import { readFileSync as readFileSync14 } from "node:fs";
60922
+ import { readFileSync as readFileSync15 } from "node:fs";
60873
60923
  import { join as join15 } from "node:path";
60874
60924
  import { Worker } from "node:worker_threads";
60875
60925
 
60876
60926
  // src/tui/session/transcript-spill/spill-dir.mjs
60877
60927
  import { randomUUID } from "node:crypto";
60878
- import { mkdtempSync, readdirSync as readdirSync5, rmSync as rmSync5, statSync as statSync5, writeFileSync as writeFileSync6 } from "node:fs";
60928
+ import { mkdtempSync, readdirSync as readdirSync5, readFileSync as readFileSync14, rmSync as rmSync5, statSync as statSync5, writeFileSync as writeFileSync6 } from "node:fs";
60879
60929
  import { tmpdir as tmpdir2 } from "node:os";
60880
60930
  import { join as join14 } from "node:path";
60881
60931
  var STALE_MS = 24 * 60 * 60 * 1e3;
@@ -56,6 +56,8 @@ export function createContextState({
56
56
  sessionProvider: runtime.sessionProvider ?? null,
57
57
  sessionModel: runtime.sessionModel ?? null,
58
58
  effort: runtime.effort,
59
+ // Resolved per-turn/per-step effort (Auto judge); null when none recorded.
60
+ turnEffort: runtime.turnEffort ?? null,
59
61
  effortOptions: runtime.effortOptions,
60
62
  fast: runtime.fast,
61
63
  fastCapable: runtime.fastCapable,
@@ -27,6 +27,21 @@ function unlinkQuietly(path) {
27
27
  }
28
28
  }
29
29
 
30
+ // Sockets this process still serves. A process that exits without closing its
31
+ // sessions (daemon shutdown, tray Quit) must not leave them behind in /tmp.
32
+ const servedSocketPaths = new Set();
33
+ let exitCleanupInstalled = false;
34
+ function serveSocketPath(path) {
35
+ if (process.platform === 'win32' || !path) return;
36
+ servedSocketPaths.add(path);
37
+ if (exitCleanupInstalled) return;
38
+ exitCleanupInstalled = true;
39
+ process.once('exit', () => {
40
+ for (const served of servedSocketPaths) unlinkQuietly(served);
41
+ servedSocketPaths.clear();
42
+ });
43
+ }
44
+
30
45
  export function createOwnerLeg({
31
46
  ownerSessionId,
32
47
  socketPathFor,
@@ -181,6 +196,7 @@ export function createOwnerLeg({
181
196
  /* already closed */
182
197
  }
183
198
  unlinkQuietly(serverPath);
199
+ servedSocketPaths.delete(serverPath);
184
200
  serverId = '';
185
201
  serverPath = '';
186
202
  };
@@ -216,6 +232,7 @@ export function createOwnerLeg({
216
232
  server = next;
217
233
  serverId = id;
218
234
  serverPath = path;
235
+ serveSocketPath(path);
219
236
  try {
220
237
  next.listen(path);
221
238
  } catch {
@@ -9,6 +9,7 @@ function oauthFlowStatus(flow) {
9
9
  provider: flow.provider,
10
10
  url: flow.url,
11
11
  manualUrl: flow.manualUrl,
12
+ userCode: flow.userCode,
12
13
  state: flow.state,
13
14
  completed: flow.state === 'complete',
14
15
  error: flow.error,
@@ -77,6 +78,7 @@ export function createSessionOAuthFlowRegistry({ ttlMs = DEFAULT_FLOW_TTL_MS } =
77
78
  provider,
78
79
  url: typeof started.url === 'string' ? started.url : null,
79
80
  manualUrl: typeof started.manualUrl === 'string' ? started.manualUrl : null,
81
+ userCode: typeof started.userCode === 'string' ? started.userCode : null,
80
82
  state: 'pending',
81
83
  result: null,
82
84
  error: null,
@@ -14,15 +14,19 @@ export function createSessionExtensionsApi(bag) {
14
14
  resetStatsAndSyncContext,
15
15
  routeState,
16
16
  });
17
- // One locked runtime mutation, then republish and announce it.
17
+ // One locked runtime mutation, then republish and announce it. A refused
18
+ // change throws so a caller never reports a skipped write as saved.
18
19
  const lockedChange = (call, notice) =>
19
- withCommandLock(async (...args) => {
20
- const result = await call(...args);
21
- refreshRouteStats();
22
- const [text, level = 'info'] = notice(result, ...args);
23
- pushNotice(text, level);
24
- return result;
25
- });
20
+ withCommandLock(
21
+ async (...args) => {
22
+ const result = await call(...args);
23
+ refreshRouteStats();
24
+ const [text, level = 'info'] = notice(result, ...args);
25
+ pushNotice(text, level);
26
+ return result;
27
+ },
28
+ { busyError: 'Another command is still running; try again when it finishes.' }
29
+ );
26
30
  const pluginLabel = (result, plugin) => result?.plugin?.title || result?.plugin?.name || plugin?.name || plugin;
27
31
 
28
32
  return {
@@ -68,6 +68,7 @@ export function createSessionIntegrationsApi(bag, { oauthFlows }) {
68
68
  // Completed-marking only; no route/agent/provider writes.
69
69
  return runtime.skipOnboarding?.() || null;
70
70
  },
71
+ saveStarterGuideState: (state) => runtime.saveStarterGuideState?.(state) || null,
71
72
  completeOnboarding: withCommandLock(async (payload = {}) => {
72
73
  const result = await runtime.completeOnboarding?.(payload);
73
74
  refreshRouteStats();
@@ -98,8 +99,8 @@ export function createSessionIntegrationsApi(bag, { oauthFlows }) {
98
99
  getOAuthProviderLoginStatus: (flowId) => oauthFlows.status(flowId),
99
100
  completeOAuthProviderLogin: async (flowId, code) => oauthFlows.complete(flowId, code),
100
101
  cancelOAuthProviderLogin: async (flowId) => oauthFlows.cancel(flowId),
101
- saveProviderApiKey: (provider, secret) => {
102
- const result = runtime.saveProviderApiKey(provider, secret);
102
+ saveProviderApiKey: async (provider, secret) => {
103
+ const result = await runtime.saveProviderApiKey(provider, secret);
103
104
  pushNotice(`provider api key saved: ${result.provider}`, 'info');
104
105
  return true;
105
106
  },
@@ -116,13 +117,13 @@ export function createSessionIntegrationsApi(bag, { oauthFlows }) {
116
117
  },
117
118
  testCustomProvider: (input) => runtime.testCustomProvider(input),
118
119
  discoverCustomProviderModels: (input) => runtime.discoverCustomProviderModels(input),
119
- saveOpenCodeGoUsageAuth: (opts) => {
120
- runtime.saveOpenCodeGoUsageAuth(opts);
120
+ saveOpenCodeGoUsageAuth: async (opts) => {
121
+ await runtime.saveOpenCodeGoUsageAuth(opts);
121
122
  pushNotice('OpenCode Go usage auth saved', 'info');
122
123
  return true;
123
124
  },
124
- saveOpenAIUsageSessionKey: (secret) => {
125
- runtime.saveOpenAIUsageSessionKey(secret);
125
+ saveOpenAIUsageSessionKey: async (secret) => {
126
+ await runtime.saveOpenAIUsageSessionKey(secret);
126
127
  pushNotice('OpenAI usage auth saved', 'info');
127
128
  return true;
128
129
  },
@@ -134,8 +135,8 @@ export function createSessionIntegrationsApi(bag, { oauthFlows }) {
134
135
  },
135
136
  { busyResult: false }
136
137
  ),
137
- forgetProviderAuth: (provider, accountId) => {
138
- const result = runtime.forgetProviderAuth(provider, accountId);
138
+ forgetProviderAuth: async (provider, accountId) => {
139
+ const result = await runtime.forgetProviderAuth(provider, accountId);
139
140
  pushNotice(`provider auth forgotten: ${result.provider}`, 'info');
140
141
  return true;
141
142
  },
@@ -148,8 +148,8 @@ export function createSessionRouteApi(bag) {
148
148
  listProviders: () => {
149
149
  return runtime.listProviders();
150
150
  },
151
- getProviderSetup: () => {
152
- return runtime.getProviderSetup();
151
+ getProviderSetup: (options = {}) => {
152
+ return runtime.getProviderSetup(options);
153
153
  },
154
154
  setRoute,
155
155
  setAgentRoute: async (agentId, opts) => {
@@ -130,6 +130,7 @@ export function createSessionSettingsApi(bag) {
130
130
  getDeveloperSettings: () => runtime.getDeveloperSettings?.(),
131
131
  setDeveloperOption: lockedRuntimeCall((id, enabled) => runtime.setDeveloperOption?.(id, enabled)),
132
132
  setWebSearchEnabled: lockedRuntimeCall((enabled) => runtime.setWebSearchEnabled?.(enabled)),
133
+ setInstructionFiles: lockedRuntimeCall((mode) => runtime.setInstructionFiles?.(mode)),
133
134
  setMemoryToolsEnabled: lockedRuntimeCall((enabled) => runtime.setMemoryToolsEnabled?.(enabled)),
134
135
  setBuiltinToolEnabled: lockedRuntimeCall((name, enabled) => runtime.setBuiltinToolEnabled?.(name, enabled)),
135
136
  installBuiltinFeature: lockedRuntimeCall((name) => runtime.installBuiltinFeature?.(name)),
@@ -5,15 +5,19 @@
5
5
  */
6
6
  export function createApiHelpers({ getState, set, resetStatsAndSyncContext, routeState, syncContextStats }) {
7
7
  /**
8
- * Wrap a runtime call in the command lock: refused (→ `busyResult`) while
9
- * another command holds commandBusy, otherwise held for the call's duration.
10
- * `onRelease` runs after the lock drops (RPC replies read the published
11
- * snapshot, not the mutable draft, so some callers flush there).
8
+ * Wrap a runtime call in the command lock: refused (→ `busyResult`, or a
9
+ * thrown `busyError` for callers that must not read a refusal as success)
10
+ * while another command holds commandBusy, otherwise held for the call's
11
+ * duration. `onRelease` runs after the lock drops (RPC replies read the
12
+ * published snapshot, not the mutable draft, so some callers flush there).
12
13
  */
13
14
  const withCommandLock =
14
- (run, { busyResult = null, onRelease = null } = {}) =>
15
+ (run, { busyResult = null, busyError = '', onRelease = null } = {}) =>
15
16
  async (...args) => {
16
- if (getState().commandBusy) return busyResult;
17
+ if (getState().commandBusy) {
18
+ if (busyError) throw new Error(busyError);
19
+ return busyResult;
20
+ }
17
21
  set({ commandBusy: true });
18
22
  try {
19
23
  return await run(...args);
@@ -5,7 +5,12 @@
5
5
  */
6
6
  import { toolGroupedDisplayFallback } from '../tool-result-text.mjs';
7
7
  import { parseAgentJob } from '../agent-envelope.mjs';
8
- import { groupedToolResultText, uiDiffPatchFromMessage, withCancelledResultMarker } from '../tool-result-status.mjs';
8
+ import {
9
+ groupedToolResultText,
10
+ toolMetaPatchFromMessage,
11
+ uiDiffPatchFromMessage,
12
+ withCancelledResultMarker,
13
+ } from '../tool-result-status.mjs';
9
14
  import { closeCard } from './item-patch.mjs';
10
15
 
11
16
  /**
@@ -69,7 +74,11 @@ export function applyGroupedResult(ctx, card, callId, outcome, message, rawText,
69
74
  if (group.errors > 0 && !String(displayResult || '').trim()) {
70
75
  displayResult = finalizedErrorFallbackBody(displayResult, text, exitCode);
71
76
  }
72
- const patch = { ...settledPatch(group, displayResult), ...uiDiffPatchFromMessage(message) };
77
+ const patch = {
78
+ ...settledPatch(group, displayResult),
79
+ ...uiDiffPatchFromMessage(message),
80
+ ...toolMetaPatchFromMessage(message),
81
+ };
73
82
  if (group.count <= 1) {
74
83
  applyAgentJobFields(ctx, patch, { itemId: card.itemId, group, text, rawText, isError, exitCode });
75
84
  }
@@ -5,7 +5,7 @@
5
5
  // proves the owner is still running, and the sweep that reclaims directories
6
6
  // of dead or long-silent owners.
7
7
  import { randomUUID } from 'node:crypto';
8
- import { mkdtempSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs';
8
+ import { mkdtempSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs';
9
9
  import { tmpdir } from 'node:os';
10
10
  import { join } from 'node:path';
11
11
 
@@ -62,11 +62,27 @@ export function cleanupStaleTranscriptSpillDirs({ root = tmpdir(), now = Date.no
62
62
  * from the live registry and cannot be mistaken for this process. Throws on
63
63
  * write failure; callers decide whether that is fatal. */
64
64
  export function writeOwnerRegistry(root = tmpdir()) {
65
- writeFileSync(
66
- join(root, `mixdog-transcript-owner-${process.pid}.json`),
67
- JSON.stringify({ pid: process.pid, nonce: PROCESS_NONCE }),
68
- 'utf8'
69
- );
65
+ const file = join(root, `mixdog-transcript-owner-${process.pid}.json`);
66
+ writeFileSync(file, JSON.stringify({ pid: process.pid, nonce: PROCESS_NONCE }), 'utf8');
67
+ ownerRegistryFiles.add(file);
68
+ installOwnerRegistryCleanup();
69
+ }
70
+
71
+ // The registry only has to outlive this process's spill directories. Remove it
72
+ // when the process exits (daemon shutdown, tray Quit) — but only a file that is
73
+ // still this run's: a PID-reuse successor may have rewritten it meanwhile.
74
+ const ownerRegistryFiles = new Set();
75
+ let ownerRegistryCleanupInstalled = false;
76
+ function installOwnerRegistryCleanup() {
77
+ if (ownerRegistryCleanupInstalled) return;
78
+ ownerRegistryCleanupInstalled = true;
79
+ process.once('exit', () => {
80
+ for (const file of ownerRegistryFiles) {
81
+ try {
82
+ if (JSON.parse(readFileSync(file, 'utf8'))?.nonce === PROCESS_NONCE) rmSync(file, { force: true });
83
+ } catch {}
84
+ }
85
+ });
70
86
  }
71
87
 
72
88
  export function createSpillDirectories() {