@theokit/sdk-tools 0.26.2 → 0.27.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
@@ -130,7 +130,7 @@ declare function createCurrentTimeTool(opts?: CreateCurrentTimeToolOptions): Cus
130
130
 
131
131
  interface CreateEditFileToolOptions {
132
132
  /**
133
- * M76 — nome exposto ao modelo. Omitidoo literal de hoje (aditivo).
133
+ * M76 — the name exposed to the model. Omittedtoday's literal (additive).
134
134
  *
135
135
  * It exists because, in Codex, the name is BORN in the tool definition and is the approval decision
136
136
  * key — three consumers (model, approval, telemetry) of a string decided in one place. Renaming
@@ -226,15 +226,15 @@ interface CreateGitStatusToolOptions {
226
226
  maxStdoutBytes?: number;
227
227
  /**
228
228
  * Injected execution backend (`@theokit/sdk/sandbox`) — when present, `git status` runs via
229
- * `SandboxBackend.execute`; omitidoo `git` local (inalterado).
229
+ * `SandboxBackend.execute`; omittedthe local `git` (unchanged).
230
230
  *
231
231
  * Symmetry with `createGitDiffTool`, flagged by the M76 review: without it `git_diff` would run
232
232
  * confined and `git_status` not, in the same session — and the asymmetry would be invisible until someone
233
- * perceber que uma das duas escapa do sandbox.
233
+ * notice that one of the two escapes the sandbox.
234
234
  */
235
235
  sandbox?: SandboxProvider;
236
236
  /**
237
- * M76 — nome exposto ao modelo. Omitido ⇒ `"git_status"` (aditivo).
237
+ * M76 — the name exposed to the model. Omitted ⇒ `"git_status"` (additive).
238
238
  *
239
239
  * The name is a contract: the approval key, what the model sees and what telemetry records.
240
240
  */
@@ -490,7 +490,7 @@ declare function buildRepoMap(cwd: string, opts?: RepoMapOptions): string;
490
490
  * This is a heuristic GUARDRAIL, NOT a sandbox: it is bypassable by deep obfuscation
491
491
  * (base64/env-indirection) and is best-effort. POSIX `/bin/sh` only; Windows
492
492
  * PowerShell is out of scope. True isolation needs a container.
493
- * referencia: .claude/knowledge-base/references/theocode-shell-guard/server-lib/shell-guard.ts
493
+ * reference: .claude/knowledge-base/references/theocode-shell-guard/server-lib/shell-guard.ts
494
494
  */
495
495
 
496
496
  /** Thrown / reported when a command matches the catastrophic deny-list. */
@@ -616,7 +616,7 @@ declare function withShellExitGuidance(tool: CustomTool): CustomTool;
616
616
 
617
617
  interface CreateListDirToolOptions {
618
618
  /**
619
- * M76 — nome exposto ao modelo. Omitidoo literal de hoje (aditivo).
619
+ * M76 — the name exposed to the model. Omittedtoday's literal (additive).
620
620
  *
621
621
  * It exists because, in Codex, the name is BORN in the tool definition and is the approval decision key —
622
622
  * three consumers (model, approval, telemetry) of a string decided in one place. Renaming
@@ -627,8 +627,8 @@ interface CreateListDirToolOptions {
627
627
  /** M76 — description exposed to the model. Omitted => today's literal (additive). */
628
628
  description?: string;
629
629
  /**
630
- * M76 — opt-in "lista-em-qualquer-lugar": honra um `path` ABSOLUTO fora de `projectRoot`
631
- * (paridade com `createReadFileTool`/`createSearchTextTool`, sandbox read-only do Codex).
630
+ * M76 — opt-in "list anywhere": honours an ABSOLUTE `path` outside `projectRoot`
631
+ * (parity with `createReadFileTool`/`createSearchTextTool`, Codex's read-only sandbox).
632
632
  *
633
633
  * The ANY-segment secret guard still applies, and is not separable: `isForbiddenPath`
634
634
  * only blocks the sensitive item when it is the FIRST segment, so a `/home/u/proj/.env/sub`
@@ -720,9 +720,9 @@ interface QuestionToolOptions {
720
720
  /**
721
721
  * Callback that presents the question to the user and resolves with the answer.
722
722
  *
723
- * M76 — passou a ser OPCIONAL: o asker preferencial vem do contexto da run
723
+ * M76 — became OPTIONAL: the preferred asker comes from the run context
724
724
  * (`ctx.context.askUser`), because a value pinned here is the "baked into each factory" that the
725
- * `CustomTool.handler` aponta como o problema que `ctx.context` existe para resolver. Este campo
725
+ * `CustomTool.handler` names as the problem `ctx.context` exists to solve. This field
726
726
  * remains as a fallback, for callers building the tool with a fixed asker (backward-compatible).
727
727
  */
728
728
  askUser?: (question: string, threadId?: string) => Promise<string>;
@@ -735,11 +735,11 @@ interface QuestionToolOptions {
735
735
  /** Maximum time to wait for user response in ms. Default: 300_000 (5 min). */
736
736
  timeoutMs?: number;
737
737
  /**
738
- * M76 — nome exposto ao modelo. Omitido ⇒ `"question"` (aditivo).
738
+ * M76 — the name exposed to the model. Omitted ⇒ `"question"` (additive).
739
739
  *
740
740
  * The consumer needed this: Codex calls the tool `request_user_input`, and without the option it
741
741
  * had to rebuild the whole object by hand — the two-cast adapter T3.3
742
- * eliminou.
742
+ * removed.
743
743
  */
744
744
  name?: string;
745
745
  /** M76 — description exposed to the model. Omitted => today's literal (additive). */
@@ -945,7 +945,7 @@ declare function createRunVitestTool(opts: CreateRunVitestToolOptions): CustomTo
945
945
 
946
946
  interface CreateSearchTextToolOptions {
947
947
  /**
948
- * M76 — nome exposto ao modelo. Omitidoo literal de hoje (aditivo).
948
+ * M76 — the name exposed to the model. Omittedtoday's literal (additive).
949
949
  *
950
950
  * It exists because, in Codex, the name is BORN in the tool definition and is the approval decision
951
951
  * key — three consumers (model, approval, telemetry) of a string decided in one place. Renaming
@@ -985,7 +985,7 @@ declare function createSearchTextTool(opts: CreateSearchTextToolOptions): Custom
985
985
 
986
986
  interface CreateShellToolOptions {
987
987
  /**
988
- * M76 — nome exposto ao modelo. Omitidoo literal de hoje (aditivo).
988
+ * M76 — the name exposed to the model. Omittedtoday's literal (additive).
989
989
  *
990
990
  * It exists because, in Codex, the name is BORN in the tool definition and is the approval decision
991
991
  * key — three consumers (model, approval, telemetry) of a string decided in one place. Renaming
@@ -1173,6 +1173,60 @@ declare function truncateOutput(output: string, opts?: TruncationOptions): Trunc
1173
1173
 
1174
1174
  declare function createUpdatePlanTool(): CustomTool;
1175
1175
 
1176
+ /**
1177
+ * `view_image` — let the agent LOOK at an image in the project.
1178
+ *
1179
+ * ## Why this is a built-in
1180
+ *
1181
+ * It was the one tool a consumer had to write from scratch (89 LOC), and its shape — a `handler`
1182
+ * returning a structured result plus `toModelOutput` shaping it into an `ImageBlock` — is the
1183
+ * canonical multimodal shape the SDK already defines (SE17). Every product that wants an agent to look at a
1184
+ * screenshot rewrites the same base64 + media-type + confinement logic.
1185
+ *
1186
+ * The confinement is the part that is easy to get wrong, and the reason this belongs in a reviewed
1187
+ * built-in rather than in each product: **an image reader that honours any path is a file
1188
+ * exfiltration primitive with a friendly name.** `/etc/passwd` renamed to `.png` is not a
1189
+ * hypothetical — it is one prompt away.
1190
+ *
1191
+ * ## The two channels
1192
+ *
1193
+ * This built-in uses the SE17 split. The handler returns the envelope as a JSON **string** — which
1194
+ * is what `Tool.create` types it to return — and `toModelOutput` turns that string into an
1195
+ * `ImageBlock` for the model, while `defineTool` routes the full value to `onToolEnd` through a
1196
+ * resolver under `TOOL_SPLIT_RESOLVER`.
1197
+ *
1198
+ * So `tool.handler(...)` yields image blocks on success and the JSON string on failure: the factory
1199
+ * has already applied the shaping. There is no `tool.toModelOutput` left to call, and returning the
1200
+ * envelope unshaped would send the model a base64 blob as TEXT — something it cannot look at, which
1201
+ * is the failure this tool exists to avoid.
1202
+ *
1203
+ * ## Result shape (the APP channel)
1204
+ *
1205
+ * - `{ ok: true, path, media_type, bytes, data }`
1206
+ * - `{ ok: false, error: "path_traversal" | "not_found" | "unsupported_image_type" | "image_too_large", … }`
1207
+ */
1208
+
1209
+ /**
1210
+ * Default ceiling: 5 MB on disk.
1211
+ *
1212
+ * Base64 inflates by 4/3 and the result lands directly in the model's context. A 20 MB screenshot is
1213
+ * not a slow request — it is a failed turn, and an expensive one.
1214
+ */
1215
+ declare const DEFAULT_MAX_IMAGE_BYTES: number;
1216
+ interface CreateViewImageToolOptions {
1217
+ /** Root the tool reads from. Every path is resolved inside it. */
1218
+ projectRoot: string;
1219
+ /** Name exposed to the model. Omitted ⇒ `view_image`. The name is a contract: it is the approval
1220
+ * key, what the model sees, and what telemetry records. */
1221
+ name?: string;
1222
+ /** Description exposed to the model. Omitted ⇒ the literal below. */
1223
+ description?: string;
1224
+ /** Ceiling in bytes, measured on disk. Omitted ⇒ {@link DEFAULT_MAX_IMAGE_BYTES}. */
1225
+ maxBytes?: number;
1226
+ }
1227
+ /** Read an image from the project so the model can look at it. */
1228
+ declare function createViewImageTool(options: CreateViewImageToolOptions): CustomTool;
1229
+
1176
1230
  /**
1177
1231
  * `web_fetch` — built-in tool for coding agents.
1178
1232
  *
@@ -1351,4 +1405,4 @@ interface CreateWriteFileToolOptions {
1351
1405
  }
1352
1406
  declare function createWriteFileTool(opts: CreateWriteFileToolOptions): CustomTool;
1353
1407
 
1354
- export { CatastrophicCommandError, type CommandPolicy, ContextMatchError, type ContextMatchReason, type CreateApplyPatchToolOptions, type CreateBraveWebSearchAdapterOptions, type CreateCurrentTimeToolOptions, type CreateEditFileToolOptions, type CreateGenericHttpSearchAdapterOptions, type CreateGitDiffToolOptions, type CreateGitStatusToolOptions, 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 TruncationMode, type TruncationOptions, type TruncationResult, type VitestSummary, type WebSearchCallback, type WebSearchResult, buildEnvContext, buildRepoMap, catastrophicShellReason, commandDenialReason, createApplyPatchTool, createBraveWebSearchAdapter, createCurrentTimeTool, createEditFileTool, createGenericHttpSearchAdapter, createGitDiffTool, createGitStatusTool, 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 };
1408
+ export { CatastrophicCommandError, type CommandPolicy, ContextMatchError, type ContextMatchReason, type CreateApplyPatchToolOptions, type CreateBraveWebSearchAdapterOptions, type CreateCurrentTimeToolOptions, type CreateEditFileToolOptions, type CreateGenericHttpSearchAdapterOptions, type CreateGitDiffToolOptions, type CreateGitStatusToolOptions, type CreateGlobToolOptions, type CreateInteractiveShellToolOptions, type CreateListDirToolOptions, type CreateReadFileToolOptions, type CreateRunVitestToolOptions, type CreateSearchTextToolOptions, type CreateShellToolOptions, type CreateViewImageToolOptions, type CreateWebFetchToolOptions, type CreateWebSearchToolOptions, type CreateWriteFileToolOptions, DEFAULT_MAX_IMAGE_BYTES, 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 TruncationMode, type TruncationOptions, type TruncationResult, type VitestSummary, type WebSearchCallback, type WebSearchResult, buildEnvContext, buildRepoMap, catastrophicShellReason, commandDenialReason, createApplyPatchTool, createBraveWebSearchAdapter, createCurrentTimeTool, createEditFileTool, createGenericHttpSearchAdapter, createGitDiffTool, createGitStatusTool, createGlobTool, createInteractiveShellTool, createListDirTool, createPlanModeTool, createQuestionTool, createReadFileTool, createRunVitestTool, createSearchTextTool, createSessionArtifactStore, createShellTool, createTodolistTool, createUpdatePlanTool, createViewImageTool, 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
@@ -130,7 +130,7 @@ declare function createCurrentTimeTool(opts?: CreateCurrentTimeToolOptions): Cus
130
130
 
131
131
  interface CreateEditFileToolOptions {
132
132
  /**
133
- * M76 — nome exposto ao modelo. Omitidoo literal de hoje (aditivo).
133
+ * M76 — the name exposed to the model. Omittedtoday's literal (additive).
134
134
  *
135
135
  * It exists because, in Codex, the name is BORN in the tool definition and is the approval decision
136
136
  * key — three consumers (model, approval, telemetry) of a string decided in one place. Renaming
@@ -226,15 +226,15 @@ interface CreateGitStatusToolOptions {
226
226
  maxStdoutBytes?: number;
227
227
  /**
228
228
  * Injected execution backend (`@theokit/sdk/sandbox`) — when present, `git status` runs via
229
- * `SandboxBackend.execute`; omitidoo `git` local (inalterado).
229
+ * `SandboxBackend.execute`; omittedthe local `git` (unchanged).
230
230
  *
231
231
  * Symmetry with `createGitDiffTool`, flagged by the M76 review: without it `git_diff` would run
232
232
  * confined and `git_status` not, in the same session — and the asymmetry would be invisible until someone
233
- * perceber que uma das duas escapa do sandbox.
233
+ * notice that one of the two escapes the sandbox.
234
234
  */
235
235
  sandbox?: SandboxProvider;
236
236
  /**
237
- * M76 — nome exposto ao modelo. Omitido ⇒ `"git_status"` (aditivo).
237
+ * M76 — the name exposed to the model. Omitted ⇒ `"git_status"` (additive).
238
238
  *
239
239
  * The name is a contract: the approval key, what the model sees and what telemetry records.
240
240
  */
@@ -490,7 +490,7 @@ declare function buildRepoMap(cwd: string, opts?: RepoMapOptions): string;
490
490
  * This is a heuristic GUARDRAIL, NOT a sandbox: it is bypassable by deep obfuscation
491
491
  * (base64/env-indirection) and is best-effort. POSIX `/bin/sh` only; Windows
492
492
  * PowerShell is out of scope. True isolation needs a container.
493
- * referencia: .claude/knowledge-base/references/theocode-shell-guard/server-lib/shell-guard.ts
493
+ * reference: .claude/knowledge-base/references/theocode-shell-guard/server-lib/shell-guard.ts
494
494
  */
495
495
 
496
496
  /** Thrown / reported when a command matches the catastrophic deny-list. */
@@ -616,7 +616,7 @@ declare function withShellExitGuidance(tool: CustomTool): CustomTool;
616
616
 
617
617
  interface CreateListDirToolOptions {
618
618
  /**
619
- * M76 — nome exposto ao modelo. Omitidoo literal de hoje (aditivo).
619
+ * M76 — the name exposed to the model. Omittedtoday's literal (additive).
620
620
  *
621
621
  * It exists because, in Codex, the name is BORN in the tool definition and is the approval decision key —
622
622
  * three consumers (model, approval, telemetry) of a string decided in one place. Renaming
@@ -627,8 +627,8 @@ interface CreateListDirToolOptions {
627
627
  /** M76 — description exposed to the model. Omitted => today's literal (additive). */
628
628
  description?: string;
629
629
  /**
630
- * M76 — opt-in "lista-em-qualquer-lugar": honra um `path` ABSOLUTO fora de `projectRoot`
631
- * (paridade com `createReadFileTool`/`createSearchTextTool`, sandbox read-only do Codex).
630
+ * M76 — opt-in "list anywhere": honours an ABSOLUTE `path` outside `projectRoot`
631
+ * (parity with `createReadFileTool`/`createSearchTextTool`, Codex's read-only sandbox).
632
632
  *
633
633
  * The ANY-segment secret guard still applies, and is not separable: `isForbiddenPath`
634
634
  * only blocks the sensitive item when it is the FIRST segment, so a `/home/u/proj/.env/sub`
@@ -720,9 +720,9 @@ interface QuestionToolOptions {
720
720
  /**
721
721
  * Callback that presents the question to the user and resolves with the answer.
722
722
  *
723
- * M76 — passou a ser OPCIONAL: o asker preferencial vem do contexto da run
723
+ * M76 — became OPTIONAL: the preferred asker comes from the run context
724
724
  * (`ctx.context.askUser`), because a value pinned here is the "baked into each factory" that the
725
- * `CustomTool.handler` aponta como o problema que `ctx.context` existe para resolver. Este campo
725
+ * `CustomTool.handler` names as the problem `ctx.context` exists to solve. This field
726
726
  * remains as a fallback, for callers building the tool with a fixed asker (backward-compatible).
727
727
  */
728
728
  askUser?: (question: string, threadId?: string) => Promise<string>;
@@ -735,11 +735,11 @@ interface QuestionToolOptions {
735
735
  /** Maximum time to wait for user response in ms. Default: 300_000 (5 min). */
736
736
  timeoutMs?: number;
737
737
  /**
738
- * M76 — nome exposto ao modelo. Omitido ⇒ `"question"` (aditivo).
738
+ * M76 — the name exposed to the model. Omitted ⇒ `"question"` (additive).
739
739
  *
740
740
  * The consumer needed this: Codex calls the tool `request_user_input`, and without the option it
741
741
  * had to rebuild the whole object by hand — the two-cast adapter T3.3
742
- * eliminou.
742
+ * removed.
743
743
  */
744
744
  name?: string;
745
745
  /** M76 — description exposed to the model. Omitted => today's literal (additive). */
@@ -945,7 +945,7 @@ declare function createRunVitestTool(opts: CreateRunVitestToolOptions): CustomTo
945
945
 
946
946
  interface CreateSearchTextToolOptions {
947
947
  /**
948
- * M76 — nome exposto ao modelo. Omitidoo literal de hoje (aditivo).
948
+ * M76 — the name exposed to the model. Omittedtoday's literal (additive).
949
949
  *
950
950
  * It exists because, in Codex, the name is BORN in the tool definition and is the approval decision
951
951
  * key — three consumers (model, approval, telemetry) of a string decided in one place. Renaming
@@ -985,7 +985,7 @@ declare function createSearchTextTool(opts: CreateSearchTextToolOptions): Custom
985
985
 
986
986
  interface CreateShellToolOptions {
987
987
  /**
988
- * M76 — nome exposto ao modelo. Omitidoo literal de hoje (aditivo).
988
+ * M76 — the name exposed to the model. Omittedtoday's literal (additive).
989
989
  *
990
990
  * It exists because, in Codex, the name is BORN in the tool definition and is the approval decision
991
991
  * key — three consumers (model, approval, telemetry) of a string decided in one place. Renaming
@@ -1173,6 +1173,60 @@ declare function truncateOutput(output: string, opts?: TruncationOptions): Trunc
1173
1173
 
1174
1174
  declare function createUpdatePlanTool(): CustomTool;
1175
1175
 
1176
+ /**
1177
+ * `view_image` — let the agent LOOK at an image in the project.
1178
+ *
1179
+ * ## Why this is a built-in
1180
+ *
1181
+ * It was the one tool a consumer had to write from scratch (89 LOC), and its shape — a `handler`
1182
+ * returning a structured result plus `toModelOutput` shaping it into an `ImageBlock` — is the
1183
+ * canonical multimodal shape the SDK already defines (SE17). Every product that wants an agent to look at a
1184
+ * screenshot rewrites the same base64 + media-type + confinement logic.
1185
+ *
1186
+ * The confinement is the part that is easy to get wrong, and the reason this belongs in a reviewed
1187
+ * built-in rather than in each product: **an image reader that honours any path is a file
1188
+ * exfiltration primitive with a friendly name.** `/etc/passwd` renamed to `.png` is not a
1189
+ * hypothetical — it is one prompt away.
1190
+ *
1191
+ * ## The two channels
1192
+ *
1193
+ * This built-in uses the SE17 split. The handler returns the envelope as a JSON **string** — which
1194
+ * is what `Tool.create` types it to return — and `toModelOutput` turns that string into an
1195
+ * `ImageBlock` for the model, while `defineTool` routes the full value to `onToolEnd` through a
1196
+ * resolver under `TOOL_SPLIT_RESOLVER`.
1197
+ *
1198
+ * So `tool.handler(...)` yields image blocks on success and the JSON string on failure: the factory
1199
+ * has already applied the shaping. There is no `tool.toModelOutput` left to call, and returning the
1200
+ * envelope unshaped would send the model a base64 blob as TEXT — something it cannot look at, which
1201
+ * is the failure this tool exists to avoid.
1202
+ *
1203
+ * ## Result shape (the APP channel)
1204
+ *
1205
+ * - `{ ok: true, path, media_type, bytes, data }`
1206
+ * - `{ ok: false, error: "path_traversal" | "not_found" | "unsupported_image_type" | "image_too_large", … }`
1207
+ */
1208
+
1209
+ /**
1210
+ * Default ceiling: 5 MB on disk.
1211
+ *
1212
+ * Base64 inflates by 4/3 and the result lands directly in the model's context. A 20 MB screenshot is
1213
+ * not a slow request — it is a failed turn, and an expensive one.
1214
+ */
1215
+ declare const DEFAULT_MAX_IMAGE_BYTES: number;
1216
+ interface CreateViewImageToolOptions {
1217
+ /** Root the tool reads from. Every path is resolved inside it. */
1218
+ projectRoot: string;
1219
+ /** Name exposed to the model. Omitted ⇒ `view_image`. The name is a contract: it is the approval
1220
+ * key, what the model sees, and what telemetry records. */
1221
+ name?: string;
1222
+ /** Description exposed to the model. Omitted ⇒ the literal below. */
1223
+ description?: string;
1224
+ /** Ceiling in bytes, measured on disk. Omitted ⇒ {@link DEFAULT_MAX_IMAGE_BYTES}. */
1225
+ maxBytes?: number;
1226
+ }
1227
+ /** Read an image from the project so the model can look at it. */
1228
+ declare function createViewImageTool(options: CreateViewImageToolOptions): CustomTool;
1229
+
1176
1230
  /**
1177
1231
  * `web_fetch` — built-in tool for coding agents.
1178
1232
  *
@@ -1351,4 +1405,4 @@ interface CreateWriteFileToolOptions {
1351
1405
  }
1352
1406
  declare function createWriteFileTool(opts: CreateWriteFileToolOptions): CustomTool;
1353
1407
 
1354
- export { CatastrophicCommandError, type CommandPolicy, ContextMatchError, type ContextMatchReason, type CreateApplyPatchToolOptions, type CreateBraveWebSearchAdapterOptions, type CreateCurrentTimeToolOptions, type CreateEditFileToolOptions, type CreateGenericHttpSearchAdapterOptions, type CreateGitDiffToolOptions, type CreateGitStatusToolOptions, 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 TruncationMode, type TruncationOptions, type TruncationResult, type VitestSummary, type WebSearchCallback, type WebSearchResult, buildEnvContext, buildRepoMap, catastrophicShellReason, commandDenialReason, createApplyPatchTool, createBraveWebSearchAdapter, createCurrentTimeTool, createEditFileTool, createGenericHttpSearchAdapter, createGitDiffTool, createGitStatusTool, 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 };
1408
+ export { CatastrophicCommandError, type CommandPolicy, ContextMatchError, type ContextMatchReason, type CreateApplyPatchToolOptions, type CreateBraveWebSearchAdapterOptions, type CreateCurrentTimeToolOptions, type CreateEditFileToolOptions, type CreateGenericHttpSearchAdapterOptions, type CreateGitDiffToolOptions, type CreateGitStatusToolOptions, type CreateGlobToolOptions, type CreateInteractiveShellToolOptions, type CreateListDirToolOptions, type CreateReadFileToolOptions, type CreateRunVitestToolOptions, type CreateSearchTextToolOptions, type CreateShellToolOptions, type CreateViewImageToolOptions, type CreateWebFetchToolOptions, type CreateWebSearchToolOptions, type CreateWriteFileToolOptions, DEFAULT_MAX_IMAGE_BYTES, 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 TruncationMode, type TruncationOptions, type TruncationResult, type VitestSummary, type WebSearchCallback, type WebSearchResult, buildEnvContext, buildRepoMap, catastrophicShellReason, commandDenialReason, createApplyPatchTool, createBraveWebSearchAdapter, createCurrentTimeTool, createEditFileTool, createGenericHttpSearchAdapter, createGitDiffTool, createGitStatusTool, createGlobTool, createInteractiveShellTool, createListDirTool, createPlanModeTool, createQuestionTool, createReadFileTool, createRunVitestTool, createSearchTextTool, createSessionArtifactStore, createShellTool, createTodolistTool, createUpdatePlanTool, createViewImageTool, 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 { rm, mkdir, writeFile, readFile, readdir, open, stat, copyFile } from 'fs/promises';
2
- import { dirname, relative, join, isAbsolute } from 'path';
2
+ import { dirname, relative, join, isAbsolute, extname } from 'path';
3
3
  import { Tool, ConfigurationError } from '@theokit/sdk';
4
4
  import { z } from 'zod';
5
5
  import { safePathJoin, assertNoSymlinkEscape, PathTraversalError, ForbiddenPathError, isForbiddenPath, safeFilenameForId } from '@theokit/sdk/path-safety';
@@ -791,12 +791,12 @@ function checkPathScope(path, projectRoot) {
791
791
  throw err;
792
792
  }
793
793
  }
794
- var SEGMENTOS_SENSIVEIS = /* @__PURE__ */ new Set([".env", ".git", "node_modules", ".theo"]);
795
- function ehProibidoEmQualquerProfundidade(path) {
794
+ var SENSITIVE_SEGMENTS = /* @__PURE__ */ new Set([".env", ".git", "node_modules", ".theo"]);
795
+ function isForbiddenAtAnyDepth(path) {
796
796
  const segs = path.replace(/\\/g, "/").split("/").filter(Boolean);
797
797
  return segs.some((s) => {
798
798
  if (s === ".env.example") return false;
799
- return SEGMENTOS_SENSIVEIS.has(s) || /^\.env\./.test(s);
799
+ return SENSITIVE_SEGMENTS.has(s) || /^\.env\./.test(s);
800
800
  });
801
801
  }
802
802
 
@@ -1584,7 +1584,7 @@ function createListDirTool(opts) {
1584
1584
  }),
1585
1585
  handler: async ({ path }, ctx) => {
1586
1586
  const relative3 = path === "" || path === "." ? "." : path;
1587
- const verdict = decidirEscopo(relative3, path, opts.allowAbsolute === true);
1587
+ const verdict = decideScope(relative3, path, opts.allowAbsolute === true);
1588
1588
  if (verdict.error !== void 0) return verdict.error;
1589
1589
  if (verdict.absoluteRoot !== void 0) {
1590
1590
  return listViaLocalFs(verdict.absoluteRoot, ".", path, max);
@@ -1597,14 +1597,14 @@ function createListDirTool(opts) {
1597
1597
  }
1598
1598
  });
1599
1599
  }
1600
- function decidirEscopo(relative3, original, allowAbsolute) {
1600
+ function decideScope(relative3, original, allowAbsolute) {
1601
1601
  const refuse = (error) => ({
1602
1602
  error: JSON.stringify({ ok: false, error, path: original })
1603
1603
  });
1604
1604
  if (relative3 !== "." && isForbiddenPath(relative3)) return refuse("forbidden_path");
1605
1605
  if (!isAbsolute(relative3)) return {};
1606
1606
  if (!allowAbsolute) return refuse("path_traversal");
1607
- if (ehProibidoEmQualquerProfundidade(relative3)) return refuse("forbidden_path");
1607
+ if (isForbiddenAtAnyDepth(relative3)) return refuse("forbidden_path");
1608
1608
  return { absoluteRoot: relative3 };
1609
1609
  }
1610
1610
  async function listViaLocalFs(projectRoot, relative3, originalPath, max) {
@@ -1767,10 +1767,10 @@ function createPlanModeTool(options) {
1767
1767
  }
1768
1768
 
1769
1769
  // src/question.ts
1770
- function askerDoContexto(context) {
1770
+ function askerFromContext(context) {
1771
1771
  if (typeof context !== "object" || context === null) return void 0;
1772
- const candidato = context.askUser;
1773
- return typeof candidato === "function" ? candidato : void 0;
1772
+ const candidate = context.askUser;
1773
+ return typeof candidate === "function" ? candidate : void 0;
1774
1774
  }
1775
1775
  function createQuestionTool(opts) {
1776
1776
  const timeoutMs = opts.timeoutMs ?? 3e5;
@@ -1785,7 +1785,7 @@ function createQuestionTool(opts) {
1785
1785
  required: ["question"]
1786
1786
  },
1787
1787
  handler: async (input, ctx) => {
1788
- const askUser = askerDoContexto(ctx?.context) ?? opts.askUser;
1788
+ const askUser = askerFromContext(ctx?.context) ?? opts.askUser;
1789
1789
  if (askUser === void 0) {
1790
1790
  return JSON.stringify({
1791
1791
  ok: false,
@@ -1822,7 +1822,7 @@ function forbiddenReadError(path, allowAbsolute) {
1822
1822
  if (isForbiddenPath(path)) {
1823
1823
  return JSON.stringify({ ok: false, error: "forbidden_path", path });
1824
1824
  }
1825
- if (allowAbsolute && isAbsolute(path) && ehProibidoEmQualquerProfundidade(path)) {
1825
+ if (allowAbsolute && isAbsolute(path) && isForbiddenAtAnyDepth(path)) {
1826
1826
  return JSON.stringify({ ok: false, error: "forbidden_path", path });
1827
1827
  }
1828
1828
  return null;
@@ -2625,6 +2625,86 @@ function createUpdatePlanTool() {
2625
2625
  }
2626
2626
  });
2627
2627
  }
2628
+ var MEDIA_TYPES = /* @__PURE__ */ new Map([
2629
+ [".png", "image/png"],
2630
+ [".jpg", "image/jpeg"],
2631
+ [".jpeg", "image/jpeg"],
2632
+ [".gif", "image/gif"],
2633
+ [".webp", "image/webp"]
2634
+ ]);
2635
+ var DEFAULT_MAX_IMAGE_BYTES = 5 * 1024 * 1024;
2636
+ var json = (result) => JSON.stringify(result);
2637
+ function createViewImageTool(options) {
2638
+ const { projectRoot } = options;
2639
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_IMAGE_BYTES;
2640
+ return Tool.create({
2641
+ name: options.name ?? "view_image",
2642
+ description: options.description ?? "Read an image file from the project and show it to the model. Supports png, jpeg, gif and webp.",
2643
+ inputSchema: z.object({
2644
+ path: z.string().describe("Path to the image, relative to the project root.")
2645
+ }),
2646
+ handler: (input) => {
2647
+ const refused = checkPathScope(input.path, projectRoot);
2648
+ if (refused !== null) return refused;
2649
+ if (isForbiddenAtAnyDepth(input.path)) {
2650
+ return json({ ok: false, error: "path_traversal", path: input.path });
2651
+ }
2652
+ const mediaType = MEDIA_TYPES.get(extname(input.path).toLowerCase());
2653
+ if (mediaType === void 0) {
2654
+ return json({
2655
+ ok: false,
2656
+ error: "unsupported_image_type",
2657
+ path: input.path,
2658
+ supported: [...MEDIA_TYPES.keys()]
2659
+ });
2660
+ }
2661
+ const absolute = safePathJoin(projectRoot, input.path);
2662
+ let bytes;
2663
+ try {
2664
+ bytes = statSync(absolute).size;
2665
+ } catch {
2666
+ return json({ ok: false, error: "not_found", path: input.path });
2667
+ }
2668
+ if (bytes > maxBytes) {
2669
+ return json({
2670
+ ok: false,
2671
+ error: "image_too_large",
2672
+ path: input.path,
2673
+ bytes,
2674
+ limit_bytes: maxBytes
2675
+ });
2676
+ }
2677
+ return json({
2678
+ ok: true,
2679
+ path: input.path,
2680
+ media_type: mediaType,
2681
+ bytes,
2682
+ data: readFileSync(absolute).toString("base64")
2683
+ });
2684
+ },
2685
+ /**
2686
+ * Turn a successful read into an image block.
2687
+ *
2688
+ * A failed read stays TEXT on purpose: the model needs to read "not_found" and try another path,
2689
+ * and an error is not something to look at.
2690
+ */
2691
+ toModelOutput: (output) => {
2692
+ let result;
2693
+ try {
2694
+ result = JSON.parse(output);
2695
+ } catch {
2696
+ return output;
2697
+ }
2698
+ if (result.ok !== true) return output;
2699
+ return [
2700
+ {
2701
+ type: "image",
2702
+ source: { type: "base64", media_type: result.media_type, data: result.data }
2703
+ }
2704
+ ];
2705
+ }
2706
+ });
2707
+ }
2628
2708
  var DEFAULT_TIMEOUT_MS4 = 3e4;
2629
2709
  var MAX_BODY_BYTES = 1 * 1024 * 1024;
2630
2710
  function createWebFetchTool(opts) {
@@ -2766,8 +2846,8 @@ function createBraveWebSearchAdapter(opts = {}) {
2766
2846
  headers: { "X-Subscription-Token": apiKey, Accept: "application/json" }
2767
2847
  });
2768
2848
  if (!res.ok) throw new Error(`brave_search_failed: HTTP ${res.status}`);
2769
- const json = await res.json();
2770
- const results = json?.web?.results ?? [];
2849
+ const json2 = await res.json();
2850
+ const results = json2?.web?.results ?? [];
2771
2851
  return results.map((r) => ({
2772
2852
  title: String(r?.title ?? ""),
2773
2853
  url: String(r?.url ?? ""),
@@ -2927,6 +3007,6 @@ async function isBinaryFile(absolutePath) {
2927
3007
  }
2928
3008
  }
2929
3009
 
2930
- export { CatastrophicCommandError, ContextMatchError, DEFAULT_TOOL_GUIDANCE, ReadTracker, ReasoningTools, RedirectBlockedError, SsrfBlockedError, buildEnvContext, buildRepoMap, catastrophicShellReason, commandDenialReason, createApplyPatchTool, createBraveWebSearchAdapter, createCurrentTimeTool, createEditFileTool, createGenericHttpSearchAdapter, createGitDiffTool, createGitStatusTool, 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 };
3010
+ export { CatastrophicCommandError, ContextMatchError, DEFAULT_MAX_IMAGE_BYTES, DEFAULT_TOOL_GUIDANCE, ReadTracker, ReasoningTools, RedirectBlockedError, SsrfBlockedError, buildEnvContext, buildRepoMap, catastrophicShellReason, commandDenialReason, createApplyPatchTool, createBraveWebSearchAdapter, createCurrentTimeTool, createEditFileTool, createGenericHttpSearchAdapter, createGitDiffTool, createGitStatusTool, createGlobTool, createInteractiveShellTool, createListDirTool, createPlanModeTool, createQuestionTool, createReadFileTool, createRunVitestTool, createSearchTextTool, createSessionArtifactStore, createShellTool, createTodolistTool, createUpdatePlanTool, createViewImageTool, createWebFetchTool, createWebSearchTool, createWriteFileTool, createWriteStdinTool, denyCatastrophicCommands, formatCode, formatDiff, formatError, formatFileList, injectGuidance, isBlockedIp, isCommandAllowed, renderToolList, replaceUnique, resolveAndScreen, screenedFetch, todoItemsToPlanNodes, truncateOutput, withDefaultGuidance, withDescription, withName, withShellExitGuidance, withToolResultGuidance };
2931
3011
  //# sourceMappingURL=index.js.map
2932
3012
  //# sourceMappingURL=index.js.map