@theokit/sdk-tools 0.16.0 → 0.18.0

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.
package/dist/index.d.cts CHANGED
@@ -671,6 +671,18 @@ interface CreateReadFileToolOptions {
671
671
  * identical current behavior (multi-tenant / per-request roots).
672
672
  */
673
673
  filesystem?: FilesystemProvider;
674
+ /**
675
+ * M17 — render a `cat -n`-style numbered view (`<n>\t<line>`) instead of raw content, so the model can
676
+ * cite / edit by line number (Codex / Claude-Code read idiom). Default `false` ⇒ raw content (unchanged).
677
+ */
678
+ lineNumbers?: boolean;
679
+ /**
680
+ * M17 — opt-in "reads-anywhere" (Codex read-only sandbox): honor an ABSOLUTE `path` outside `projectRoot`
681
+ * instead of rejecting it as traversal. The `isForbiddenPath` secret guard STILL fires first, so `.env`/
682
+ * `.git`/lock files remain blocked. Default `false` ⇒ absolute paths rejected (unchanged). Opt-in only —
683
+ * this widens the read boundary to the whole filesystem; enable only for a trusted local agent.
684
+ */
685
+ allowAbsolute?: boolean;
674
686
  }
675
687
  declare function createReadFileTool(opts: CreateReadFileToolOptions): CustomTool;
676
688
 
@@ -910,6 +922,22 @@ interface TruncationResult {
910
922
  }
911
923
  declare function truncateOutput(output: string, opts?: TruncationOptions): TruncationResult;
912
924
 
