zelari-code 2.46.0 → 2.46.1

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.
@@ -38898,7 +38898,7 @@ var CORE_VERSION;
38898
38898
  var init_version = __esm({
38899
38899
  "packages/core/dist/version.js"() {
38900
38900
  "use strict";
38901
- CORE_VERSION = "2.46.0";
38901
+ CORE_VERSION = "2.46.1";
38902
38902
  }
38903
38903
  });
38904
38904
 
@@ -40110,6 +40110,7 @@ var init_cmdline = __esm({
40110
40110
  var updater_exports = {};
40111
40111
  __export(updater_exports, {
40112
40112
  REGISTRY_URL: () => REGISTRY_URL,
40113
+ UPDATE_CHECK_DELAY_MS: () => UPDATE_CHECK_DELAY_MS,
40113
40114
  checkForUpdate: () => checkForUpdate,
40114
40115
  compareSemver: () => compareSemver,
40115
40116
  distTagForVersion: () => distTagForVersion,
@@ -40120,7 +40121,8 @@ __export(updater_exports, {
40120
40121
  performUpdate: () => performUpdate,
40121
40122
  registryUrlForTag: () => registryUrlForTag,
40122
40123
  resolveBundledNpmCli: () => resolveBundledNpmCli,
40123
- resolveInstallKind: () => resolveInstallKind
40124
+ resolveInstallKind: () => resolveInstallKind,
40125
+ runDeferredUpdateCheck: () => runDeferredUpdateCheck
40124
40126
  });
40125
40127
  import { createRequire } from "node:module";
40126
40128
  import { execSync, spawn as spawn6 } from "node:child_process";
@@ -40251,6 +40253,23 @@ async function checkForUpdate(fetcher = fetch, registryUrl) {
40251
40253
  updateAvailable: cmp < 0
40252
40254
  };
40253
40255
  }
40256
+ async function runDeferredUpdateCheck(opts = {}) {
40257
+ const delayMs = opts.delayMs ?? UPDATE_CHECK_DELAY_MS;
40258
+ const sleep = opts.sleep ?? ((ms) => new Promise((resolve11) => setTimeout(resolve11, ms)));
40259
+ const report = opts.report ?? ((message) => {
40260
+ console.error(message);
40261
+ });
40262
+ try {
40263
+ await sleep(delayMs);
40264
+ const info = await (opts.check ?? (() => checkForUpdate()))();
40265
+ if (info.updateAvailable && !info.error) {
40266
+ report(
40267
+ `[zelari-code] \u{1F195} v${info.latestVersion} available (current: v${info.currentVersion}). Run \`zelari-code\` then \`/update --yes\` to upgrade.`
40268
+ );
40269
+ }
40270
+ } catch {
40271
+ }
40272
+ }
40254
40273
  async function performUpdate(packageName = "zelari-code", executor = spawn6, resolveNpmCli = resolveBundledNpmCli, channel, installKind = resolveInstallKind()) {
40255
40274
  if (installKind === "npx" || installKind === "local") {
40256
40275
  return {
@@ -40307,7 +40326,7 @@ function runNpm(executor, args, mode, npmCliPath) {
40307
40326
  });
40308
40327
  });
40309
40328
  }
40310
- var require2, __dirname2, PKG_ROOT, REGISTRY_URL;
40329
+ var require2, __dirname2, PKG_ROOT, REGISTRY_URL, UPDATE_CHECK_DELAY_MS;
40311
40330
  var init_updater = __esm({
40312
40331
  "src/cli/updater.ts"() {
40313
40332
  "use strict";
@@ -40316,6 +40335,7 @@ var init_updater = __esm({
40316
40335
  __dirname2 = path32.dirname(fileURLToPath(import.meta.url));
40317
40336
  PKG_ROOT = path32.resolve(__dirname2, "..", "..");
40318
40337
  REGISTRY_URL = "https://registry.npmjs.org/zelari-code/latest";
40338
+ UPDATE_CHECK_DELAY_MS = 12e3;
40319
40339
  }
40320
40340
  });
40321
40341
 
@@ -77834,26 +77854,59 @@ import { Box as Box9, Static, useInput as useInput2, useStdin as useStdin2 } fro
77834
77854
  import React from "react";
77835
77855
  import { Box, Text } from "ink";
77836
77856
  import TextInput from "ink-text-input";
77837
- function InputBarImpl({ value, onChange, onSubmit, disabled }) {
77857
+
77858
+ // src/cli/components/inputDraft.ts
77859
+ import { useSyncExternalStore } from "react";
77860
+ function createInputDraftStore(initial = "") {
77861
+ let value = initial;
77862
+ const listeners = /* @__PURE__ */ new Set();
77863
+ const emit = () => {
77864
+ for (const listener of listeners) listener();
77865
+ };
77866
+ return {
77867
+ get: () => value,
77868
+ set(next) {
77869
+ if (next === value) return;
77870
+ value = next;
77871
+ emit();
77872
+ },
77873
+ clear() {
77874
+ if (value === "") return;
77875
+ value = "";
77876
+ emit();
77877
+ },
77878
+ subscribe(listener) {
77879
+ listeners.add(listener);
77880
+ return () => {
77881
+ listeners.delete(listener);
77882
+ };
77883
+ }
77884
+ };
77885
+ }
77886
+ function useInputDraft(store6) {
77887
+ return useSyncExternalStore(store6.subscribe, store6.get, store6.get);
77888
+ }
77889
+
77890
+ // src/cli/components/InputBar.tsx
77891
+ function InputBarImpl({ draft, onSubmit, disabled }) {
77892
+ const value = useInputDraft(draft);
77838
77893
  const onSubmitRef = React.useRef(onSubmit);
77839
- const onChangeRef = React.useRef(onChange);
77840
77894
  onSubmitRef.current = onSubmit;
77841
- onChangeRef.current = onChange;
77842
77895
  const stableSubmit = React.useCallback((v) => onSubmitRef.current(v), []);
77843
- const stableChange = React.useCallback((v) => onChangeRef.current(v), []);
77844
77896
  return /* @__PURE__ */ React.createElement(Box, { borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "cyan", bold: true }, "\u276F "), /* @__PURE__ */ React.createElement(
77845
77897
  TextInput,
77846
77898
  {
77847
77899
  value,
77848
- onChange: stableChange,
77900
+ onChange: draft.set,
77849
77901
  onSubmit: stableSubmit,
77850
77902
  placeholder: disabled ? "..." : "Prompt, /skills, or @path"
77851
77903
  }
77852
77904
  ));
77853
77905
  }
77854
- var InputBar = React.memo(InputBarImpl, (prev2, next) => {
77855
- return prev2.value === next.value && prev2.disabled === next.disabled;
77856
- });
77906
+ function inputBarPropsEqual(prev2, next) {
77907
+ return prev2.draft === next.draft && prev2.disabled === next.disabled;
77908
+ }
77909
+ var InputBar = React.memo(InputBarImpl, inputBarPropsEqual);
77857
77910
 
77858
77911
  // src/cli/components/LiveRegion.tsx
77859
77912
  import React5 from "react";
@@ -78010,7 +78063,7 @@ init_duration();
78010
78063
  init_modelPricing();
78011
78064
  import React6 from "react";
78012
78065
  import { Box as Box5, Text as Text6 } from "ink";
78013
- function StatusBar({
78066
+ function StatusBarImpl({
78014
78067
  model,
78015
78068
  provider,
78016
78069
  sessionId: sessionId2,
@@ -78039,6 +78092,15 @@ function StatusBar({
78039
78092
  const modeColor = mode === "council" ? "magenta" : mode === "zelari" ? "green" : "red";
78040
78093
  return /* @__PURE__ */ React6.createElement(Box5, { paddingX: 1, width: "100%", justifyContent: "space-between", gap: 2 }, /* @__PURE__ */ React6.createElement(Box5, { flexShrink: 2 }, /* @__PURE__ */ React6.createElement(Text6, { wrap: "truncate" }, /* @__PURE__ */ React6.createElement(Text6, { color: sessionActive ? "green" : "gray" }, sessionActive ? "\u25CF" : "\u25CB"), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " "), /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: phase2 === "plan" ? "yellow" : "green" }, phase2 === "plan" ? "\u25C7 plan" : "\u25C6 build"), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: modeColor }, modeLabel), verify ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: verify.tone }, verify.label)) : null, permissions ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: permissions.tone }, permissions.label)) : null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), jail ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: jail.tone }, jail.label)) : null, /* @__PURE__ */ React6.createElement(Text6, { bold: true, color: "cyan" }, provider), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(Text6, null, model), cwd ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 "), /* @__PURE__ */ React6.createElement(Text6, { color: "blue" }, cwd)) : null)), /* @__PURE__ */ React6.createElement(Box5, { flexShrink: 1 }, /* @__PURE__ */ React6.createElement(Text6, { wrap: "truncate" }, busy && elapsedMs !== null ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Spinner, { color: "yellow" }), /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, " ", formatDuration(elapsedMs)), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : lastMs !== null ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "last ", formatDuration(lastMs)), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, queueCount > 0 ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { color: "magenta" }, "queue ", queueCount), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, todoSummary ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { color: "yellow" }, todoSummary), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, krakenLive ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { color: "magenta" }, krakenLive), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, krakenGraph ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { color: "magenta" }, krakenGraph), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, ctxLabel ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { color: "cyan" }, ctxLabel), /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, costUsd > 0 ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(Text6, { color: "green" }, formatCost(costUsd)), cachedTokens > 0 ? /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " (", formatTokens(cachedTokens), " cached)") : null, cacheHitRate > 0 ? /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " ", Math.round(cacheHitRate * 100), "% hit") : null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, " \xB7 ")) : null, /* @__PURE__ */ React6.createElement(Text6, { dimColor: true }, "session ", sessionId2))));
