@theokit/sdk-tools 0.21.0 → 0.22.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.cjs +136 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +111 -4
- package/dist/index.d.ts +111 -4
- package/dist/index.js +136 -80
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -119,6 +119,17 @@ declare function createCurrentTimeTool(opts?: CreateCurrentTimeToolOptions): Cus
|
|
|
119
119
|
*/
|
|
120
120
|
|
|
121
121
|
interface CreateEditFileToolOptions {
|
|
122
|
+
/**
|
|
123
|
+
* M76 — nome exposto ao modelo. Omitido ⇒ o literal de hoje (aditivo).
|
|
124
|
+
*
|
|
125
|
+
* Existe porque, no Codex, o nome NASCE na definição da tool e é a chave de decisão de approval —
|
|
126
|
+
* três consumidores (modelo, approval, telemetry) de uma string decidida num lugar só. Renomear
|
|
127
|
+
* depois da construção é mudar a identidade de algo já publicado ao modelo. `withName` continua
|
|
128
|
+
* para o caso genuinamente dinâmico.
|
|
129
|
+
*/
|
|
130
|
+
name?: string;
|
|
131
|
+
/** M76 — descrição exposta ao modelo. Omitida ⇒ o literal de hoje (aditivo). */
|
|
132
|
+
description?: string;
|
|
122
133
|
/** Absolute path to the project root. Every edit is gated against this boundary. */
|
|
123
134
|
projectRoot: string;
|
|
124
135
|
/** Optional injected filesystem (`@theokit/sdk/filesystem`) — when provided, the read + `.bak` backup +
|
|
@@ -175,6 +186,40 @@ interface CreateGitDiffToolOptions {
|
|
|
175
186
|
}
|
|
176
187
|
declare function createGitDiffTool(opts: CreateGitDiffToolOptions): CustomTool;
|
|
177
188
|
|
|
189
|
+
/**
|
|
190
|
+
* `git_status` — built-in tool for coding agents.
|
|
191
|
+
*
|
|
192
|
+
* Returns the working-tree status in porcelain v1 format (`git status --porcelain`), which is the
|
|
193
|
+
* stable machine-readable form — the human format is explicitly not guaranteed across git versions.
|
|
194
|
+
*
|
|
195
|
+
* M76 — nasce ao lado de `git_diff` e compartilha o motor de execução (`internal/git-exec.ts`): teto
|
|
196
|
+
* de stdout, kill do grupo de processos no timeout e mapeamento para erro tipado são a MESMA regra
|
|
197
|
+
* para qualquer subcomando do git. O consumidor (agent-builder) tinha isto local em 62 LoC; nada ali
|
|
198
|
+
* era específico dele.
|
|
199
|
+
*
|
|
200
|
+
* Result shape (always a JSON string):
|
|
201
|
+
* - `{ ok: true, diff: string, truncated?: boolean }` — `diff` carrega a saída porcelain
|
|
202
|
+
* - `{ ok: false, error: 'not_a_repo' | 'path_traversal' | 'timeout' | 'git_failed' }`
|
|
203
|
+
*/
|
|
204
|
+
|
|
205
|
+
interface CreateGitStatusToolOptions {
|
|
206
|
+
/** Absolute path to the project root. Every invocation is gated against this boundary. */
|
|
207
|
+
projectRoot: string;
|
|
208
|
+
/** Wall-clock cap; the process group is killed on expiry. Default 30_000. */
|
|
209
|
+
timeoutMs?: number;
|
|
210
|
+
/** Cap on captured stdout; excess sets `truncated: true`. Default 5 MB. */
|
|
211
|
+
maxStdoutBytes?: number;
|
|
212
|
+
/**
|
|
213
|
+
* M76 — nome exposto ao modelo. Omitido ⇒ `"git_status"` (aditivo).
|
|
214
|
+
*
|
|
215
|
+
* O nome é contrato: chave de approval, o que o modelo vê e o que o telemetry registra.
|
|
216
|
+
*/
|
|
217
|
+
name?: string;
|
|
218
|
+
/** M76 — descrição exposta ao modelo. Omitida ⇒ o literal abaixo (aditivo). */
|
|
219
|
+
description?: string;
|
|
220
|
+
}
|
|
221
|
+
declare function createGitStatusTool(opts: CreateGitStatusToolOptions): CustomTool;
|
|
222
|
+
|
|
178
223
|
/**
|
|
179
224
|
* `glob_files` — built-in tool for coding agents.
|
|
180
225
|
*
|
|
@@ -528,6 +573,26 @@ declare function withShellExitGuidance(tool: CustomTool): CustomTool;
|
|
|
528
573
|
*/
|
|
529
574
|
|
|
530
575
|
interface CreateListDirToolOptions {
|
|
576
|
+
/**
|
|
577
|
+
* M76 — nome exposto ao modelo. Omitido ⇒ o literal de hoje (aditivo).
|
|
578
|
+
*
|
|
579
|
+
* Existe porque, no Codex, o nome NASCE na definição da tool e é a chave de decisão de approval —
|
|
580
|
+
* três consumidores (modelo, approval, telemetry) de uma string decidida num lugar só. Renomear
|
|
581
|
+
* depois da construção é mudar a identidade de algo já publicado ao modelo. `withName` continua
|
|
582
|
+
* para o caso genuinamente dinâmico.
|
|
583
|
+
*/
|
|
584
|
+
name?: string;
|
|
585
|
+
/** M76 — descrição exposta ao modelo. Omitida ⇒ o literal de hoje (aditivo). */
|
|
586
|
+
description?: string;
|
|
587
|
+
/**
|
|
588
|
+
* M76 — opt-in "lista-em-qualquer-lugar": honra um `path` ABSOLUTO fora de `projectRoot`
|
|
589
|
+
* (paridade com `createReadFileTool`/`createSearchTextTool`, sandbox read-only do Codex).
|
|
590
|
+
*
|
|
591
|
+
* O guard de segredo por QUALQUER segmento continua valendo, e não é separável: `isForbiddenPath`
|
|
592
|
+
* só bloqueia o item sensível quando ele é o PRIMEIRO segmento, então um `/home/u/proj/.env/sub`
|
|
593
|
+
* passaria. Ligar o flag sem o guard é abrir exfiltração. Default `false` ⇒ absoluto rejeitado.
|
|
594
|
+
*/
|
|
595
|
+
allowAbsolute?: boolean;
|
|
531
596
|
/** Absolute path to the project root. Every listing is gated against this boundary. */
|
|
532
597
|
projectRoot: string;
|
|
533
598
|
/** Maximum number of entries returned per call. Default 500. */
|
|
@@ -605,17 +670,37 @@ declare function createPlanModeTool(options: PlanModeToolOptions): PlanModeToolW
|
|
|
605
670
|
* - `{ ok: false, error: "timeout" }`
|
|
606
671
|
*/
|
|
607
672
|
interface QuestionToolOptions {
|
|
608
|
-
/**
|
|
609
|
-
|
|
673
|
+
/**
|
|
674
|
+
* Callback que apresenta a pergunta ao usuário e resolve com a resposta.
|
|
675
|
+
*
|
|
676
|
+
* M76 — passou a ser OPCIONAL: o asker preferencial vem do contexto da run
|
|
677
|
+
* (`ctx.context.askUser`), porque um valor fixado aqui é o "baked into each factory" que a doc do
|
|
678
|
+
* `CustomTool.handler` aponta como o problema que `ctx.context` existe para resolver. Este campo
|
|
679
|
+
* permanece como fallback, para quem constrói a tool com um asker fixo (retrocompatível).
|
|
680
|
+
*/
|
|
681
|
+
askUser?: (question: string) => Promise<string>;
|
|
610
682
|
/** Maximum time to wait for user response in ms. Default: 300_000 (5 min). */
|
|
611
683
|
timeoutMs?: number;
|
|
612
684
|
}
|
|
685
|
+
/**
|
|
686
|
+
* M76 — alinhado ao `CustomTool` do SDK. Era uma interface própria com `inputSchema: unknown`, o que
|
|
687
|
+
* obrigava todo consumidor a escrever um cast para registrar a tool — e cast não conserta contrato,
|
|
688
|
+
* só silencia o compilador, transformando uma futura mudança de assinatura em erro de RUNTIME.
|
|
689
|
+
*
|
|
690
|
+
* Estreitar foi aditivo: o valor sempre foi um objeto (`{ type: "object", properties, required }`
|
|
691
|
+
* logo abaixo); só o tipo declarado estava frouxo. O handler aceita o 2º argumento opcional do
|
|
692
|
+
* contrato (`ctx`), por onde o M76 passa a resolver o asker por sessão.
|
|
693
|
+
*/
|
|
613
694
|
interface QuestionTool {
|
|
614
695
|
name: string;
|
|
615
696
|
description: string;
|
|
616
|
-
inputSchema: unknown
|
|
697
|
+
inputSchema: Record<string, unknown>;
|
|
617
698
|
handler: (input: {
|
|
618
699
|
question: string;
|
|
700
|
+
}, ctx?: {
|
|
701
|
+
signal?: AbortSignal;
|
|
702
|
+
context?: unknown;
|
|
703
|
+
threadId?: string;
|
|
619
704
|
}) => Promise<string>;
|
|
620
705
|
}
|
|
621
706
|
declare function createQuestionTool(opts: QuestionToolOptions): QuestionTool;
|
|
@@ -782,6 +867,17 @@ declare function createRunVitestTool(opts: CreateRunVitestToolOptions): CustomTo
|
|
|
782
867
|
*/
|
|
783
868
|
|
|
784
869
|
interface CreateSearchTextToolOptions {
|
|
870
|
+
/**
|
|
871
|
+
* M76 — nome exposto ao modelo. Omitido ⇒ o literal de hoje (aditivo).
|
|
872
|
+
*
|
|
873
|
+
* Existe porque, no Codex, o nome NASCE na definição da tool e é a chave de decisão de approval —
|
|
874
|
+
* três consumidores (modelo, approval, telemetry) de uma string decidida num lugar só. Renomear
|
|
875
|
+
* depois da construção é mudar a identidade de algo já publicado ao modelo. `withName` continua
|
|
876
|
+
* para o caso genuinamente dinâmico.
|
|
877
|
+
*/
|
|
878
|
+
name?: string;
|
|
879
|
+
/** M76 — descrição exposta ao modelo. Omitida ⇒ o literal de hoje (aditivo). */
|
|
880
|
+
description?: string;
|
|
785
881
|
projectRoot: string;
|
|
786
882
|
/** Cap on total matches returned. Default 100. */
|
|
787
883
|
maxMatches?: number;
|
|
@@ -811,6 +907,17 @@ declare function createSearchTextTool(opts: CreateSearchTextToolOptions): Custom
|
|
|
811
907
|
*/
|
|
812
908
|
|
|
813
909
|
interface CreateShellToolOptions {
|
|
910
|
+
/**
|
|
911
|
+
* M76 — nome exposto ao modelo. Omitido ⇒ o literal de hoje (aditivo).
|
|
912
|
+
*
|
|
913
|
+
* Existe porque, no Codex, o nome NASCE na definição da tool e é a chave de decisão de approval —
|
|
914
|
+
* três consumidores (modelo, approval, telemetry) de uma string decidida num lugar só. Renomear
|
|
915
|
+
* depois da construção é mudar a identidade de algo já publicado ao modelo. `withName` continua
|
|
916
|
+
* para o caso genuinamente dinâmico.
|
|
917
|
+
*/
|
|
918
|
+
name?: string;
|
|
919
|
+
/** M76 — descrição exposta ao modelo. Omitida ⇒ o literal de hoje (aditivo). */
|
|
920
|
+
description?: string;
|
|
814
921
|
/** Absolute path to the project root. Commands execute in this cwd. */
|
|
815
922
|
projectRoot: string;
|
|
816
923
|
/** Default timeout in ms. Capped at 300s. */
|
|
@@ -1117,4 +1224,4 @@ interface CreateWriteFileToolOptions {
|
|
|
1117
1224
|
}
|
|
1118
1225
|
declare function createWriteFileTool(opts: CreateWriteFileToolOptions): CustomTool;
|
|
1119
1226
|
|
|
1120
|
-
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 };
|
|
1227
|
+
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 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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -119,6 +119,17 @@ declare function createCurrentTimeTool(opts?: CreateCurrentTimeToolOptions): Cus
|
|
|
119
119
|
*/
|
|
120
120
|
|
|
121
121
|
interface CreateEditFileToolOptions {
|
|
122
|
+
/**
|
|
123
|
+
* M76 — nome exposto ao modelo. Omitido ⇒ o literal de hoje (aditivo).
|
|
124
|
+
*
|
|
125
|
+
* Existe porque, no Codex, o nome NASCE na definição da tool e é a chave de decisão de approval —
|
|
126
|
+
* três consumidores (modelo, approval, telemetry) de uma string decidida num lugar só. Renomear
|
|
127
|
+
* depois da construção é mudar a identidade de algo já publicado ao modelo. `withName` continua
|
|
128
|
+
* para o caso genuinamente dinâmico.
|
|
129
|
+
*/
|
|
130
|
+
name?: string;
|
|
131
|
+
/** M76 — descrição exposta ao modelo. Omitida ⇒ o literal de hoje (aditivo). */
|
|
132
|
+
description?: string;
|
|
122
133
|
/** Absolute path to the project root. Every edit is gated against this boundary. */
|
|
123
134
|
projectRoot: string;
|
|
124
135
|
/** Optional injected filesystem (`@theokit/sdk/filesystem`) — when provided, the read + `.bak` backup +
|
|
@@ -175,6 +186,40 @@ interface CreateGitDiffToolOptions {
|
|
|
175
186
|
}
|
|
176
187
|
declare function createGitDiffTool(opts: CreateGitDiffToolOptions): CustomTool;
|
|
177
188
|
|
|
189
|
+
/**
|
|
190
|
+
* `git_status` — built-in tool for coding agents.
|
|
191
|
+
*
|
|
192
|
+
* Returns the working-tree status in porcelain v1 format (`git status --porcelain`), which is the
|
|
193
|
+
* stable machine-readable form — the human format is explicitly not guaranteed across git versions.
|
|
194
|
+
*
|
|
195
|
+
* M76 — nasce ao lado de `git_diff` e compartilha o motor de execução (`internal/git-exec.ts`): teto
|
|
196
|
+
* de stdout, kill do grupo de processos no timeout e mapeamento para erro tipado são a MESMA regra
|
|
197
|
+
* para qualquer subcomando do git. O consumidor (agent-builder) tinha isto local em 62 LoC; nada ali
|
|
198
|
+
* era específico dele.
|
|
199
|
+
*
|
|
200
|
+
* Result shape (always a JSON string):
|
|
201
|
+
* - `{ ok: true, diff: string, truncated?: boolean }` — `diff` carrega a saída porcelain
|
|
202
|
+
* - `{ ok: false, error: 'not_a_repo' | 'path_traversal' | 'timeout' | 'git_failed' }`
|
|
203
|
+
*/
|
|
204
|
+
|
|
205
|
+
interface CreateGitStatusToolOptions {
|
|
206
|
+
/** Absolute path to the project root. Every invocation is gated against this boundary. */
|
|
207
|
+
projectRoot: string;
|
|
208
|
+
/** Wall-clock cap; the process group is killed on expiry. Default 30_000. */
|
|
209
|
+
timeoutMs?: number;
|
|
210
|
+
/** Cap on captured stdout; excess sets `truncated: true`. Default 5 MB. */
|
|
211
|
+
maxStdoutBytes?: number;
|
|
212
|
+
/**
|
|
213
|
+
* M76 — nome exposto ao modelo. Omitido ⇒ `"git_status"` (aditivo).
|
|
214
|
+
*
|
|
215
|
+
* O nome é contrato: chave de approval, o que o modelo vê e o que o telemetry registra.
|
|
216
|
+
*/
|
|
217
|
+
name?: string;
|
|
218
|
+
/** M76 — descrição exposta ao modelo. Omitida ⇒ o literal abaixo (aditivo). */
|
|
219
|
+
description?: string;
|
|
220
|
+
}
|
|
221
|
+
declare function createGitStatusTool(opts: CreateGitStatusToolOptions): CustomTool;
|
|
222
|
+
|
|
178
223
|
/**
|
|
179
224
|
* `glob_files` — built-in tool for coding agents.
|
|
180
225
|
*
|
|
@@ -528,6 +573,26 @@ declare function withShellExitGuidance(tool: CustomTool): CustomTool;
|
|
|
528
573
|
*/
|
|
529
574
|
|
|
530
575
|
interface CreateListDirToolOptions {
|
|
576
|
+
/**
|
|
577
|
+
* M76 — nome exposto ao modelo. Omitido ⇒ o literal de hoje (aditivo).
|
|
578
|
+
*
|
|
579
|
+
* Existe porque, no Codex, o nome NASCE na definição da tool e é a chave de decisão de approval —
|
|
580
|
+
* três consumidores (modelo, approval, telemetry) de uma string decidida num lugar só. Renomear
|
|
581
|
+
* depois da construção é mudar a identidade de algo já publicado ao modelo. `withName` continua
|
|
582
|
+
* para o caso genuinamente dinâmico.
|
|
583
|
+
*/
|
|
584
|
+
name?: string;
|
|
585
|
+
/** M76 — descrição exposta ao modelo. Omitida ⇒ o literal de hoje (aditivo). */
|
|
586
|
+
description?: string;
|
|
587
|
+
/**
|
|
588
|
+
* M76 — opt-in "lista-em-qualquer-lugar": honra um `path` ABSOLUTO fora de `projectRoot`
|
|
589
|
+
* (paridade com `createReadFileTool`/`createSearchTextTool`, sandbox read-only do Codex).
|
|
590
|
+
*
|
|
591
|
+
* O guard de segredo por QUALQUER segmento continua valendo, e não é separável: `isForbiddenPath`
|
|
592
|
+
* só bloqueia o item sensível quando ele é o PRIMEIRO segmento, então um `/home/u/proj/.env/sub`
|
|
593
|
+
* passaria. Ligar o flag sem o guard é abrir exfiltração. Default `false` ⇒ absoluto rejeitado.
|
|
594
|
+
*/
|
|
595
|
+
allowAbsolute?: boolean;
|
|
531
596
|
/** Absolute path to the project root. Every listing is gated against this boundary. */
|
|
532
597
|
projectRoot: string;
|
|
533
598
|
/** Maximum number of entries returned per call. Default 500. */
|
|
@@ -605,17 +670,37 @@ declare function createPlanModeTool(options: PlanModeToolOptions): PlanModeToolW
|
|
|
605
670
|
* - `{ ok: false, error: "timeout" }`
|
|
606
671
|
*/
|
|
607
672
|
interface QuestionToolOptions {
|
|
608
|
-
/**
|
|
609
|
-
|
|
673
|
+
/**
|
|
674
|
+
* Callback que apresenta a pergunta ao usuário e resolve com a resposta.
|
|
675
|
+
*
|
|
676
|
+
* M76 — passou a ser OPCIONAL: o asker preferencial vem do contexto da run
|
|
677
|
+
* (`ctx.context.askUser`), porque um valor fixado aqui é o "baked into each factory" que a doc do
|
|
678
|
+
* `CustomTool.handler` aponta como o problema que `ctx.context` existe para resolver. Este campo
|
|
679
|
+
* permanece como fallback, para quem constrói a tool com um asker fixo (retrocompatível).
|
|
680
|
+
*/
|
|
681
|
+
askUser?: (question: string) => Promise<string>;
|
|
610
682
|
/** Maximum time to wait for user response in ms. Default: 300_000 (5 min). */
|
|
611
683
|
timeoutMs?: number;
|
|
612
684
|
}
|
|
685
|
+
/**
|
|
686
|
+
* M76 — alinhado ao `CustomTool` do SDK. Era uma interface própria com `inputSchema: unknown`, o que
|
|
687
|
+
* obrigava todo consumidor a escrever um cast para registrar a tool — e cast não conserta contrato,
|
|
688
|
+
* só silencia o compilador, transformando uma futura mudança de assinatura em erro de RUNTIME.
|
|
689
|
+
*
|
|
690
|
+
* Estreitar foi aditivo: o valor sempre foi um objeto (`{ type: "object", properties, required }`
|
|
691
|
+
* logo abaixo); só o tipo declarado estava frouxo. O handler aceita o 2º argumento opcional do
|
|
692
|
+
* contrato (`ctx`), por onde o M76 passa a resolver o asker por sessão.
|
|
693
|
+
*/
|
|
613
694
|
interface QuestionTool {
|
|
614
695
|
name: string;
|
|
615
696
|
description: string;
|
|
616
|
-
inputSchema: unknown
|
|
697
|
+
inputSchema: Record<string, unknown>;
|
|
617
698
|
handler: (input: {
|
|
618
699
|
question: string;
|
|
700
|
+
}, ctx?: {
|
|
701
|
+
signal?: AbortSignal;
|
|
702
|
+
context?: unknown;
|
|
703
|
+
threadId?: string;
|
|
619
704
|
}) => Promise<string>;
|
|
620
705
|
}
|
|
621
706
|
declare function createQuestionTool(opts: QuestionToolOptions): QuestionTool;
|
|
@@ -782,6 +867,17 @@ declare function createRunVitestTool(opts: CreateRunVitestToolOptions): CustomTo
|
|
|
782
867
|
*/
|
|
783
868
|
|
|
784
869
|
interface CreateSearchTextToolOptions {
|
|
870
|
+
/**
|
|
871
|
+
* M76 — nome exposto ao modelo. Omitido ⇒ o literal de hoje (aditivo).
|
|
872
|
+
*
|
|
873
|
+
* Existe porque, no Codex, o nome NASCE na definição da tool e é a chave de decisão de approval —
|
|
874
|
+
* três consumidores (modelo, approval, telemetry) de uma string decidida num lugar só. Renomear
|
|
875
|
+
* depois da construção é mudar a identidade de algo já publicado ao modelo. `withName` continua
|
|
876
|
+
* para o caso genuinamente dinâmico.
|
|
877
|
+
*/
|
|
878
|
+
name?: string;
|
|
879
|
+
/** M76 — descrição exposta ao modelo. Omitida ⇒ o literal de hoje (aditivo). */
|
|
880
|
+
description?: string;
|
|
785
881
|
projectRoot: string;
|
|
786
882
|
/** Cap on total matches returned. Default 100. */
|
|
787
883
|
maxMatches?: number;
|
|
@@ -811,6 +907,17 @@ declare function createSearchTextTool(opts: CreateSearchTextToolOptions): Custom
|
|
|
811
907
|
*/
|
|
812
908
|
|
|
813
909
|
interface CreateShellToolOptions {
|
|
910
|
+
/**
|
|
911
|
+
* M76 — nome exposto ao modelo. Omitido ⇒ o literal de hoje (aditivo).
|
|
912
|
+
*
|
|
913
|
+
* Existe porque, no Codex, o nome NASCE na definição da tool e é a chave de decisão de approval —
|
|
914
|
+
* três consumidores (modelo, approval, telemetry) de uma string decidida num lugar só. Renomear
|
|
915
|
+
* depois da construção é mudar a identidade de algo já publicado ao modelo. `withName` continua
|
|
916
|
+
* para o caso genuinamente dinâmico.
|
|
917
|
+
*/
|
|
918
|
+
name?: string;
|
|
919
|
+
/** M76 — descrição exposta ao modelo. Omitida ⇒ o literal de hoje (aditivo). */
|
|
920
|
+
description?: string;
|
|
814
921
|
/** Absolute path to the project root. Commands execute in this cwd. */
|
|
815
922
|
projectRoot: string;
|
|
816
923
|
/** Default timeout in ms. Capped at 300s. */
|
|
@@ -1117,4 +1224,4 @@ interface CreateWriteFileToolOptions {
|
|
|
1117
1224
|
}
|
|
1118
1225
|
declare function createWriteFileTool(opts: CreateWriteFileToolOptions): CustomTool;
|
|
1119
1226
|
|
|
1120
|
-
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 };
|
|
1227
|
+
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 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 };
|
package/dist/index.js
CHANGED
|
@@ -5,9 +5,9 @@ import { z } from 'zod';
|
|
|
5
5
|
import { safePathJoin, assertNoSymlinkEscape, PathTraversalError, ForbiddenPathError, isForbiddenPath, safeFilenameForId } from '@theokit/sdk/path-safety';
|
|
6
6
|
import { replaceFileAtomic } from '@theokit/sdk/persistence';
|
|
7
7
|
import { resolveFilesystem, FileNotFoundError, FilesystemSecurityError, FilesystemReadOnlyError, StaleFileError, FilesystemError } from '@theokit/sdk/filesystem';
|
|
8
|
-
import { spawn } from 'child_process';
|
|
9
8
|
import { existsSync, statSync, mkdirSync, writeFileSync, readFileSync, readdirSync } from 'fs';
|
|
10
9
|
import { resolveSandbox } from '@theokit/sdk/sandbox';
|
|
10
|
+
import { spawn } from 'child_process';
|
|
11
11
|
import { resolveInteractive, InteractiveUnavailableError, NoSuchSessionError } from '@theokit/sdk/interactive';
|
|
12
12
|
import { lookup } from 'dns/promises';
|
|
13
13
|
import { isIP } from 'net';
|
|
@@ -609,8 +609,8 @@ function editScopeError(path, projectRoot) {
|
|
|
609
609
|
function createEditFileTool(opts) {
|
|
610
610
|
const { projectRoot, filesystem } = opts;
|
|
611
611
|
return Tool.create({
|
|
612
|
-
name: "edit_file",
|
|
613
|
-
description: "Make an exact string replacement in a project-relative file. Replaces the FIRST occurrence of old_string with new_string (a whitespace-normalized fallback is attempted if the exact match fails) and writes a .bak backup first. Read the file first so old_string matches the on-disk text exactly; include enough surrounding context to make it unique \u2014 only the first match is replaced, so a too-short old_string can edit the wrong location. old_string must be non-empty and differ from new_string; to change every occurrence, call edit_file repeatedly. Returns { ok, replacements } or { ok: false, error }.",
|
|
612
|
+
name: opts.name ?? "edit_file",
|
|
613
|
+
description: opts.description ?? "Make an exact string replacement in a project-relative file. Replaces the FIRST occurrence of old_string with new_string (a whitespace-normalized fallback is attempted if the exact match fails) and writes a .bak backup first. Read the file first so old_string matches the on-disk text exactly; include enough surrounding context to make it unique \u2014 only the first match is replaced, so a too-short old_string can edit the wrong location. old_string must be non-empty and differ from new_string; to change every occurrence, call edit_file repeatedly. Returns { ok, replacements } or { ok: false, error }.",
|
|
614
614
|
inputSchema: z.object({
|
|
615
615
|
path: z.string().min(1).describe("Project-relative file path."),
|
|
616
616
|
old_string: z.string().min(1).describe("String to find in the file."),
|
|
@@ -682,21 +682,6 @@ function formatError(message, code) {
|
|
|
682
682
|
return `> **Error:** ${prefix}${message}`;
|
|
683
683
|
}
|
|
684
684
|
|
|
685
|
-
// src/path-scope.ts
|
|
686
|
-
function checkPathScope(path, projectRoot) {
|
|
687
|
-
if (path === void 0 || path === "") return null;
|
|
688
|
-
try {
|
|
689
|
-
const abs = safePathJoin(projectRoot, path);
|
|
690
|
-
assertNoSymlinkEscape(abs, projectRoot);
|
|
691
|
-
return null;
|
|
692
|
-
} catch (err) {
|
|
693
|
-
if (err instanceof PathTraversalError || err instanceof ForbiddenPathError) {
|
|
694
|
-
return JSON.stringify({ ok: false, error: "path_traversal", path });
|
|
695
|
-
}
|
|
696
|
-
throw err;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
|
|
700
685
|
// src/subprocess.ts
|
|
701
686
|
function createSettleGate(timer) {
|
|
702
687
|
let done = false;
|
|
@@ -732,6 +717,85 @@ function attachChildSettlers(child, gate, onClose, onError, resolve) {
|
|
|
732
717
|
});
|
|
733
718
|
}
|
|
734
719
|
|
|
720
|
+
// src/internal/git-exec.ts
|
|
721
|
+
function formatGitResult(result, timeoutMs) {
|
|
722
|
+
if (result.kind === "timeout") {
|
|
723
|
+
return JSON.stringify({ ok: false, error: "timeout", timeoutMs });
|
|
724
|
+
}
|
|
725
|
+
if (result.kind === "error") {
|
|
726
|
+
return JSON.stringify({ ok: false, error: "git_failed", stderr: result.stderr });
|
|
727
|
+
}
|
|
728
|
+
return JSON.stringify({ ok: true, diff: result.stdout, truncated: result.truncated });
|
|
729
|
+
}
|
|
730
|
+
function runGitProcess(cwd, args, timeoutMs, maxStdoutBytes) {
|
|
731
|
+
return new Promise((resolve) => {
|
|
732
|
+
const child = spawn("git", args, { cwd, detached: true, stdio: ["ignore", "pipe", "pipe"] });
|
|
733
|
+
const stdoutChunks = [];
|
|
734
|
+
const stderrChunks = [];
|
|
735
|
+
let stdoutBytes = 0;
|
|
736
|
+
let truncated = false;
|
|
737
|
+
const gate = armTimeoutKill(
|
|
738
|
+
child,
|
|
739
|
+
timeoutMs,
|
|
740
|
+
() => ({ kind: "timeout" }),
|
|
741
|
+
resolve
|
|
742
|
+
);
|
|
743
|
+
child.stdout.on("data", (chunk) => {
|
|
744
|
+
if (gate.settled()) return;
|
|
745
|
+
if (stdoutBytes >= maxStdoutBytes) {
|
|
746
|
+
truncated = true;
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
const remaining = maxStdoutBytes - stdoutBytes;
|
|
750
|
+
if (chunk.length > remaining) {
|
|
751
|
+
stdoutChunks.push(chunk.subarray(0, remaining));
|
|
752
|
+
stdoutBytes = maxStdoutBytes;
|
|
753
|
+
truncated = true;
|
|
754
|
+
} else {
|
|
755
|
+
stdoutChunks.push(chunk);
|
|
756
|
+
stdoutBytes += chunk.length;
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
child.stderr.on("data", (chunk) => {
|
|
760
|
+
stderrChunks.push(chunk);
|
|
761
|
+
});
|
|
762
|
+
attachChildSettlers(
|
|
763
|
+
child,
|
|
764
|
+
gate,
|
|
765
|
+
(code) => {
|
|
766
|
+
const stdout = Buffer.concat(stdoutChunks).toString("utf-8");
|
|
767
|
+
const stderr = Buffer.concat(stderrChunks).toString("utf-8");
|
|
768
|
+
return code === 0 ? { kind: "ok", stdout, truncated } : { kind: "error", stderr };
|
|
769
|
+
},
|
|
770
|
+
(err) => ({ kind: "error", stderr: err.message }),
|
|
771
|
+
resolve
|
|
772
|
+
);
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// src/path-scope.ts
|
|
777
|
+
function checkPathScope(path, projectRoot) {
|
|
778
|
+
if (path === void 0 || path === "") return null;
|
|
779
|
+
try {
|
|
780
|
+
const abs = safePathJoin(projectRoot, path);
|
|
781
|
+
assertNoSymlinkEscape(abs, projectRoot);
|
|
782
|
+
return null;
|
|
783
|
+
} catch (err) {
|
|
784
|
+
if (err instanceof PathTraversalError || err instanceof ForbiddenPathError) {
|
|
785
|
+
return JSON.stringify({ ok: false, error: "path_traversal", path });
|
|
786
|
+
}
|
|
787
|
+
throw err;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
var SEGMENTOS_SENSIVEIS = /* @__PURE__ */ new Set([".env", ".git", "node_modules", ".theo"]);
|
|
791
|
+
function ehProibidoEmQualquerProfundidade(path) {
|
|
792
|
+
const segs = path.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
793
|
+
return segs.some((s) => {
|
|
794
|
+
if (s === ".env.example") return false;
|
|
795
|
+
return SEGMENTOS_SENSIVEIS.has(s) || /^\.env\./.test(s);
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
|
|
735
799
|
// src/git-diff.ts
|
|
736
800
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
737
801
|
var DEFAULT_MAX_STDOUT_BYTES = 5 * 1024 * 1024;
|
|
@@ -785,58 +849,25 @@ function buildDiffArgs(cached, path) {
|
|
|
785
849
|
if (path !== void 0 && path !== "") args.push("--", path);
|
|
786
850
|
return args;
|
|
787
851
|
}
|
|
788
|
-
function
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
const child = spawn("git", args, { cwd, detached: true, stdio: ["ignore", "pipe", "pipe"] });
|
|
800
|
-
const stdoutChunks = [];
|
|
801
|
-
const stderrChunks = [];
|
|
802
|
-
let stdoutBytes = 0;
|
|
803
|
-
let truncated = false;
|
|
804
|
-
const gate = armTimeoutKill(
|
|
805
|
-
child,
|
|
806
|
-
timeoutMs,
|
|
807
|
-
() => ({ kind: "timeout" }),
|
|
808
|
-
resolve
|
|
809
|
-
);
|
|
810
|
-
child.stdout.on("data", (chunk) => {
|
|
811
|
-
if (gate.settled()) return;
|
|
812
|
-
if (stdoutBytes >= maxStdoutBytes) {
|
|
813
|
-
truncated = true;
|
|
814
|
-
return;
|
|
815
|
-
}
|
|
816
|
-
const remaining = maxStdoutBytes - stdoutBytes;
|
|
817
|
-
if (chunk.length > remaining) {
|
|
818
|
-
stdoutChunks.push(chunk.subarray(0, remaining));
|
|
819
|
-
stdoutBytes = maxStdoutBytes;
|
|
820
|
-
truncated = true;
|
|
821
|
-
} else {
|
|
822
|
-
stdoutChunks.push(chunk);
|
|
823
|
-
stdoutBytes += chunk.length;
|
|
852
|
+
function createGitStatusTool(opts) {
|
|
853
|
+
const { projectRoot, timeoutMs = 3e4, maxStdoutBytes = 5 * 1024 * 1024 } = opts;
|
|
854
|
+
return Tool.create({
|
|
855
|
+
name: opts.name ?? "git_status",
|
|
856
|
+
description: opts.description ?? "Show the working-tree status in porcelain format: staged, unstaged and untracked paths, one per line with a two-character status code. Use before committing, or to see what changed without reading the full diff. Optional 'path' scopes the report to a subdirectory.",
|
|
857
|
+
inputSchema: z.object({
|
|
858
|
+
path: z.string().optional().describe("Optional project-relative path to scope the status report.")
|
|
859
|
+
}),
|
|
860
|
+
handler: async ({ path }) => {
|
|
861
|
+
if (!existsSync(join(projectRoot, ".git"))) {
|
|
862
|
+
return JSON.stringify({ ok: false, error: "not_a_repo" });
|
|
824
863
|
}
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
(code) => {
|
|
833
|
-
const stdout = Buffer.concat(stdoutChunks).toString("utf-8");
|
|
834
|
-
const stderr = Buffer.concat(stderrChunks).toString("utf-8");
|
|
835
|
-
return code === 0 ? { kind: "ok", stdout, truncated } : { kind: "error", stderr };
|
|
836
|
-
},
|
|
837
|
-
(err) => ({ kind: "error", stderr: err.message }),
|
|
838
|
-
resolve
|
|
839
|
-
);
|
|
864
|
+
const scopeCheck = checkPathScope(path, projectRoot);
|
|
865
|
+
if (scopeCheck !== null) return scopeCheck;
|
|
866
|
+
const args = ["status", "--porcelain"];
|
|
867
|
+
if (path !== void 0 && path !== "") args.push("--", path);
|
|
868
|
+
const result = await runGitProcess(projectRoot, args, timeoutMs, maxStdoutBytes);
|
|
869
|
+
return formatGitResult(result, timeoutMs);
|
|
870
|
+
}
|
|
840
871
|
});
|
|
841
872
|
}
|
|
842
873
|
var DEFAULT_EXCLUDES = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", ".theo"]);
|
|
@@ -1508,15 +1539,17 @@ var DEFAULT_MAX_ENTRIES = 500;
|
|
|
1508
1539
|
function createListDirTool(opts) {
|
|
1509
1540
|
const { projectRoot, max = DEFAULT_MAX_ENTRIES, filesystem } = opts;
|
|
1510
1541
|
return Tool.create({
|
|
1511
|
-
name: "list_dir",
|
|
1512
|
-
description: `Return the direct entries of a project-relative directory. Refuses paths outside the project root or in the sensitive-file blocklist (.env, .git/, node_modules/, .theo/, lock files). Caps at ${String(max)} entries by default; result carries truncated + totalCount.`,
|
|
1542
|
+
name: opts.name ?? "list_dir",
|
|
1543
|
+
description: opts.description ?? `Return the direct entries of a project-relative directory. Refuses paths outside the project root or in the sensitive-file blocklist (.env, .git/, node_modules/, .theo/, lock files). Caps at ${String(max)} entries by default; result carries truncated + totalCount.`,
|
|
1513
1544
|
inputSchema: z.object({
|
|
1514
1545
|
path: z.string().min(1).describe("Project-relative directory path. Use '.' for root.")
|
|
1515
1546
|
}),
|
|
1516
1547
|
handler: async ({ path }, ctx) => {
|
|
1517
1548
|
const relative3 = path === "" || path === "." ? "." : path;
|
|
1518
|
-
|
|
1519
|
-
|
|
1549
|
+
const veredito = decidirEscopo(relative3, path, opts.allowAbsolute === true);
|
|
1550
|
+
if (veredito.erro !== void 0) return veredito.erro;
|
|
1551
|
+
if (veredito.raizAbsoluta !== void 0) {
|
|
1552
|
+
return listViaLocalFs(veredito.raizAbsoluta, ".", path, max);
|
|
1520
1553
|
}
|
|
1521
1554
|
if (filesystem) {
|
|
1522
1555
|
const backend = await resolveFilesystem(filesystem, ctx ?? {});
|
|
@@ -1526,6 +1559,16 @@ function createListDirTool(opts) {
|
|
|
1526
1559
|
}
|
|
1527
1560
|
});
|
|
1528
1561
|
}
|
|
1562
|
+
function decidirEscopo(relative3, original, allowAbsolute) {
|
|
1563
|
+
const recusa = (error) => ({
|
|
1564
|
+
erro: JSON.stringify({ ok: false, error, path: original })
|
|
1565
|
+
});
|
|
1566
|
+
if (relative3 !== "." && isForbiddenPath(relative3)) return recusa("forbidden_path");
|
|
1567
|
+
if (!isAbsolute(relative3)) return {};
|
|
1568
|
+
if (!allowAbsolute) return recusa("path_traversal");
|
|
1569
|
+
if (ehProibidoEmQualquerProfundidade(relative3)) return recusa("forbidden_path");
|
|
1570
|
+
return { raizAbsoluta: relative3 };
|
|
1571
|
+
}
|
|
1529
1572
|
async function listViaLocalFs(projectRoot, relative3, originalPath, max) {
|
|
1530
1573
|
const boundary = resolveDirBoundary(relative3, projectRoot, originalPath);
|
|
1531
1574
|
if ("error" in boundary) return boundary.error;
|
|
@@ -1686,6 +1729,11 @@ function createPlanModeTool(options) {
|
|
|
1686
1729
|
}
|
|
1687
1730
|
|
|
1688
1731
|
// src/question.ts
|
|
1732
|
+
function askerDoContexto(context) {
|
|
1733
|
+
if (typeof context !== "object" || context === null) return void 0;
|
|
1734
|
+
const candidato = context.askUser;
|
|
1735
|
+
return typeof candidato === "function" ? candidato : void 0;
|
|
1736
|
+
}
|
|
1689
1737
|
function createQuestionTool(opts) {
|
|
1690
1738
|
const timeoutMs = opts.timeoutMs ?? 3e5;
|
|
1691
1739
|
return {
|
|
@@ -1698,12 +1746,20 @@ function createQuestionTool(opts) {
|
|
|
1698
1746
|
},
|
|
1699
1747
|
required: ["question"]
|
|
1700
1748
|
},
|
|
1701
|
-
handler: async (input) => {
|
|
1749
|
+
handler: async (input, ctx) => {
|
|
1750
|
+
const askUser = askerDoContexto(ctx?.context) ?? opts.askUser;
|
|
1751
|
+
if (askUser === void 0) {
|
|
1752
|
+
return JSON.stringify({
|
|
1753
|
+
ok: false,
|
|
1754
|
+
error: "no_asker",
|
|
1755
|
+
message: "No asker available: pass `askUser` to createQuestionTool, or provide `context.askUser` via SendOptions.context."
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
1702
1758
|
const timeout = new Promise((_, reject) => {
|
|
1703
1759
|
setTimeout(() => reject(new Error("timeout")), timeoutMs);
|
|
1704
1760
|
});
|
|
1705
1761
|
try {
|
|
1706
|
-
const answer = await Promise.race([
|
|
1762
|
+
const answer = await Promise.race([askUser(input.question), timeout]);
|
|
1707
1763
|
return JSON.stringify({ ok: true, answer });
|
|
1708
1764
|
} catch (err) {
|
|
1709
1765
|
if (err instanceof Error && err.message === "timeout") {
|
|
@@ -2041,8 +2097,8 @@ function createSearchTextTool(opts) {
|
|
|
2041
2097
|
const queryKind = regex ? "a JavaScript REGULAR EXPRESSION" : "LITERAL, CASE-SENSITIVE text";
|
|
2042
2098
|
const queryMatch = regex ? "matched as a regex" : "matched as a substring, not a regex";
|
|
2043
2099
|
return Tool.create({
|
|
2044
|
-
name: "search_text",
|
|
2045
|
-
description: `Search file CONTENTS for ${queryKind} across the project tree (the query is ${queryMatch}). Use search_text when you know the content; use glob_files when you know the filename shape; use read_file when you know the exact path. Skips sensitive dirs (.env/.git/node_modules/.theo), binary files, and files over 1 MB; 'path' scopes the search to a subdirectory. Returns up to ${String(maxMatches)} matches as { file, line, preview } \u2014 cite locations to the user as file:line. Returns { ok, matches } or { ok: false, error }.`,
|
|
2100
|
+
name: opts.name ?? "search_text",
|
|
2101
|
+
description: opts.description ?? `Search file CONTENTS for ${queryKind} across the project tree (the query is ${queryMatch}). Use search_text when you know the content; use glob_files when you know the filename shape; use read_file when you know the exact path. Skips sensitive dirs (.env/.git/node_modules/.theo), binary files, and files over 1 MB; 'path' scopes the search to a subdirectory. Returns up to ${String(maxMatches)} matches as { file, line, preview } \u2014 cite locations to the user as file:line. Returns { ok, matches } or { ok: false, error }.`,
|
|
2046
2102
|
inputSchema: z.object({
|
|
2047
2103
|
query: regex ? z.string().min(1).describe("A JavaScript regular expression, e.g. 'function\\\\s+main'.") : z.string().min(1).describe("Literal text to search for. Case-sensitive."),
|
|
2048
2104
|
path: z.string().optional().describe(
|
|
@@ -2250,8 +2306,8 @@ function createShellTool(opts) {
|
|
|
2250
2306
|
sandbox
|
|
2251
2307
|
} = opts;
|
|
2252
2308
|
return Tool.create({
|
|
2253
|
-
name: "shell_exec",
|
|
2254
|
-
description: "Execute a shell command in the project directory. Use this for terminal operations \u2014 running tests, git, package managers, build tools. Do NOT use it for file operations (reading, writing, editing, finding files): prefer the specialized read_file/write_file/edit_file/glob_files/search_text tools, which are path-checked and safer. Only commit, push, or change git state when the user explicitly asks. timeout_ms defaults to 30000 (max 300000); stdout/stderr are capped (~5 MB). Returns { ok, stdout, stderr, exit_code } or { ok: false, error }.",
|
|
2309
|
+
name: opts.name ?? "shell_exec",
|
|
2310
|
+
description: opts.description ?? "Execute a shell command in the project directory. Use this for terminal operations \u2014 running tests, git, package managers, build tools. Do NOT use it for file operations (reading, writing, editing, finding files): prefer the specialized read_file/write_file/edit_file/glob_files/search_text tools, which are path-checked and safer. Only commit, push, or change git state when the user explicitly asks. timeout_ms defaults to 30000 (max 300000); stdout/stderr are capped (~5 MB). Returns { ok, stdout, stderr, exit_code } or { ok: false, error }.",
|
|
2255
2311
|
inputSchema: z.object({
|
|
2256
2312
|
command: z.string().min(1).describe("Shell command to execute."),
|
|
2257
2313
|
timeout_ms: z.number().int().positive().optional().describe("Timeout in milliseconds (default 30000, max 300000).")
|
|
@@ -2817,6 +2873,6 @@ async function isBinaryFile(absolutePath) {
|
|
|
2817
2873
|
}
|
|
2818
2874
|
}
|
|
2819
2875
|
|
|
2820
|
-
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 };
|
|
2876
|
+
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 };
|
|
2821
2877
|
//# sourceMappingURL=index.js.map
|
|
2822
2878
|
//# sourceMappingURL=index.js.map
|