925
+ /**
926
+ * `update_plan` — built-in tool for coding agents.
927
+ *
928
+ * Codex-faithful: the model posts a DECLARATIVE plan — an ordered list of short steps, each
929
+ * `pending | in_progress | completed` — and refreshes it as work proceeds. Codex's invariant is
930
+ * "exactly one step in_progress until everything is done"; this tool WARNS (never rejects) when that
931
+ * doesn't hold, so the agent self-corrects on the next update rather than failing the turn.
932
+ *
933
+ * Surface-agnostic by design (M17 DX): the result is STRUCTURED (`{ ok, steps, warning? }`) — each
934
+ * surface (terminal TUI, desktop, web) renders the checklist however it likes, rather than the package
935
+ * hard-coding glyphs. Result shape (always a JSON string):
936
+ * - `{ ok: true, explanation: string | null, steps: PlanStep[], warning?: string }`
937
+ */
938
+
939
+ declare function createUpdatePlanTool(): CustomTool;
940
+
913
941
  /**
914
942
  * `web_fetch` — built-in tool for coding agents.
915
943
  *
@@ -1073,4 +1101,4 @@ interface CreateWriteFileToolOptions {
1073
1101
  }
1074
1102
  declare function createWriteFileTool(opts: CreateWriteFileToolOptions): CustomTool;
1075
1103
 
1076
- export { CatastrophicCommandError, type CommandPolicy, ContextMatchError, type ContextMatchReason, type CreateApplyPatchToolOptions, type CreateBraveWebSearchAdapterOptions, type CreateCurrentTimeToolOptions, type CreateEditFileToolOptions, type CreateGenericHttpSearchAdapterOptions, type CreateGitDiffToolOptions, type CreateGlobToolOptions, type CreateInteractiveShellToolOptions, type CreateListDirToolOptions, type CreateReadFileToolOptions, type CreateRunVitestToolOptions, type CreateSearchTextToolOptions, type CreateShellToolOptions, type CreateWebFetchToolOptions, type CreateWebSearchToolOptions, type CreateWriteFileToolOptions, DEFAULT_TOOL_GUIDANCE, type EnvContextOptions, type PlanModeTool, type PlanModeToolOptions, type PlanModeToolWithStore, type PlanNode, type QuestionTool, type QuestionToolOptions, ReadTracker, ReasoningTools, RedirectBlockedError, type RepoMapOptions, type ResolveAndScreenOptions, type ScreenedFetchOptions, type SessionArtifactStore, type SessionArtifactStoreOptions, SsrfBlockedError, type TodoItem, type TodolistTool, type ToolGuidanceMap, type TruncationOptions, type TruncationResult, type VitestSummary, type WebSearchCallback, type WebSearchResult, buildEnvContext, buildRepoMap, catastrophicShellReason, commandDenialReason, createApplyPatchTool, createBraveWebSearchAdapter, createCurrentTimeTool, createEditFileTool, createGenericHttpSearchAdapter, createGitDiffTool, createGlobTool, createInteractiveShellTool, createListDirTool, createPlanModeTool, createQuestionTool, createReadFileTool, createRunVitestTool, createSearchTextTool, createSessionArtifactStore, createShellTool, createTodolistTool, createWebFetchTool, createWebSearchTool, createWriteFileTool, createWriteStdinTool, denyCatastrophicCommands, formatCode, formatDiff, formatError, formatFileList, injectGuidance, isBlockedIp, isCommandAllowed, renderToolList, replaceUnique, resolveAndScreen, screenedFetch, todoItemsToPlanNodes, truncateOutput, withDefaultGuidance, withDescription, withName, withShellExitGuidance, withToolResultGuidance };
1104
+ export { CatastrophicCommandError, type CommandPolicy, ContextMatchError, type ContextMatchReason, type CreateApplyPatchToolOptions, type CreateBraveWebSearchAdapterOptions, type CreateCurrentTimeToolOptions, type CreateEditFileToolOptions, type CreateGenericHttpSearchAdapterOptions, type CreateGitDiffToolOptions, type CreateGlobToolOptions, type CreateInteractiveShellToolOptions, type CreateListDirToolOptions, type CreateReadFileToolOptions, type CreateRunVitestToolOptions, type CreateSearchTextToolOptions, type CreateShellToolOptions, type CreateWebFetchToolOptions, type CreateWebSearchToolOptions, type CreateWriteFileToolOptions, DEFAULT_TOOL_GUIDANCE, type EnvContextOptions, type PlanModeTool, type PlanModeToolOptions, type PlanModeToolWithStore, type PlanNode, type QuestionTool, type QuestionToolOptions, ReadTracker, ReasoningTools, RedirectBlockedError, type RepoMapOptions, type ResolveAndScreenOptions, type ScreenedFetchOptions, type SessionArtifactStore, type SessionArtifactStoreOptions, SsrfBlockedError, type TodoItem, type TodolistTool, type ToolGuidanceMap, type TruncationOptions, type TruncationResult, type VitestSummary, type WebSearchCallback, type WebSearchResult, buildEnvContext, buildRepoMap, catastrophicShellReason, commandDenialReason, createApplyPatchTool, createBraveWebSearchAdapter, createCurrentTimeTool, createEditFileTool, createGenericHttpSearchAdapter, createGitDiffTool, createGlobTool, createInteractiveShellTool, createListDirTool, createPlanModeTool, createQuestionTool, createReadFileTool, createRunVitestTool, createSearchTextTool, createSessionArtifactStore, createShellTool, createTodolistTool, createUpdatePlanTool, createWebFetchTool, createWebSearchTool, createWriteFileTool, createWriteStdinTool, denyCatastrophicCommands, formatCode, formatDiff, formatError, formatFileList, injectGuidance, isBlockedIp, isCommandAllowed, renderToolList, replaceUnique, resolveAndScreen, screenedFetch, todoItemsToPlanNodes, truncateOutput, withDefaultGuidance, withDescription, withName, withShellExitGuidance, withToolResultGuidance };
package/dist/index.d.ts CHANGED
@@ -671,6 +671,18 @@ interface CreateReadFileToolOptions {
671
671
  * identical current behavior (multi-tenant / per-request roots).
672
672
  */
673
673
  filesystem?: FilesystemProvider;