78041
78094
  }
78095
+ function statusChipPropsEqual(prev2, next) {
78096
+ if (prev2 === next) return true;
78097
+ if (!prev2 || !next) return false;
78098
+ return prev2.label === next.label && prev2.tone === next.tone;
78099
+ }
78100
+ function statusBarPropsEqual(prev2, next) {
78101
+ return prev2.model === next.model && prev2.provider === next.provider && prev2.sessionId === next.sessionId && prev2.sessionActive === next.sessionActive && prev2.queueCount === next.queueCount && prev2.busy === next.busy && prev2.mode === next.mode && prev2.phase === next.phase && prev2.cwd === next.cwd && prev2.elapsedMs === next.elapsedMs && prev2.lastMs === next.lastMs && prev2.costUsd === next.costUsd && prev2.cachedTokens === next.cachedTokens && prev2.cacheHitRate === next.cacheHitRate && prev2.contextUsed === next.contextUsed && prev2.contextLimit === next.contextLimit && prev2.todoSummary === next.todoSummary && prev2.krakenLive === next.krakenLive && prev2.krakenGraph === next.krakenGraph && statusChipPropsEqual(prev2.verify, next.verify) && statusChipPropsEqual(prev2.permissions, next.permissions) && statusChipPropsEqual(prev2.jail, next.jail);
78102
+ }
78103
+ var StatusBar = React6.memo(StatusBarImpl, statusBarPropsEqual);
78042
78104
 
