Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions assistant/src/tools/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,15 +330,27 @@ export interface ToolDefinition {
input_schema?: object;
/** Where the tool runs — sandbox (assistant container) or host (guardian device via proxy). Resolved by `resolveExecutionTarget` if omitted. */
executionTarget?: ExecutionTarget;
/** When set to 'proxy', the tool is forwarded to a connected client rather than executed locally. Genuinely optional — omit (or set to 'local') for in-process tools. */
executionMode?: "local" | "proxy";
Comment on lines +333 to +334
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don't expose proxy mode for plugin tool definitions

When this ToolDefinition is consumed through @vellumai/plugin-api, external plugin tools loaded in external-plugin-loader.ts now type-check with executionMode: "proxy", but the conversation tool list still only includes non-proxy registry tools plus the hard-coded UI/app proxy tools (getAllToolDefinitions() filters t.executionMode !== "proxy", and buildToolDefinitions() only re-adds allUiSurfaceTools/coreAppProxyTools). A plugin author following this new public type would have their tool registered and then silently omitted from the model-visible tool catalog, with no plugin projection path to add it back.

Useful? React with 👍 / 👎.

/** Implementation invoked when the model calls the tool. */
execute?: (
input: Record<string, unknown>,
context: ToolContext,
) => Promise<ToolExecutionResult>;
}

/** Tool after the loader has derived its name and filled defaults. */
export type LoadedTool = Required<ToolDefinition> & { name: string };
/**
* Tool after the loader has derived its name and filled defaults.
*
* `executionMode` is deliberately kept optional on the loaded shape — it
* carries dispatch intent ("forward to client" vs "execute locally") and
* staying `undefined` is the canonical "local" state. All other declared
* fields are required post-finalize.
*/
export type LoadedTool = Required<Omit<ToolDefinition, "executionMode">> & {
name: string;
executionMode?: "local" | "proxy";
};

/** The kind of extension that owns a tool. Core tools have no owner. */
export type OwnerKind = "skill" | "mcp" | "plugin";
Expand All @@ -356,6 +368,4 @@ export interface OwnerInfo {

export interface Tool extends LoadedTool {
category: string;
/** When set to 'proxy', the tool is forwarded to a connected client rather than executed locally. */
executionMode?: "local" | "proxy";
}
Loading