674
+ /**
675
+ * M17 — render a `cat -n`-style numbered view (`<n>\t<line>`) instead of raw content, so the model can
676
+ * cite / edit by line number (Codex / Claude-Code read idiom). Default `false` ⇒ raw content (unchanged).
677
+ */
678
+ lineNumbers?: boolean;
679
+ /**
680
+ * M17 — opt-in "reads-anywhere" (Codex read-only sandbox): honor an ABSOLUTE `path` outside `projectRoot`
681
+ * instead of rejecting it as traversal. The `isForbiddenPath` secret guard STILL fires first, so `.env`/
682
+ * `.git`/lock files remain blocked. Default `false` ⇒ absolute paths rejected (unchanged). Opt-in only —
683
+ * this widens the read boundary to the whole filesystem; enable only for a trusted local agent.
684
+ */
685
+ allowAbsolute?: boolean;
674
686
  }
675
687
  declare function createReadFileTool(opts: CreateReadFileToolOptions): CustomTool;
676
688
 
@@ -910,6 +922,22 @@ interface TruncationResult {
910
922
  }
911
923
  declare function truncateOutput(output: string, opts?: TruncationOptions): TruncationResult;
912
924
 
925
+ /**
926
+ * `update_plan` — built-in tool for coding agents.
927
+ *
928
+ * Codex-faithful: the model posts a DECLARATIVE plan — an ordered list of short steps, each
929
+ * `pending | in_progress | completed` — and refreshes it as work proceeds. Codex's invariant is
930
+ * "exactly one step in_progress until everything is done"; this tool WARNS (never rejects) when that
931
+ * doesn't hold, so the agent self-corrects on the next update rather than failing the turn.
932
+ *
933
+ * Surface-agnostic by design (M17 DX): the result is STRUCTURED (`{ ok, steps, warning? }`) — each
934
+ * surface (terminal TUI, desktop, web) renders the checklist however it likes, rather than the package
935
+ * hard-coding glyphs. Result shape (always a JSON string):
936
+ * - `{ ok: true, explanation: string | null, steps: PlanStep[], warning?: string }`
937
+ */
938
+
939
+ declare function createUpdatePlanTool(): CustomTool;
940
+
913
941
  /**
914
942
  * `web_fetch` — built-in tool for coding agents.
915
943
  *
@@ -1073,4 +1101,4 @@ interface CreateWriteFileToolOptions {
1073
1101
  }
1074
1102
  declare function createWriteFileTool(opts: CreateWriteFileToolOptions): CustomTool;
1075
1103
 
1076
- export { CatastrophicCommandError, type CommandPolicy, ContextMatchError, type ContextMatchReason, type CreateApplyPatchToolOptions, type CreateBraveWebSearchAdapterOptions, type CreateCurrentTimeToolOptions, type CreateEditFileToolOptions, type CreateGenericHttpSearchAdapterOptions, type CreateGitDiffToolOptions, type CreateGlobToolOptions, type CreateInteractiveShellToolOptions, type CreateListDirToolOptions, type CreateReadFileToolOptions, type CreateRunVitestToolOptions, type CreateSearchTextToolOptions, type CreateShellToolOptions, type CreateWebFetchToolOptions, type CreateWebSearchToolOptions, type CreateWriteFileToolOptions, DEFAULT_TOOL_GUIDANCE, type EnvContextOptions, type PlanModeTool, type PlanModeToolOptions, type PlanModeToolWithStore, type PlanNode, type QuestionTool, type QuestionToolOptions, ReadTracker, ReasoningTools, RedirectBlockedError, type RepoMapOptions, type ResolveAndScreenOptions, type ScreenedFetchOptions, type SessionArtifactStore, type SessionArtifactStoreOptions, SsrfBlockedError, type TodoItem, type TodolistTool, type ToolGuidanceMap, type TruncationOptions, type TruncationResult, type VitestSummary, type WebSearchCallback, type WebSearchResult, buildEnvContext, buildRepoMap, catastrophicShellReason, commandDenialReason, createApplyPatchTool, createBraveWebSearchAdapter, createCurrentTimeTool, createEditFileTool, createGenericHttpSearchAdapter, createGitDiffTool, createGlobTool, createInteractiveShellTool, createListDirTool, createPlanModeTool, createQuestionTool, createReadFileTool, createRunVitestTool, createSearchTextTool, createSessionArtifactStore, createShellTool, createTodolistTool, createWebFetchTool, createWebSearchTool, createWriteFileTool, createWriteStdinTool, denyCatastrophicCommands, formatCode, formatDiff, formatError, formatFileList, injectGuidance, isBlockedIp, isCommandAllowed, renderToolList, replaceUnique, resolveAndScreen, screenedFetch, todoItemsToPlanNodes, truncateOutput, withDefaultGuidance, withDescription, withName, withShellExitGuidance, withToolResultGuidance };
1104
+ export { CatastrophicCommandError, type CommandPolicy, ContextMatchError, type ContextMatchReason, type CreateApplyPatchToolOptions, type CreateBraveWebSearchAdapterOptions, type CreateCurrentTimeToolOptions, type CreateEditFileToolOptions, type CreateGenericHttpSearchAdapterOptions, type CreateGitDiffToolOptions, type CreateGlobToolOptions, type CreateInteractiveShellToolOptions, type CreateListDirToolOptions, type CreateReadFileToolOptions, type CreateRunVitestToolOptions, type CreateSearchTextToolOptions, type CreateShellToolOptions, type CreateWebFetchToolOptions, type CreateWebSearchToolOptions, type CreateWriteFileToolOptions, DEFAULT_TOOL_GUIDANCE, type EnvContextOptions, type PlanModeTool, type PlanModeToolOptions, type PlanModeToolWithStore, type PlanNode, type QuestionTool, type QuestionToolOptions, ReadTracker, ReasoningTools, RedirectBlockedError, type RepoMapOptions, type ResolveAndScreenOptions, type ScreenedFetchOptions, type SessionArtifactStore, type SessionArtifactStoreOptions, SsrfBlockedError, type TodoItem, type TodolistTool, type ToolGuidanceMap, type TruncationOptions, type TruncationResult, type VitestSummary, type WebSearchCallback, type WebSearchResult, buildEnvContext, buildRepoMap, catastrophicShellReason, commandDenialReason, createApplyPatchTool, createBraveWebSearchAdapter, createCurrentTimeTool, createEditFileTool, createGenericHttpSearchAdapter, createGitDiffTool, createGlobTool, createInteractiveShellTool, createListDirTool, createPlanModeTool, createQuestionTool, createReadFileTool, createRunVitestTool, createSearchTextTool, createSessionArtifactStore, createShellTool, createTodolistTool, createUpdatePlanTool, createWebFetchTool, createWebSearchTool, createWriteFileTool, createWriteStdinTool, denyCatastrophicCommands, formatCode, formatDiff, formatError, formatFileList, injectGuidance, isBlockedIp, isCommandAllowed, renderToolList, replaceUnique, resolveAndScreen, screenedFetch, todoItemsToPlanNodes, truncateOutput, withDefaultGuidance, withDescription, withName, withShellExitGuidance, withToolResultGuidance };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { readFile, copyFile, mkdir, writeFile, readdir, open, stat } from 'fs/promises';
2
- import { dirname, join, relative, resolve, sep } from 'path';
2
+ import { dirname, join, relative, isAbsolute, resolve, sep } from 'path';
3
3
  import { Tool, ConfigurationError } from '@theokit/sdk';
4
4
  import { z } from 'zod';
5
5
  import { existsSync, statSync, mkdirSync, writeFileSync, realpathSync, readFileSync, lstatSync, readlinkSync, readdirSync } from 'fs';
@@ -1577,23 +1577,53 @@ function createQuestionTool(opts) {
1577
1577
  }
1578
1578
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
1579
1579
  var BINARY_PROBE_BYTES = 8 * 1024;
1580
+ var SENSITIVE_SEGMENTS = /* @__PURE__ */ new Set([".env", ".git", "node_modules", ".theo"]);
1581
+ function isForbiddenAtAnyDepth(path) {
1582
+ const segs = path.replace(/\\/g, "/").split("/").filter(Boolean);
1583
+ return segs.some((s) => {
1584
+ if (s === ".env.example") return false;
1585
+ return SENSITIVE_SEGMENTS.has(s) || /^\.env\./.test(s);
1586
+ });
1587
+ }
1588
+ function forbiddenReadError(path, allowAbsolute) {
1589
+ if (isForbiddenPath(path)) {
1590
+ return JSON.stringify({ ok: false, error: "forbidden_path", path });
1591
+ }
1592
+ if (allowAbsolute && isAbsolute(path) && isForbiddenAtAnyDepth(path)) {
1593
+ return JSON.stringify({ ok: false, error: "forbidden_path", path });
1594
+ }
1595
+ return null;
1596
+ }
1597
+ function renderView(content, opts) {
1598
+ const paginated = opts.offset !== void 0 || opts.limit !== void 0;
1599
+ if (!opts.lineNumbers && !paginated) return content;
1600
+ const lines = content.split("\n");
1601
+ const start = Math.max(1, opts.offset ?? 1);
1602
+ const end = opts.limit !== void 0 ? Math.min(lines.length, start - 1 + opts.limit) : lines.length;
1603
+ const slice = lines.slice(start - 1, end);
1604
+ return opts.lineNumbers ? slice.map((l, i) => `${start + i} ${l}`).join("\n") : slice.join("\n");
1605
+ }
1580
1606
  function createReadFileTool(opts) {
1581
- const { projectRoot, readTracker, filesystem } = opts;
1607
+ const { projectRoot, readTracker, filesystem, lineNumbers, allowAbsolute } = opts;
1608
+ const numbered = lineNumbers === true ? " Returns a cat -n numbered view (`<n>\\t<line>`)." : "";
1609
+ const abs = allowAbsolute === true ? " Absolute paths outside the project are honored." : "";
1582
1610
  return Tool.create({
1583
1611
  name: "read_file",
1584
- description: "Read a project-relative text file as UTF-8. ALWAYS read a file before you edit it (edit_file) or overwrite it (write_file), so your old_string / new content matches the real bytes exactly. Returns the WHOLE file (there is no offset or line-range parameter); to locate a symbol inside a large file, use search_text instead of re-reading. Refuses paths that escape the project root, sensitive files (.env, .git/, node_modules/, .theo/, lock files), and binary files (null byte in the first 8 KB); caps at 5 MB. Returns { ok, content, size } or { ok: false, error }.",
1612
+ description: "Read a text file as UTF-8. ALWAYS read a file before you edit it (edit_file) or overwrite it (write_file), so your old_string / new content matches the real bytes exactly." + numbered + abs + " By default returns the whole file; use the optional offset (1-based first line) + limit to page through a large file, or search_text to locate a symbol. Refuses sensitive files (.env, .git/, node_modules/, .theo/, lock files) and binary files (null byte in the first 8 KB); caps at 5 MB. Returns { ok, content, size } or { ok: false, error }.",
1585
1613
  inputSchema: z.object({
1586
- path: z.string().min(1).describe("Project-relative file path.")
1614
+ path: z.string().min(1).describe("File path (project-relative; absolute when allowed)."),
1615
+ offset: z.number().int().min(1).optional().describe("1-based first line to read (default 1)."),
1616
+ limit: z.number().int().min(1).optional().describe("Max number of lines to read (default: all).")
1587
1617
  }),
1588
- handler: async ({ path }, ctx) => {
1589
- if (isForbiddenPath(path)) {
1590
- return JSON.stringify({ ok: false, error: "forbidden_path", path });
1591
- }
1618
+ handler: async ({ path, offset, limit }, ctx) => {
1619
+ const forbidden = forbiddenReadError(path, allowAbsolute === true);
1620
+ if (forbidden !== null) return forbidden;
1621
+ const view = { lineNumbers, offset, limit };
1592
1622
  if (filesystem) {
1593
1623
  const backend = await resolveFilesystem(filesystem, ctx ?? {});
1594
- return readViaBackend(backend, path, (mtimeMs) => readTracker?.record(path, mtimeMs));
1624
+ return readViaBackend(backend, path, view, (mtimeMs) => readTracker?.record(path, mtimeMs));
1595
1625
  }
1596
- const boundary = resolveBoundary(path, projectRoot);
1626
+ const boundary = resolveBoundary(path, projectRoot, allowAbsolute === true);
1597
1627
  if ("error" in boundary) return boundary.error;
1598
1628
  const opened = await openHandleSafe(boundary.absolutePath, path);
1599
1629
  if ("error" in opened) return opened.error;
@@ -1601,6 +1631,7 @@ function createReadFileTool(opts) {
1601
1631
  return await readContent(
1602
1632
  opened.handle,
1603
1633
  path,
1634
+ view,
1604
1635
  (mtimeMs) => readTracker?.record(path, mtimeMs)
1605
1636
  );
1606
1637
  } finally {
@@ -1609,7 +1640,7 @@ function createReadFileTool(opts) {
1609
1640
  }
1610
1641
  });
1611
1642
  }
1612
- async function readViaBackend(backend, path, onRead) {
1643
+ async function readViaBackend(backend, path, view, onRead) {
1613
1644
  try {
1614
1645
  const stat2 = await backend.stat(path);
1615
1646
  if (stat2.size > MAX_FILE_SIZE) {
@@ -1621,12 +1652,12 @@ async function readViaBackend(backend, path, onRead) {
1621
1652
  limit: MAX_FILE_SIZE
1622
1653
  });
1623
1654
  }
1624
- const content = await backend.readFile(path);
1625
- if (content.includes("\0")) {
1655
+ const raw = await backend.readFile(path);
1656
+ if (raw.includes("\0")) {
1626
1657
  return JSON.stringify({ ok: false, error: "binary_file", path, size: stat2.size });
1627
1658
  }
1628
1659
  onRead?.(stat2.mtimeMs);
1629
- return JSON.stringify({ ok: true, content, size: stat2.size });
1660
+ return JSON.stringify({ ok: true, content: renderView(raw, view), size: stat2.size });
1630
1661
  } catch (err) {
1631
1662
  if (err instanceof FileNotFoundError) {
1632
1663
  return JSON.stringify({ ok: false, error: "not_found", path });
@@ -1637,7 +1668,10 @@ async function readViaBackend(backend, path, onRead) {
1637
1668
  throw err;
1638
1669
  }
1639
1670
  }
1640
- function resolveBoundary(path, projectRoot) {
1671
+ function resolveBoundary(path, projectRoot, allowAbsolute) {
1672
+ if (allowAbsolute && isAbsolute(path)) {
1673
+ return { absolutePath: path };
1674
+ }
1641
1675
  try {
1642
1676
  const absolutePath = safePathJoin(projectRoot, path);
1643
1677
  assertNoSymlinkEscape(absolutePath, projectRoot);
@@ -1661,7 +1695,7 @@ async function openHandleSafe(absolutePath, path) {
1661
1695
  throw err;
1662
1696
  }
1663
1697
  }
1664
- async function readContent(handle, path, onRead) {
1698
+ async function readContent(handle, path, view, onRead) {
1665
1699
  const stat2 = await handle.stat();
1666
1700
  if (stat2.size > MAX_FILE_SIZE) {
1667
1701
  return JSON.stringify({
@@ -1675,9 +1709,9 @@ async function readContent(handle, path, onRead) {
1675
1709
  if (await isBinaryProbe(handle, Number(stat2.size))) {
1676
1710
  return JSON.stringify({ ok: false, error: "binary_file", path, size: stat2.size });
1677
1711
  }
1678
- const content = await handle.readFile({ encoding: "utf-8" });
1712
+ const raw = await handle.readFile({ encoding: "utf-8" });
1679
1713
  onRead?.(stat2.mtimeMs);
1680
- return JSON.stringify({ ok: true, content, size: stat2.size });
1714
+ return JSON.stringify({ ok: true, content: renderView(raw, view), size: stat2.size });
1681
1715
  }
1682
1716
  async function isBinaryProbe(handle, size) {
1683
1717
  const probeLen = Math.min(BINARY_PROBE_BYTES, size);
@@ -2295,6 +2329,27 @@ function truncateOutput(output, opts) {
2295
2329
  overflowPath
2296
2330
  };
2297
2331
  }
2332
+ var STATUS = ["pending", "in_progress", "completed"];
2333
+ var planStepSchema = z.object({
2334
+ step: z.string().min(1).max(100).describe("A short step, \u2264 ~7 words."),
2335
+ status: z.enum(STATUS)
2336
+ });
2337
+ function createUpdatePlanTool() {
2338
+ return Tool.create({
2339
+ name: "update_plan",
2340
+ description: "Post or refresh a short plan so the user sees your progress on a multi-step task. Pass an ordered `plan` of steps, each with a status (pending | in_progress | completed); keep exactly one step in_progress at a time and mark steps completed as you finish. Returns { ok, steps, warning? } as a JSON string \u2014 the surface renders the checklist. A `warning` is returned (not an error) if the one-in_progress invariant is violated, so you can self-correct on the next update.",
2341
+ inputSchema: z.object({
2342
+ explanation: z.string().max(200).optional().describe("One line on what changed / why (optional)."),
2343
+ plan: z.array(planStepSchema).min(1).describe("The ordered steps.")
2344
+ }),
2345
+ handler: ({ explanation, plan }) => {
2346
+ const inProgress = plan.filter((s) => s.status === "in_progress").length;
2347
+ const allDone = plan.every((s) => s.status === "completed");
2348
+ const warning = !allDone && inProgress !== 1 ? `keep exactly one step in_progress until all are completed \u2014 found ${inProgress}` : void 0;
2349
+ return JSON.stringify({ ok: true, explanation: explanation ?? null, steps: plan, warning });
2350
+ }
2351
+ });
2352
+ }
2298
2353
  var DEFAULT_TIMEOUT_MS4 = 3e4;
2299
2354
  var MAX_BODY_BYTES = 1 * 1024 * 1024;
2300
2355
  function createWebFetchTool(opts) {
@@ -2597,6 +2652,6 @@ async function isBinaryFile(absolutePath) {
2597
2652
  }
2598
2653
  }
2599
2654
 
2600
- export { CatastrophicCommandError, ContextMatchError, DEFAULT_TOOL_GUIDANCE, ReadTracker, ReasoningTools, RedirectBlockedError, SsrfBlockedError, buildEnvContext, buildRepoMap, catastrophicShellReason, commandDenialReason, createApplyPatchTool, createBraveWebSearchAdapter, createCurrentTimeTool, createEditFileTool, createGenericHttpSearchAdapter, createGitDiffTool, createGlobTool, createInteractiveShellTool, createListDirTool, createPlanModeTool, createQuestionTool, createReadFileTool, createRunVitestTool, createSearchTextTool, createSessionArtifactStore, createShellTool, createTodolistTool, createWebFetchTool, createWebSearchTool, createWriteFileTool, createWriteStdinTool, denyCatastrophicCommands, formatCode, formatDiff, formatError, formatFileList, injectGuidance, isBlockedIp, isCommandAllowed, renderToolList, replaceUnique, resolveAndScreen, screenedFetch, todoItemsToPlanNodes, truncateOutput, withDefaultGuidance, withDescription, withName, withShellExitGuidance, withToolResultGuidance };
2655
+ export { CatastrophicCommandError, ContextMatchError, DEFAULT_TOOL_GUIDANCE, ReadTracker, ReasoningTools, RedirectBlockedError, SsrfBlockedError, buildEnvContext, buildRepoMap, catastrophicShellReason, commandDenialReason, createApplyPatchTool, createBraveWebSearchAdapter, createCurrentTimeTool, createEditFileTool, createGenericHttpSearchAdapter, createGitDiffTool, createGlobTool, createInteractiveShellTool, createListDirTool, createPlanModeTool, createQuestionTool, createReadFileTool, createRunVitestTool, createSearchTextTool, createSessionArtifactStore, createShellTool, createTodolistTool, createUpdatePlanTool, createWebFetchTool, createWebSearchTool, createWriteFileTool, createWriteStdinTool, denyCatastrophicCommands, formatCode, formatDiff, formatError, formatFileList, injectGuidance, isBlockedIp, isCommandAllowed, renderToolList, replaceUnique, resolveAndScreen, screenedFetch, todoItemsToPlanNodes, truncateOutput, withDefaultGuidance, withDescription, withName, withShellExitGuidance, withToolResultGuidance };
2601
2656
  //# sourceMappingURL=index.js.map
2602
2657
  //# sourceMappingURL=index.js.map