78043
78105
  // src/cli/components/SelectList.tsx
78044
78106
  import React7, { useState as useState2 } from "react";
@@ -78248,32 +78310,56 @@ async function snapshotGitChanges(cwd) {
78248
78310
  files: mergeChanges(parseNumstat(unstaged), parseNumstat(staged), parseUntracked(status))
78249
78311
  };
78250
78312
  }
78313
+ var GIT_POLL_MS = 4e3;
78314
+ var GIT_IDLE_POLL_MS = 2e4;
78315
+ var GIT_IDLE_AFTER_TICKS = 3;
78316
+ function nextGitPollDelay(quietTicks, opts) {
78317
+ if (opts.hot) return opts.pollMs;
78318
+ return quietTicks >= opts.idleAfterTicks ? Math.max(opts.pollMs, opts.idlePollMs) : opts.pollMs;
78319
+ }
78251
78320
  function useGitChanges(opts = {}) {
78252
- const { pollMs = 4e3, cwd = process.cwd() } = opts;
78321
+ const {
78322
+ pollMs = GIT_POLL_MS,
78323
+ idlePollMs = GIT_IDLE_POLL_MS,
78324
+ idleAfterTicks = GIT_IDLE_AFTER_TICKS,
78325
+ hot = false,
78326
+ cwd = process.cwd(),
78327
+ snapshot = snapshotGitChanges
78328
+ } = opts;
78253
78329
  const [changes, setChanges] = useState3(EMPTY_GIT_CHANGES);
78254
78330
  const lastJson = useRef("");
78255
78331
  useEffect2(() => {
78256
78332
  let cancelled = false;
78257
78333
  let timer = null;
78334
+ let quiet = 0;
78258
78335
  const tick = async () => {
78259
78336
  try {
78260
- const snap = await snapshotGitChanges(cwd);
78337
+ const snap = await snapshot(cwd);
78261
78338
  if (cancelled) return;
78262
78339
  const json3 = JSON.stringify(snap);
78263
78340
  if (json3 !== lastJson.current) {
78264
78341
  lastJson.current = json3;
78342
+ quiet = 0;
78265
78343
  setChanges(snap);
78344
+ } else {
78345
+ quiet += 1;
78266
78346
  }
78267
78347
  } catch {
78348
+ quiet += 1;
78349
+ }
78350
+ if (!cancelled) {
78351
+ timer = setTimeout(
78352
+ tick,
78353
+ nextGitPollDelay(quiet, { pollMs, idlePollMs, idleAfterTicks, hot })
78354
+ );
78268
78355
  }
78269
- if (!cancelled) timer = setTimeout(tick, pollMs);
78270
78356
  };
78271
78357
  void tick();
78272
78358
  return () => {
78273
78359
  cancelled = true;
78274
78360
  if (timer !== null) clearTimeout(timer);
78275
78361
  };
78276
- }, [pollMs, cwd]);
78362
+ }, [pollMs, idlePollMs, idleAfterTicks, hot, cwd, snapshot]);
78277
78363
  return changes;
