Skip to content

Commit 696a473

Browse files
hiskudinclaude
andcommitted
feat: add defender config option to StackOneToolSet
Adds a `defender` option to the `StackOneToolSet` constructor that allows controlling prompt injection detection behavior at the toolset level. - Add `DefenderConfig` interface with `enabled`, `blockHighRisk`, `useTier1Classification`, and `useTier2Classification` fields — matching canonical `DefenderSettings` names from `@stackone/core` - Add `defender_enabled` to `rpcActionRequestSchema` so it is no longer silently dropped by Zod validation - Forward `defender_enabled` through `RpcClient.rpcAction()` request body - Thread `defenderConfig.enabled` → `defender_enabled` in every RPC call made by `createRpcBackedTool` - Export `DefenderConfig` from the package index Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 8c1aca8 commit 696a473

5 files changed

Lines changed: 50 additions & 1 deletion

File tree

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export {
3232
export type {
3333
AISDKToolDefinition,
3434
AISDKToolResult,
35+
DefenderConfig,
3536
ExecuteConfig,
3637
ExecuteOptions,
3738
JsonObject,

src/rpc-client.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,13 @@ export class RpcClient {
5050
const requestBody = {
5151
action: validatedRequest.action,
5252
body: validatedRequest.body,
53+
...(validatedRequest.defender_enabled !== undefined
54+
? { defender_enabled: validatedRequest.defender_enabled }
55+
: {}),
5356
headers: validatedRequest.headers,
5457
path: validatedRequest.path,
5558
query: validatedRequest.query,
56-
} as const satisfies RpcActionRequest;
59+
} satisfies RpcActionRequest;
5760

5861
// Forward StackOne-specific headers as HTTP headers
5962
const requestHeaders = validatedRequest.headers;

src/schema.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { stackOneHeadersSchema } from './headers';
88
export const rpcActionRequestSchema = z.object({
99
action: z.string(),
1010
body: z.optional(z.record(z.string(), z.unknown())),
11+
defender_enabled: z.optional(z.boolean()),
1112
headers: z.optional(stackOneHeadersSchema),
1213
path: z.optional(z.record(z.string(), z.unknown())),
1314
query: z.optional(z.record(z.string(), z.unknown())),

src/toolsets.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
} from './semantic-search';
1414
import { BaseTool, Tools } from './tool';
1515
import type {
16+
DefenderConfig,
1617
ExecuteOptions,
1718
JsonObject,
1819
JsonSchemaProperties,
@@ -141,6 +142,13 @@ interface StackOneToolSetBaseConfig extends BaseToolSetConfig {
141142
* Per-call options always override these defaults.
142143
*/
143144
search?: SearchConfig | null;
145+
/**
146+
* Defender configuration. Controls prompt injection detection behavior.
147+
* Overrides the project-level defender settings for all tool calls made by this toolset.
148+
*
149+
* - Omit or pass `undefined` → uses the project defender settings
150+
*/
151+
defender?: DefenderConfig;
144152
}
145153

146154
/**
@@ -261,6 +269,7 @@ export class StackOneToolSet {
261269
private headers: Record<string, string>;
262270
private rpcClient?: RpcClient;
263271
private readonly searchConfig: SearchConfig | null;
272+
private readonly defenderConfig?: DefenderConfig;
264273

265274
/**
266275
* Account ID for StackOne API
@@ -320,6 +329,8 @@ export class StackOneToolSet {
320329
// Resolve search config: undefined → defaults, null → disabled, object → custom
321330
this.searchConfig = config?.search === null ? null : { method: 'auto', ...config?.search };
322331

332+
this.defenderConfig = config?.defender;
333+
323334
// Set Authentication headers if provided
324335
if (this.authentication) {
325336
// Only set auth headers if they don't already exist in custom headers
@@ -965,6 +976,9 @@ export class StackOneToolSet {
965976
const response = await actionsClient.actions.rpcAction({
966977
action: name,
967978
body: rpcBody,
979+
...(this.defenderConfig?.enabled !== undefined
980+
? { defender_enabled: this.defenderConfig.enabled }
981+
: {}),
968982
headers: actionHeaders,
969983
path: pathParams ?? undefined,
970984
query: queryParams ?? undefined,

src/types.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,33 @@ export interface ClaudeAgentSdkOptions {
234234
*/
235235
serverVersion?: string;
236236
}
237+
238+
/**
239+
* Defender configuration for controlling prompt injection detection behavior.
240+
* Field names match the canonical `DefenderSettings` from `@stackone/core`.
241+
*
242+
* Note: only `enabled` is applied per-request via the `defender_enabled` API field.
243+
* The remaining fields are included for forward compatibility and documentation.
244+
*/
245+
export interface DefenderConfig {
246+
/**
247+
* Whether to enable defender. Maps to `defender_enabled` in the RPC request.
248+
* Defaults to the project setting.
249+
*/
250+
enabled?: boolean;
251+
/**
252+
* Whether to block tool execution when a HIGH risk score is detected.
253+
* Defaults to the project setting.
254+
*/
255+
blockHighRisk?: boolean;
256+
/**
257+
* Whether to enable tier 1 pattern-based (regex) detection.
258+
* Defaults to the project setting.
259+
*/
260+
useTier1Classification?: boolean;
261+
/**
262+
* Whether to enable tier 2 ML-based detection.
263+
* Defaults to the project setting.
264+
*/
265+
useTier2Classification?: boolean;
266+
}

0 commit comments

Comments
 (0)