stratum-cli 0.8.0-beta.1 → 0.8.0-beta.3

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.
@@ -144,7 +144,9 @@
144
144
  "agents": {
145
145
  "defaultProfile": "general",
146
146
  "maxConcurrency": 1,
147
- "subagentRetentionDays": 30
147
+ "subagentRetentionDays": 30,
148
+ "subagentTimeoutMs": 1800000,
149
+ "subagentMaxIterations": 50
148
150
  },
149
151
  "skills": {
150
152
  "enabled": true,
package/CHANGELOG.md CHANGED
@@ -6,6 +6,25 @@ El formato sigue [Keep a Changelog](https://keepachangelog.com/es-ES/1.1.0/) y l
6
6
 
7
7
  > Las versiones anteriores a la 0.2.1-beta.0 solo existen como tags de git: la primera publicación en npm fue la 0.2.1-beta.0.
8
8
 
9
+ ## [0.8.0-beta.3] — 2026-10-12
10
+
11
+ Cuarta pre-release (`npm install -g stratum-cli@beta`).
12
+
13
+ ### Cambiado
14
+ - **Los subagentes tienen más margen**: el tiempo máximo por defecto pasa de 5 a 30 minutos y las iteraciones de 25 a 50. Ambos se ajustan en la config con `agents.subagentTimeoutMs` (`0` quita el límite de tiempo) y `agents.subagentMaxIterations`; lo que un perfil declare en su `budget` sigue ganando.
15
+
16
+ ### Corregido
17
+ - Un subagente que agotaba su tiempo aparecía como «cancelado», como si alguien lo hubiera parado. Ahora termina como presupuesto agotado, y el agente principal recibe el límite que se alcanzó, el aviso de que el trabajo parcial puede estar en disco y dónde se cambia.
18
+
19
+ ## [0.8.0-beta.2] — 2026-10-12
20
+
21
+ Tercera pre-release (`npm install -g stratum-cli@beta`), con más arreglos de lo visto al probar la beta.
22
+
23
+ ### Corregido
24
+ - **El terminal parpadeaba con varios subagentes trabajando.** El árbol de subagentes listaba todas sus tool calls; al superar el alto del terminal, la pantalla entera se borraba y repintaba en cada actualización. Ahora cada subagente enseña solo las últimas (entre 1 y 6, según el alto del terminal) y resume las anteriores en una línea; el detalle completo sigue en `/subagents`.
25
+ - La etiqueta de una tool call enseña el argumento que la identifica (la ruta, el comando, el patrón) aunque el modelo lo envíe detrás de otros: antes salía `read_file: 700` cuando `limit` llegaba antes que `path`.
26
+ - Dos sesiones nuevas guardadas en el mismo segundo podían recibir el mismo id y la segunda pisaba a la primera. Ahora el id generado se comprueba contra el disco.
27
+
9
28
  ## [0.8.0-beta.1] — 2026-10-12
10
29
 
11
30
  Segunda pre-release (`npm install -g stratum-cli@beta`), con lo visto al probar la beta.0.
@@ -284,6 +303,8 @@ Primera versión etiquetada. Hitos 0 y 1.
284
303
  - `/init` para generar o actualizar `STRATUM.md`.
285
304
  - Render de markdown de las respuestas.
286
305
 
306
+ [0.8.0-beta.3]: https://github.com/choruzo/CLI/compare/v0.8.0-beta.2...v0.8.0-beta.3
307
+ [0.8.0-beta.2]: https://github.com/choruzo/CLI/compare/v0.8.0-beta.1...v0.8.0-beta.2
287
308
  [0.8.0-beta.1]: https://github.com/choruzo/CLI/compare/v0.8.0-beta.0...v0.8.0-beta.1
288
309
  [0.8.0-beta.0]: https://github.com/choruzo/CLI/compare/v0.7.0...v0.8.0-beta.0
289
310
  [0.7.0]: https://github.com/choruzo/CLI/compare/v0.6.0...v0.7.0
package/dist/index.js CHANGED
@@ -643,7 +643,15 @@ var init_schema = __esm({
643
643
  * Días que se conservan los registros de `.stratum/subagents/` (8B endurecido).
644
644
  * `chat` purga al arrancar lo que lleve más sin tocarse; `0` lo desactiva.
645
645
  */
646
- subagentRetentionDays: z.number().int().nonnegative().default(30)
646
+ subagentRetentionDays: z.number().int().nonnegative().default(30),
647
+ /**
648
+ * Tiempo máximo de un subagente en ms, para los perfiles que no declaran
649
+ * `budget.timeoutMs`. `0` quita el límite: solo lo paran sus iteraciones,
650
+ * la cancelación del usuario o el fin del turno.
651
+ */
652
+ subagentTimeoutMs: z.number().int().nonnegative().default(30 * 60 * 1e3),
653
+ /** Iteraciones máximas de un subagente, para los perfiles sin `budget.maxIterations`. */
654
+ subagentMaxIterations: z.number().int().positive().default(50)
647
655
  }).default({}),
648
656
  /**
649
657
  * Registro de skills (Hito 12). Las skills en sí son ficheros sueltos
@@ -15921,6 +15929,15 @@ import { existsSync as existsSync11, readdirSync as readdirSync6, readFileSync a
15921
15929
  import { homedir as homedir4 } from "os";
15922
15930
  import { join as join16, resolve as resolve12 } from "path";
15923
15931
  import { z as z25 } from "zod";
15932
+ function resolveSubagentBudget(profile, agents) {
15933
+ const declared = profile.declaredBudget ?? {};
15934
+ const own = (key) => declared[key] ?? (profile.budget[key] !== DEFAULT_BUDGET[key] ? profile.budget[key] : void 0);
15935
+ return {
15936
+ maxIterations: own("maxIterations") ?? agents.subagentMaxIterations,
15937
+ maxTokens: declared.maxTokens ?? profile.budget.maxTokens,
15938
+ timeoutMs: own("timeoutMs") ?? agents.subagentTimeoutMs
15939
+ };
15940
+ }
15924
15941
  function isValidProfileName(name) {
15925
15942
  return PROFILE_NAME_RE.test(name) && !RESERVED_PROFILE_NAMES.has(name);
15926
15943
  }
@@ -15964,6 +15981,7 @@ function parseProfileDetailed(name, raw) {
15964
15981
  destructivePolicy: fm.destructivePolicy,
15965
15982
  budget,
15966
15983
  budgetDeclared: fm.budget !== void 0,
15984
+ declaredBudget: fm.budget ?? {},
15967
15985
  systemPromptFragment: body.trim() || GENERAL_PROFILE.systemPromptFragment
15968
15986
  }
15969
15987
  };
@@ -15986,7 +16004,7 @@ var init_profiles = __esm({
15986
16004
  init_frontmatter();
15987
16005
  init_logging();
15988
16006
  log15 = getLogger("agent");
15989
- DEFAULT_BUDGET = { maxIterations: 25, timeoutMs: 3e5 };
16007
+ DEFAULT_BUDGET = { maxIterations: 50, timeoutMs: 30 * 60 * 1e3 };
15990
16008
  PROFILE_NAME_RE = /^[a-z0-9][a-z0-9._-]*$/;
15991
16009
  RESERVED_PROFILE_NAMES = /* @__PURE__ */ new Set(["off", "default"]);
15992
16010
  DESCRIPTION_CAP = 160;
@@ -16309,10 +16327,10 @@ async function runSubagent(opts) {
16309
16327
  let tokenStatus = "unavailable";
16310
16328
  let currentText = "";
16311
16329
  let lastError;
16330
+ const budget = resolveSubagentBudget(profile, config.agents);
16312
16331
  let signal = parentSignal;
16313
- if (profile.budget.timeoutMs && profile.budget.timeoutMs > 0) {
16314
- signal = AbortSignal.any([parentSignal, AbortSignal.timeout(profile.budget.timeoutMs)]);
16315
- }
16332
+ const timeLimit = budget.timeoutMs && budget.timeoutMs > 0 ? AbortSignal.timeout(budget.timeoutMs) : null;
16333
+ if (timeLimit) signal = AbortSignal.any([parentSignal, timeLimit]);
16316
16334
  let router;
16317
16335
  try {
16318
16336
  if (opts.makeRouter) {
@@ -16384,8 +16402,8 @@ async function runSubagent(opts) {
16384
16402
  jobs: opts.jobs,
16385
16403
  jobScope: task.id,
16386
16404
  inbox: opts.inbox,
16387
- maxIterations: profile.budget.maxIterations,
16388
- maxTokens: profile.budget.maxTokens,
16405
+ maxIterations: budget.maxIterations,
16406
+ maxTokens: budget.maxTokens,
16389
16407
  trace: opts.trace
16390
16408
  };
16391
16409
  log17.info("subagent run", {
@@ -16393,7 +16411,8 @@ async function runSubagent(opts) {
16393
16411
  profile: profile.name,
16394
16412
  provider: router.providerName,
16395
16413
  model: router.model,
16396
- maxIterations: profile.budget.maxIterations
16414
+ maxIterations: budget.maxIterations,
16415
+ timeoutMs: budget.timeoutMs
16397
16416
  });
16398
16417
  let stopReason = "stop";
16399
16418
  try {
@@ -16463,7 +16482,8 @@ async function runSubagent(opts) {
16463
16482
  if (accounting.status !== "reported") {
16464
16483
  log17.debug("subagent tokens sin dato", { id: task.id, tokenStatus: accounting.status });
16465
16484
  }
16466
- const status = stopReason === "cancelled" ? "cancelled" : stopReason === "max_iterations" || stopReason === "budget_tokens" ? "budget_exceeded" : stopReason === "error" ? "failed" : "completed";
16485
+ const timedOut = timeLimit?.aborted === true && !parentSignal.aborted;
16486
+ const status = timedOut ? "budget_exceeded" : stopReason === "cancelled" ? "cancelled" : stopReason === "max_iterations" || stopReason === "budget_tokens" ? "budget_exceeded" : stopReason === "error" ? "failed" : "completed";
16467
16487
  const summary = truncateToolOutput(
16468
16488
  currentText.trim() || "El subagente termin\xF3 sin un resumen textual.",
16469
16489
  RESULT_SUMMARY_CAP
@@ -16476,7 +16496,7 @@ async function runSubagent(opts) {
16476
16496
  filesChanged: toFilesArray(filesChanged),
16477
16497
  decisions: decisions.length ? decisions : void 0,
16478
16498
  usage: { iterations, tokens, tokenStatus, durationMs: Date.now() - start },
16479
- error: status === "failed" && lastError ? `Subagent failed: ${lastError}` : statusErrorText(status)
16499
+ error: status === "failed" && lastError ? `Subagent failed: ${lastError}` : timedOut ? `Subagent ran out of time (${Math.round((budget.timeoutMs ?? 0) / 1e3)} s limit) before finishing. Its partial work may be on disk: check before redoing it. The limit is agents.subagentTimeoutMs in .stratumrc.json (0 = no limit), or budget.timeoutMs in the profile.` : statusErrorText(status)
16480
16500
  };
16481
16501
  }
16482
16502
  function canonicalChangePath(target, baseCwd, rawPath, cwd) {
@@ -16720,7 +16740,7 @@ async function* executeDelegations(jobs, ctx) {
16720
16740
  task: job.taskText,
16721
16741
  profile: job.profile.name,
16722
16742
  context: job.context,
16723
- budget: job.profile.budget
16743
+ budget: resolveSubagentBudget(job.profile, ctx.config.agents)
16724
16744
  },
16725
16745
  profile: job.profile,
16726
16746
  registry: ctx.registry,
@@ -19726,6 +19746,16 @@ var init_store2 = __esm({
19726
19746
  mkdirSync7(this.sessionsDir, { recursive: true });
19727
19747
  }
19728
19748
  }
19749
+ /**
19750
+ * Un id que no está en disco. El id lleva la hora al segundo y tres
19751
+ * caracteres al azar: dos sesiones guardadas en el mismo segundo pueden
19752
+ * coincidir, y la segunda pisaría a la primera.
19753
+ */
19754
+ freshSessionId() {
19755
+ let id = generateSessionId();
19756
+ while (existsSync16(this.sessionPath(id))) id = generateSessionId();
19757
+ return id;
19758
+ }
19729
19759
  sessionPath(id) {
19730
19760
  if (!isSessionId(id)) {
19731
19761
  throw new Error(`Id de sesi\xF3n inv\xE1lido: ${JSON.stringify(id.slice(0, 80))}`);
@@ -19747,14 +19777,14 @@ var init_store2 = __esm({
19747
19777
  async save(params) {
19748
19778
  this.ensureDir();
19749
19779
  const now = (/* @__PURE__ */ new Date()).toISOString();
19750
- let id = params.existingId ?? generateSessionId();
19780
+ let id = params.existingId ?? this.freshSessionId();
19751
19781
  let createdAt = params.createdAt ?? now;
19752
19782
  let forkedFrom = params.forkedFrom;
19753
19783
  if (params.existingId) {
19754
19784
  const onDisk = this.diskUpdatedAt(params.existingId);
19755
19785
  if (onDisk !== null && onDisk !== params.expectedUpdatedAt) {
19756
19786
  forkedFrom = params.existingId;
19757
- id = generateSessionId();
19787
+ id = this.freshSessionId();
19758
19788
  createdAt = now;
19759
19789
  log21.warn("session changed on disk: saving as a fork", { from: forkedFrom, to: id });
19760
19790
  }
@@ -20781,6 +20811,51 @@ var init_spinner = __esm({
20781
20811
  }
20782
20812
  });
20783
20813
 
20814
+ // src/cli/ui/tool-arg-label.ts
20815
+ function labelOf(value2) {
20816
+ if (value2 === null || value2 === void 0) return "";
20817
+ if (typeof value2 !== "object") return String(value2);
20818
+ if (!Array.isArray(value2)) return JSON.stringify(value2);
20819
+ const first = value2[0];
20820
+ const head = typeof first === "object" && first !== null ? Object.values(first).find((v) => typeof v === "string") ?? JSON.stringify(first) : String(first ?? "");
20821
+ return value2.length > 1 ? `${head} (+${value2.length - 1})` : head;
20822
+ }
20823
+ function primaryArg(input) {
20824
+ if (!input) return "";
20825
+ const keys = Object.keys(input);
20826
+ if (keys.length === 0) return "";
20827
+ const key = IDENTIFYING_KEYS.find((k) => typeof input[k] === "string" && input[k] !== "") ?? keys[0];
20828
+ return labelOf(input[key]);
20829
+ }
20830
+ function tailWindow(items, max) {
20831
+ const keep = Math.max(1, Math.floor(max));
20832
+ if (items.length <= keep) return { hidden: 0, visible: [...items] };
20833
+ return { hidden: items.length - keep, visible: items.slice(-keep) };
20834
+ }
20835
+ function treeToolBudget(rows, nodes, reservedRows = 22) {
20836
+ const perNode = Math.floor((rows - reservedRows) / Math.max(1, nodes)) - 2;
20837
+ return Math.min(6, Math.max(1, perNode));
20838
+ }
20839
+ var IDENTIFYING_KEYS;
20840
+ var init_tool_arg_label = __esm({
20841
+ "src/cli/ui/tool-arg-label.ts"() {
20842
+ "use strict";
20843
+ init_esm_shims();
20844
+ IDENTIFYING_KEYS = [
20845
+ "command",
20846
+ "path",
20847
+ "file_path",
20848
+ "filePath",
20849
+ "pattern",
20850
+ "query",
20851
+ "url",
20852
+ "task",
20853
+ "jobId",
20854
+ "name"
20855
+ ];
20856
+ }
20857
+ });
20858
+
20784
20859
  // src/cli/ui/ToolCallBlock.tsx
20785
20860
  import { Box, Text } from "ink";
20786
20861
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -20811,15 +20886,7 @@ function formatInput(state) {
20811
20886
  return truncateLabel(`${from} \u2192 ${to}`);
20812
20887
  }
20813
20888
  }
20814
- return truncateLabel(labelOf(src[keys[0]]));
20815
- }
20816
- function labelOf(value2) {
20817
- if (value2 === null || value2 === void 0) return "";
20818
- if (typeof value2 !== "object") return String(value2);
20819
- if (!Array.isArray(value2)) return JSON.stringify(value2);
20820
- const first = value2[0];
20821
- const head = typeof first === "object" && first !== null ? Object.values(first).find((v) => typeof v === "string") ?? JSON.stringify(first) : String(first ?? "");
20822
- return value2.length > 1 ? `${head} (+${value2.length - 1})` : head;
20889
+ return truncateLabel(primaryArg(src));
20823
20890
  }
20824
20891
  function formatDuration(ms) {
20825
20892
  return `${(ms / 1e3).toFixed(1)}s`;
@@ -20940,6 +21007,7 @@ var init_ToolCallBlock = __esm({
20940
21007
  init_esm_shims();
20941
21008
  init_theme();
20942
21009
  init_spinner();
21010
+ init_tool_arg_label();
20943
21011
  MAX_EXPANDED_LINES = 10;
20944
21012
  SLOW_MS = 1e3;
20945
21013
  }
@@ -22398,7 +22466,7 @@ var init_SubagentBlock = __esm({
22398
22466
  });
22399
22467
 
22400
22468
  // src/cli/ui/AgentTree.tsx
22401
- import { Box as Box12, Text as Text13 } from "ink";
22469
+ import { Box as Box12, Text as Text13, useStdout as useStdout3 } from "ink";
22402
22470
  import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
22403
22471
  function fmtDur2(ms) {
22404
22472
  return `${(ms / 1e3).toFixed(1)}s`;
@@ -22408,10 +22476,7 @@ function truncate2(text, max) {
22408
22476
  return oneLine.length > max ? oneLine.slice(0, max - 1) + "\u2026" : oneLine;
22409
22477
  }
22410
22478
  function firstArg(tc) {
22411
- const src = tc.input ?? {};
22412
- const keys = Object.keys(src);
22413
- if (keys.length === 0) return "";
22414
- return truncate2(String(src[keys[0]] ?? ""), 40);
22479
+ return truncate2(primaryArg(tc.input), 40);
22415
22480
  }
22416
22481
  function ToolLine({ tc }) {
22417
22482
  const icon = tc.status === "completed" ? "\u2713" : tc.status === "error" ? "\u2717" : "\u27F3";
@@ -22446,7 +22511,7 @@ function nodeIcon(status) {
22446
22511
  return { icon: "\u22B3", color: theme.accent };
22447
22512
  }
22448
22513
  }
22449
- function SubagentNode({ node, speaking, focused, expanded, isLast, now }) {
22514
+ function SubagentNode({ node, speaking, focused, expanded, isLast, now, maxToolLines }) {
22450
22515
  const running = node.status === "running";
22451
22516
  const elapsedMs = node.startedAt ? Math.max(0, now - node.startedAt) : 0;
22452
22517
  const { icon, color } = nodeIcon(node.status);
@@ -22458,7 +22523,7 @@ function SubagentNode({ node, speaking, focused, expanded, isLast, now }) {
22458
22523
  node.iterations !== void 0 ? `${node.iterations} it` : ""
22459
22524
  ].filter(Boolean).join(" \xB7 ");
22460
22525
  const tail2 = node.status === "failed" && node.error ? truncate2(node.error, 44) : node.status === "completed" && node.summary ? truncate2(node.summary, 44) : truncate2(node.task, 44);
22461
- const tcs = node.toolCalls ?? [];
22526
+ const { hidden, visible: tcs } = tailWindow(node.toolCalls ?? [], maxToolLines);
22462
22527
  const files = node.filesChanged ?? [];
22463
22528
  return /* @__PURE__ */ jsxs11(Box12, { flexDirection: "column", children: [
22464
22529
  /* @__PURE__ */ jsxs11(Text13, { wrap: "truncate-end", children: [
@@ -22482,6 +22547,15 @@ function SubagentNode({ node, speaking, focused, expanded, isLast, now }) {
22482
22547
  ] }),
22483
22548
  focused ? /* @__PURE__ */ jsx13(Text13, { color: theme.accent, children: " \u25C0" }) : null
22484
22549
  ] }),
22550
+ hidden > 0 && /* @__PURE__ */ jsxs11(Text13, { color: theme.textDisabled, wrap: "truncate-end", children: [
22551
+ " ",
22552
+ "\u2026 ",
22553
+ hidden,
22554
+ " ",
22555
+ hidden === 1 ? "acci\xF3n anterior" : "acciones anteriores",
22556
+ " ",
22557
+ "(/subagents para verlas)"
22558
+ ] }),
22485
22559
  tcs.map((tc) => /* @__PURE__ */ jsx13(ToolLine, { tc }, tc.id)),
22486
22560
  expanded && node.summary && /* @__PURE__ */ jsxs11(Text13, { color: theme.textFaint, wrap: "truncate-end", children: [
22487
22561
  " ",
@@ -22507,6 +22581,8 @@ function AgentTree({
22507
22581
  expandedBlockIds,
22508
22582
  now = Date.now()
22509
22583
  }) {
22584
+ const { stdout } = useStdout3();
22585
+ const maxToolLines = treeToolBudget(stdout?.rows ?? 24, nodes.length);
22510
22586
  const allTerminal = nodes.every((n) => TERMINAL.has(n.status));
22511
22587
  if (allTerminal) {
22512
22588
  const completed = nodes.filter((n) => n.status === "completed").length;
@@ -22552,7 +22628,8 @@ function AgentTree({
22552
22628
  focused: focusedBlockId === n.id,
22553
22629
  expanded: expandedBlockIds?.has(n.id) ?? false,
22554
22630
  isLast: i === nodes.length - 1,
22555
- now
22631
+ now,
22632
+ maxToolLines
22556
22633
  },
22557
22634
  n.id
22558
22635
  ))
@@ -22565,6 +22642,7 @@ var init_AgentTree = __esm({
22565
22642
  init_esm_shims();
22566
22643
  init_theme();
22567
22644
  init_spinner();
22645
+ init_tool_arg_label();
22568
22646
  TERMINAL = /* @__PURE__ */ new Set([
22569
22647
  "completed",
22570
22648
  "failed",
@@ -22786,7 +22864,7 @@ var init_AgentMessage = __esm({
22786
22864
  });
22787
22865
 
22788
22866
  // src/cli/ui/MessageList.tsx
22789
- import { Box as Box15, Static as Static2, useStdout as useStdout3 } from "ink";
22867
+ import { Box as Box15, Static as Static2, useStdout as useStdout4 } from "ink";
22790
22868
  import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
22791
22869
  function renderItem(item, key, focusedBlockId, expandedBlockIds, debug, now, liveTextLines, liveColumns, liveActionLimit) {
22792
22870
  if (item.kind === "user") {
@@ -22836,7 +22914,7 @@ function MessageList({
22836
22914
  now = Date.now(),
22837
22915
  availableRows
22838
22916
  }) {
22839
- const { stdout } = useStdout3();
22917
+ const { stdout } = useStdout4();
22840
22918
  const { contentWidth } = resolveLayout(stdout.columns ?? 80, stdout.rows ?? 24);
22841
22919
  const terminalRows = availableRows ?? stdout.rows ?? 24;
22842
22920
  const liveActionLimit = Math.max(1, Math.min(6, Math.floor((terminalRows - 8) / 2)));
@@ -23563,7 +23641,7 @@ var init_FatalError = __esm({
23563
23641
  });
23564
23642
 
23565
23643
  // src/cli/ui/ConversationView.tsx
23566
- import { Box as Box26, Text as Text27, useStdout as useStdout4 } from "ink";
23644
+ import { Box as Box26, Text as Text27, useStdout as useStdout5 } from "ink";
23567
23645
  import { jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
23568
23646
  function ConversationView({
23569
23647
  completedItems,
@@ -23613,7 +23691,7 @@ function ConversationView({
23613
23691
  const liveNow = useLiveClock(thinking);
23614
23692
  const gateOpen = !!pendingConfirm || !!pendingQuestions?.length || !!pendingApproval;
23615
23693
  const steerable = thinking && !gateOpen && !fatalError;
23616
- const { stdout } = useStdout4();
23694
+ const { stdout } = useStdout5();
23617
23695
  const terminalRows = stdout.rows ?? 24;
23618
23696
  const panelMaxSteps = Math.max(2, Math.min(5, Math.floor(terminalRows / 5)));
23619
23697
  const jobsClock = jobsNow ?? Date.now();
@@ -26961,7 +27039,7 @@ async function settle(step, fn) {
26961
27039
  }
26962
27040
  }
26963
27041
  function resolveVersion() {
26964
- if (true) return "0.8.0-beta.1";
27042
+ if (true) return "0.8.0-beta.3";
26965
27043
  try {
26966
27044
  const thisDir = dirname14(fileURLToPath2(import.meta.url));
26967
27045
  const pkg = JSON.parse(
@@ -32816,7 +32894,7 @@ function resolveResult(ref, dir) {
32816
32894
  }
32817
32895
 
32818
32896
  // src/cli/commands/eval.ts
32819
- var VERSION = true ? "0.8.0-beta.1" : "dev";
32897
+ var VERSION = true ? "0.8.0-beta.3" : "dev";
32820
32898
  var fail2 = (message) => {
32821
32899
  process.stderr.write(`${message}
32822
32900
  `);
@@ -33429,7 +33507,7 @@ var statsCommand = new Command14("stats").description(
33429
33507
  init_loader();
33430
33508
  init_schema_version();
33431
33509
  function resolveVersion2() {
33432
- if (true) return "0.8.0-beta.1";
33510
+ if (true) return "0.8.0-beta.3";
33433
33511
  const thisDir = dirname19(fileURLToPath5(import.meta.url));
33434
33512
  const pkg = JSON.parse(readFileSync26(join32(thisDir, "..", "..", "package.json"), "utf-8"));
33435
33513
  return pkg.version;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stratum-cli",
3
- "version": "0.8.0-beta.1",
3
+ "version": "0.8.0-beta.3",
4
4
  "description": "Agente CLI extensible sobre un loop ReAct — provider-agnostic (Ollama, llama.cpp, vLLM, LiteLLM, OpenAI), con plan-and-execute, subagentes, MCP y SSH nativo",
5
5
  "keywords": [
6
6
  "cli",