78278
78364
  }
78279
78365
 
@@ -78307,7 +78393,39 @@ init_paths2();
78307
78393
  init_sessionTodos();
78308
78394
  init_krakenLive();
78309
78395
  init_verifyStatus();
78396
+
78397
+ // src/cli/components/statusChips.ts
78310
78398
  init_osJail();
78399
+ init_policyLoadMode();
78400
+ function jailStatusChip(env = process.env, platform = process.platform) {
78401
+ const mode = activeJailMode(env);
78402
+ if (mode === "off") return null;
78403
+ const probe = probeJailBackend(platform);
78404
+ if (!probe.available) {
78405
+ return { label: `jail: advisory (${probe.backend})`, tone: "yellow" };
78406
+ }
78407
+ return mode === "required" ? { label: `jail: on (${probe.backend})`, tone: "green" } : { label: `jail: advisory (${probe.backend})`, tone: "yellow" };
78408
+ }
78409
+ function jailChipKey(env, platform) {
78410
+ return [
78411
+ platform,
78412
+ env[OS_JAIL_ENV] ?? "",
78413
+ env.ZELARI_PERMISSION_PRESET ?? "",
78414
+ env[POLICY_LOAD_MODE_ENV] ?? "",
78415
+ env.CI ?? "",
78416
+ activePolicyLoadSurface()
78417
+ ].join("|");
78418
+ }
78419
+ var chipCache = null;
78420
+ function cachedJailStatusChip(env = process.env, platform = process.platform) {
78421
+ const key = jailChipKey(env, platform);
78422
+ if (chipCache && chipCache.key === key) return chipCache.chip;
78423
+ const chip = jailStatusChip(env, platform);
78424
+ chipCache = { key, chip };
78425
+ return chip;
78426
+ }
78427
+
78428
+ // src/cli/app.tsx
78311
78429
  init_graphStatus();
78312
78430
 
78313
78431
  // packages/core/dist/agents/skills/builtin/debugging.js
@@ -86626,15 +86744,6 @@ function useTerminalSize(options = {}) {
86626
86744
  // src/cli/app.tsx
86627
86745
  init_chatStats();
86628
86746
  init_duration();
86629
- function jailStatusChip() {
86630
- const mode = activeJailMode();
86631
- if (mode === "off") return null;
86632
- const probe = probeJailBackend();
86633
- if (!probe.available) {
86634
- return { label: `jail: advisory (${probe.backend})`, tone: "yellow" };
86635
- }
86636
- return mode === "required" ? { label: `jail: on (${probe.backend})`, tone: "green" } : { label: `jail: advisory (${probe.backend})`, tone: "yellow" };
86637
- }
86638
86747
  var MODEL = process.env.OPENAI_MODEL ?? "grok-4.5";
86639
86748
  var providerDefaults = {
86640
86749
  "openai-compatible": "grok-4.5",
@@ -86646,7 +86755,8 @@ var providerDefaults = {
86646
86755
  "anthropic": "claude-sonnet-4-5"
86647
86756
  };
86648
86757
  function App() {
86649
- const [input, setInput] = useState8("");
86758
+ const [inputDraft] = useState8(() => createInputDraftStore());
86759
+ const setInput = useCallback5((value) => inputDraft.set(value), [inputDraft]);
86650
86760
  const [busy, setBusy] = useState8(false);
86651
86761
  const [providerConfig, setProviderConfig] = useState8(() => getProviderConfig());
86652
86762
  const [sessionStats, setSessionStats] = useState8({
@@ -86674,7 +86784,6 @@ function App() {
86674
86784
  const session = useSession();
86675
86785
  usePermissionBroker({ setPicker: setPicker2, setMessages: session.setMessages });
86676
86786
  const size = useTerminalSize();
86677
- const gitChanges = useGitChanges();
86678
86787
  const cwd = useMemo(() => shortenCwd(process.cwd(), 32), []);
86679
86788
  const timer = useExecutionTimer(busy);
86680
86789
  const { isRawModeSupported } = useStdin2();
@@ -86788,6 +86897,7 @@ function App() {
86788
86897
  useEffect8(() => {
86789
86898
  setSidebarOpen((prev2) => sidebarVisibility(size.columns, size.rows, prev2));
86790
86899
  }, [size.columns, size.rows]);
86900
+ const gitChanges = useGitChanges({ hot: busy || sidebarOpen });
86791
86901
  const staticKey = `${session.sessionId || "pre-bootstrap"}-${clearEpoch}`;
86792
86902
  const staticItems = session.sessionId ? [banner, ...session.messages] : [];
86793
86903
  return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(Static, { key: staticKey, items: staticItems }, (item) => item.id === "banner-once" ? /* @__PURE__ */ React10.createElement(
@@ -86822,8 +86932,7 @@ function App() {
86822
86932
  ) : /* @__PURE__ */ React10.createElement(
86823
86933
  InputBar,
86824
86934
  {
86825
- value: input,
86826
- onChange: setInput,
86935
+ draft: inputDraft,
86827
86936
  onSubmit: handleSubmit,
86828
86937
  disabled: busy
86829
86938
  }
@@ -86851,7 +86960,7 @@ function App() {
86851
86960
  krakenGraph: formatKrakenGraphSummary() ?? void 0,
86852
86961
  verify: getVerifyChip() ?? void 0,
86853
86962
  permissions: permissionsChip(phase2),
86854
- jail: jailStatusChip()
86963
+ jail: cachedJailStatusChip()
86855
86964
  }
86856
86965
  )), sidebarOpen && /* @__PURE__ */ React10.createElement(Sidebar, { version: VERSION, changes: gitChanges, rows: size.rows })));
86857
86966
  }
@@ -87807,17 +87916,8 @@ function runPreflight() {
87807
87916
  }
87808
87917
  async function backgroundUpdateCheck() {
87809
87918
  if (process.env.ANATHEMA_DEV === "1") return;
87810
- await new Promise((resolve11) => setTimeout(resolve11, 3e3));
87811
- try {
87812
- const { checkForUpdate: checkForUpdate2 } = await Promise.resolve().then(() => (init_updater(), updater_exports));
87813
- const info = await checkForUpdate2();
87814
- if (info.updateAvailable && !info.error) {
87815
- console.error(
87816
- `[zelari-code] \u{1F195} v${info.latestVersion} available (current: v${info.currentVersion}). Run \`zelari-code\` then \`/update --yes\` to upgrade.`
87817
- );
87818
- }
87819
- } catch {
87820
- }
87919
+ const { runDeferredUpdateCheck: runDeferredUpdateCheck2 } = await Promise.resolve().then(() => (init_updater(), updater_exports));
87920
+ await runDeferredUpdateCheck2();
87821
87921
  }
87822
87922
  async function shutdown() {
87823
87923
  try {