chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:44:08 +08:00
commit 983960e2dd
1244 changed files with 281996 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
from .src.python.cerebras_tool import CerebrasTool
__all__ = ["CerebrasTool"]
@@ -0,0 +1,4 @@
{
"CEREBRAS_API_KEY": null,
"CEREBRAS_MODEL": "zai-glm-4.7"
}
@@ -0,0 +1,352 @@
import { Tool } from '@sdk/base-tool'
import { ToolkitConfig } from '@sdk/toolkit-config'
import { Network, NetworkError } from '@sdk/network'
// Hardcoded default settings for Cerebras tool
const CEREBRAS_API_KEY: string | null = null
const CEREBRAS_MODEL = 'zai-glm-4.7'
const DEFAULT_SETTINGS: Record<string, unknown> = {
CEREBRAS_API_KEY,
CEREBRAS_MODEL
}
const REQUIRED_SETTINGS = ['CEREBRAS_API_KEY']
interface ChatMessage {
role: string
content: string
}
interface ChatCompletionOptions {
messages: ChatMessage[]
model?: string
temperature?: number
max_tokens?: number
system_prompt?: string
use_structured_output?: boolean
// eslint-disable-next-line @typescript-eslint/no-explicit-any
json_schema?: Record<string, any>
}
interface CompletionOptions {
prompt: string
model?: string
temperature?: number
max_tokens?: number
system_prompt?: string
use_structured_output?: boolean
// eslint-disable-next-line @typescript-eslint/no-explicit-any
json_schema?: Record<string, any>
}
interface StructuredCompletionOptions {
prompt: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
json_schema: Record<string, any>
model?: string
temperature?: number
max_tokens?: number
system_prompt?: string
}
interface ApiResponse {
success: boolean
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data?: any
model_used?: string
error?: string
status_code?: number
}
export default class CerebrasTool extends Tool {
private static readonly TOOLKIT = 'communication'
private readonly config: ReturnType<typeof ToolkitConfig.load>
private api_key: string | null
private model: string
private readonly network: Network
// Popular Cerebras-hosted models (override with full model IDs if needed)
private readonly popular_models = {
'zai-glm-4.7': 'zai-glm-4.7',
'qwen-3-235b-a22b-instruct-2507': 'qwen-3-235b-a22b-instruct-2507',
'qwen-3-32b': 'qwen-3-32b'
}
constructor(apiKey?: string) {
super()
// Load configuration from central toolkits directory
this.config = ToolkitConfig.load(CerebrasTool.TOOLKIT, this.toolName)
const toolSettings = ToolkitConfig.loadToolSettings(
CerebrasTool.TOOLKIT,
this.toolName,
DEFAULT_SETTINGS
)
this.settings = toolSettings
this.requiredSettings = REQUIRED_SETTINGS
this.checkRequiredSettings(this.toolName)
// Priority: skill-provided apiKey > toolkit settings > hardcoded default
this.api_key =
apiKey ||
(this.settings['CEREBRAS_API_KEY'] as string) ||
CEREBRAS_API_KEY
// Load model from toolkit settings or hardcoded default
this.model = (this.settings['CEREBRAS_MODEL'] as string) || CEREBRAS_MODEL
this.network = new Network({ baseURL: 'https://api.cerebras.ai/v1' })
}
get toolName(): string {
return 'cerebras'
}
get toolkit(): string {
return CerebrasTool.TOOLKIT
}
get description(): string {
return this.config['description']
}
/**
* Set the Cerebras API key
*/
setApiKey(apiKey: string): void {
this.api_key = apiKey
}
/**
* Get list of popular available models
*/
getAvailableModels(): string[] {
return Object.keys(this.popular_models)
}
/**
* Convert friendly model name to Cerebras model ID
*/
getModelId(modelName: string): string {
return (
this.popular_models[modelName as keyof typeof this.popular_models] ||
modelName
)
}
/**
* Send a chat completion request to Cerebras
*/
async chatCompletion(options: ChatCompletionOptions): Promise<ApiResponse> {
const {
messages,
model,
temperature = 0.7,
max_tokens,
system_prompt,
use_structured_output = false,
json_schema
} = options
if (!this.api_key) {
return {
success: false,
error: 'Cerebras API key not configured'
}
}
// Use default model if none provided
const finalModel = model || this.model
const modelId = this.getModelId(finalModel)
const requestMessages = []
if (system_prompt) {
requestMessages.push({ role: 'system', content: system_prompt })
}
requestMessages.push(...messages)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const payload: any = {
model: modelId,
messages: requestMessages,
temperature
}
if (max_tokens) {
payload.max_tokens = max_tokens
}
if (use_structured_output) {
payload.response_format = { type: 'json_object' }
if (json_schema) {
const schemaText = JSON.stringify(json_schema)
const schemaPrompt = `You must return a valid JSON object that matches this schema:\n${schemaText}`
payload.messages = [
{ role: 'system', content: schemaPrompt },
...requestMessages
]
}
}
try {
const response = await this.network.request({
url: '/chat/completions',
method: 'POST',
headers: {
Authorization: `Bearer ${this.api_key}`,
'Content-Type': 'application/json'
},
data: payload
})
return {
success: true,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: response.data as any,
model_used: modelId
}
} catch (error: unknown) {
return {
success: false,
error: `Cerebras API error: ${(error as Error).message}`,
status_code:
error instanceof NetworkError ? error.response.statusCode : undefined
}
}
}
/**
* General text completion for any use case
*/
async completion(options: CompletionOptions): Promise<ApiResponse> {
const {
prompt,
model,
temperature = 0.7,
max_tokens,
system_prompt,
use_structured_output = false,
json_schema
} = options
const messages = [{ role: 'user', content: prompt }]
const response = await this.chatCompletion({
messages,
model: model || this.model,
temperature,
max_tokens,
system_prompt,
use_structured_output,
json_schema
})
if (!response.success) {
return response
}
try {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const content = (response.data as any).choices[0].message.content
return {
success: true,
data: { content },
model_used: response.model_used
}
} catch (error: unknown) {
return {
success: false,
error: `Failed to extract completion: ${(error as Error).message}`
}
}
}
/**
* Generate structured JSON output using Cerebras structured outputs
*/
async structuredCompletion(
options: StructuredCompletionOptions
): Promise<ApiResponse> {
const {
prompt,
json_schema,
model,
temperature = 0.7,
max_tokens,
system_prompt
} = options
const messages = [{ role: 'user', content: prompt }]
const response = await this.chatCompletion({
messages,
model: model || this.model,
temperature,
max_tokens,
system_prompt,
use_structured_output: true,
json_schema
})
if (!response.success) {
return response
}
try {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const content = (response.data as any).choices[0].message.content
const parsedData = JSON.parse(content)
return {
success: true,
data: parsedData,
model_used: response.model_used
}
} catch (error: unknown) {
if (error instanceof SyntaxError) {
return {
success: false,
error: `Failed to parse JSON response: ${error.message}`
}
}
return {
success: false,
error: `Failed to extract completion: ${(error as Error).message}`
}
}
}
/**
* Get list of available models from Cerebras API
*/
async listModels(): Promise<ApiResponse> {
if (!this.api_key) {
return {
success: false,
error: 'Cerebras API key not configured'
}
}
try {
const response = await this.network.request({
url: '/models',
method: 'GET',
headers: {
Authorization: `Bearer ${this.api_key}`
}
})
return {
success: true,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: { models: (response.data as any).data }
}
} catch (error: unknown) {
return {
success: false,
error: `Failed to fetch models: ${(error as Error).message}`
}
}
}
}
@@ -0,0 +1 @@
export { default } from './cerebras-tool'
@@ -0,0 +1,290 @@
import json
from typing import Dict, Any, Optional, List
from bridges.python.src.sdk.base_tool import BaseTool
from bridges.python.src.sdk.toolkit_config import ToolkitConfig
from bridges.python.src.sdk.network import Network, NetworkError
# Hardcoded default settings for Cerebras tool
CEREBRAS_API_KEY = None
CEREBRAS_MODEL = "zai-glm-4.7"
DEFAULT_SETTINGS = {
"CEREBRAS_API_KEY": CEREBRAS_API_KEY,
"CEREBRAS_MODEL": CEREBRAS_MODEL,
}
REQUIRED_SETTINGS = ["CEREBRAS_API_KEY"]
class CerebrasTool(BaseTool):
"""Cerebras tool for LLM API access (e.g., GLM 4.7)"""
TOOLKIT = "communication"
def __init__(self, api_key: Optional[str] = None):
super().__init__()
self.config = ToolkitConfig.load(self.TOOLKIT, self.tool_name)
tool_settings = ToolkitConfig.load_tool_settings(
self.TOOLKIT, self.tool_name, DEFAULT_SETTINGS
)
self.settings = tool_settings
self.required_settings = REQUIRED_SETTINGS
self._check_required_settings(self.tool_name)
# Priority: skill-provided api_key > toolkit settings > hardcoded default
self.api_key = api_key or self.settings.get(
"CEREBRAS_API_KEY", CEREBRAS_API_KEY
)
# Load model settings
self.model = self.settings.get("CEREBRAS_MODEL", CEREBRAS_MODEL)
self.network = Network({"base_url": "https://api.cerebras.ai/v1"})
# Popular Cerebras-hosted models (override with full model IDs if needed)
self.popular_models = {
"zai-glm-4.7": "zai-glm-4.7",
"qwen-3-235b-a22b-instruct-2507": "qwen-3-235b-a22b-instruct-2507",
"qwen-3-32b": "qwen-3-32b",
}
@property
def tool_name(self) -> str:
return "cerebras"
@property
def toolkit(self) -> str:
return self.TOOLKIT
@property
def description(self) -> str:
return self.config["description"]
def set_api_key(self, api_key: str) -> None:
"""Set the Cerebras API key"""
self.api_key = api_key
def get_available_models(self) -> List[str]:
"""Get list of popular available models"""
return list(self.popular_models.keys())
def get_model_id(self, model_name: str) -> str:
"""Convert friendly model name to Cerebras model ID"""
return self.popular_models.get(model_name, model_name)
def chat_completion(
self,
messages: List[Dict[str, str]],
model: Optional[str] = None,
temperature: float = 0.7,
max_tokens: Optional[int] = None,
system_prompt: Optional[str] = None,
use_structured_output: bool = False,
json_schema: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
"""
Send a chat completion request to Cerebras
Args:
messages: List of message dictionaries with 'role' and 'content'
model: Model name (friendly name or full model ID)
temperature: Sampling temperature (0-2)
max_tokens: Maximum tokens to generate
system_prompt: System prompt to prepend
use_structured_output: Whether to use structured outputs
json_schema: JSON schema for structured output (required if use_structured_output=True)
Returns:
Dict with response data or error information
"""
if not self.api_key:
return {"success": False, "error": "Cerebras API key not configured"}
# Use default model if none provided
model = model or self.model
model_id = self.get_model_id(model)
request_messages: List[Dict[str, str]] = []
if system_prompt:
request_messages.append({"role": "system", "content": system_prompt})
request_messages.extend(messages)
payload: Dict[str, Any] = {
"model": model_id,
"messages": request_messages,
"temperature": temperature,
}
if max_tokens:
payload["max_tokens"] = max_tokens
if use_structured_output:
payload["response_format"] = {"type": "json_object"}
if json_schema:
schema_text = json.dumps(json_schema)
schema_prompt = (
"You must return a valid JSON object that matches this schema:\n"
f"{schema_text}"
)
payload["messages"] = [
{"role": "system", "content": schema_prompt}
] + request_messages
try:
response = self.network.request(
{
"url": "/chat/completions",
"method": "POST",
"headers": {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
},
"data": payload,
}
)
return {"success": True, "data": response["data"], "model_used": model_id}
except NetworkError as e:
return {
"success": False,
"error": f"Cerebras API error: {str(e)}",
"status_code": getattr(e.response, "status_code", None),
}
def completion(
self,
prompt: str,
model: Optional[str] = None,
temperature: float = 0.7,
max_tokens: Optional[int] = None,
system_prompt: Optional[str] = None,
use_structured_output: bool = False,
json_schema: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
"""
General text completion for any use case
Args:
prompt: Text prompt to complete
model: LLM model to use
temperature: Sampling temperature
max_tokens: Maximum tokens to generate
system_prompt: Optional system prompt
use_structured_output: Whether to use structured outputs
json_schema: JSON schema for structured output
Returns:
Dict with completion result
"""
messages = [{"role": "user", "content": prompt}]
response = self.chat_completion(
messages=messages,
model=model,
temperature=temperature,
max_tokens=max_tokens,
system_prompt=system_prompt,
use_structured_output=use_structured_output,
json_schema=json_schema,
)
if not response["success"]:
return response
try:
content = response["data"]["choices"][0]["message"]["content"]
return {
"success": True,
"content": content,
"model_used": response["model_used"],
}
except (KeyError, IndexError) as e:
return {
"success": False,
"error": f"Failed to extract completion: {str(e)}",
}
def structured_completion(
self,
prompt: str,
json_schema: Dict[str, Any],
model: Optional[str] = None,
temperature: float = 0.7,
max_tokens: Optional[int] = None,
system_prompt: Optional[str] = None,
) -> Dict[str, Any]:
"""
Generate structured JSON output using Cerebras structured outputs
Args:
prompt: Text prompt to complete
json_schema: JSON schema defining the required output structure
model: LLM model to use
temperature: Sampling temperature
max_tokens: Maximum tokens to generate
system_prompt: Optional system prompt
Returns:
Dict with parsed JSON result or error
"""
messages = [{"role": "user", "content": prompt}]
response = self.chat_completion(
messages=messages,
model=model,
temperature=temperature,
max_tokens=max_tokens,
system_prompt=system_prompt,
use_structured_output=True,
json_schema=json_schema,
)
if not response["success"]:
return response
try:
content = response["data"]["choices"][0]["message"]["content"]
parsed_data = json.loads(content)
return {
"success": True,
"data": parsed_data,
"model_used": response["model_used"],
}
except (KeyError, IndexError) as e:
return {
"success": False,
"error": f"Failed to extract completion: {str(e)}",
}
except json.JSONDecodeError as e:
return {
"success": False,
"error": f"Failed to parse JSON response: {str(e)}",
}
def list_models(self) -> Dict[str, Any]:
"""
Get list of available models from Cerebras API
Returns:
Dict with models list or error
"""
if not self.api_key:
return {"success": False, "error": "Cerebras API key not configured"}
try:
response = self.network.request(
{
"url": "/models",
"method": "GET",
"headers": {"Authorization": f"Bearer {self.api_key}"},
}
)
return {
"success": True,
"models": response["data"].get("data", response["data"]),
}
except NetworkError as e:
return {"success": False, "error": f"Failed to fetch models: {str(e)}"}
+161
View File
@@ -0,0 +1,161 @@
{
"$schema": "../../../schemas/tool-schemas/tool.json",
"tool_id": "cerebras",
"toolkit_id": "communication",
"name": "Cerebras",
"description": "A tool for interacting with Cerebras LLM APIs (e.g., GLM 4.7).",
"author": {
"name": "Louis Grenard",
"email": "louis@getleon.ai",
"url": "https://twitter.com/grenlouis"
},
"functions": {
"chatCompletion": {
"description": "Generate a chat completion using the Cerebras API.",
"parameters": {
"type": "object",
"properties": {
"options": {
"type": "object",
"properties": {
"messages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"role": {
"type": "string"
},
"content": {
"type": "string"
}
},
"required": [
"role",
"content"
],
"additionalProperties": false
}
},
"model": {
"type": "string"
},
"temperature": {
"type": "number"
},
"max_tokens": {
"type": "number"
},
"system_prompt": {
"type": "string"
},
"use_structured_output": {
"type": "boolean"
},
"json_schema": {
"type": "object",
"additionalProperties": true
}
},
"required": [
"messages"
],
"additionalProperties": false
}
},
"required": [
"options"
]
}
},
"completion": {
"description": "Generate a completion using the Cerebras API.",
"parameters": {
"type": "object",
"properties": {
"options": {
"type": "object",
"properties": {
"prompt": {
"type": "string"
},
"model": {
"type": "string"
},
"temperature": {
"type": "number"
},
"max_tokens": {
"type": "number"
},
"system_prompt": {
"type": "string"
},
"use_structured_output": {
"type": "boolean"
},
"json_schema": {
"type": "object",
"additionalProperties": true
}
},
"required": [
"prompt"
],
"additionalProperties": false
}
},
"required": [
"options"
]
}
},
"structuredCompletion": {
"description": "Generate a structured completion using a JSON schema.",
"parameters": {
"type": "object",
"properties": {
"options": {
"type": "object",
"properties": {
"prompt": {
"type": "string"
},
"json_schema": {
"type": "object",
"additionalProperties": true
},
"model": {
"type": "string"
},
"temperature": {
"type": "number"
},
"max_tokens": {
"type": "number"
},
"system_prompt": {
"type": "string"
}
},
"required": [
"prompt",
"json_schema"
],
"additionalProperties": false
}
},
"required": [
"options"
]
}
},
"listModels": {
"description": "List available Cerebras models.",
"parameters": {
"type": "object",
"properties": {}
}
}
}
}
@@ -0,0 +1,3 @@
from .src.python.inference_tool import InferenceTool
__all__ = ["InferenceTool"]
@@ -0,0 +1 @@
{}
@@ -0,0 +1 @@
export { default } from './inference-tool'
@@ -0,0 +1,97 @@
import { Tool } from '@sdk/base-tool'
import { ToolkitConfig } from '@sdk/toolkit-config'
import { Network } from '@sdk/network'
interface CompletionOptions {
prompt: string
system_prompt?: string
temperature?: number
max_tokens?: number
thought_tokens_budget?: number
disable_thinking?: boolean
reasoning_mode?: 'off' | 'guarded' | 'on'
track_provider_errors?: boolean
}
interface StructuredCompletionOptions extends CompletionOptions {
json_schema: Record<string, unknown>
}
interface InferenceResponse {
success: boolean
output?: unknown
reasoning?: string
usedInputTokens?: number
usedOutputTokens?: number
generationDurationMs?: number
providerDecodeDurationMs?: number
providerTokensPerSecond?: number
error?: string
}
export default class InferenceTool extends Tool {
private static readonly TOOLKIT = 'communication'
private readonly config: ReturnType<typeof ToolkitConfig.load>
private readonly network: Network
constructor() {
super()
this.config = ToolkitConfig.load(InferenceTool.TOOLKIT, this.toolName)
this.network = new Network({
baseURL: `${process.env['LEON_HOST']}:${process.env['LEON_PORT']}/api/v1`
})
}
get toolName(): string {
return 'inference'
}
get toolkit(): string {
return InferenceTool.TOOLKIT
}
get description(): string {
return this.config['description']
}
async completion(options: CompletionOptions): Promise<InferenceResponse> {
const response = await this.network.request<InferenceResponse>({
url: '/inference',
method: 'POST',
data: {
prompt: options.prompt,
systemPrompt: options.system_prompt,
temperature: options.temperature,
maxTokens: options.max_tokens,
thoughtTokensBudget: options.thought_tokens_budget,
disableThinking: options.disable_thinking,
reasoningMode: options.reasoning_mode,
trackProviderErrors: options.track_provider_errors
}
})
return response.data
}
async structuredCompletion(
options: StructuredCompletionOptions
): Promise<InferenceResponse> {
const response = await this.network.request<InferenceResponse>({
url: '/inference',
method: 'POST',
data: {
prompt: options.prompt,
systemPrompt: options.system_prompt,
temperature: options.temperature,
maxTokens: options.max_tokens,
thoughtTokensBudget: options.thought_tokens_budget,
jsonSchema: options.json_schema,
disableThinking: options.disable_thinking,
reasoningMode: options.reasoning_mode,
trackProviderErrors: options.track_provider_errors
}
})
return response.data
}
}
@@ -0,0 +1,93 @@
import os
from typing import Any, Dict, Optional, Literal
from bridges.python.src.sdk.base_tool import BaseTool
from bridges.python.src.sdk.network import Network
from bridges.python.src.sdk.toolkit_config import ToolkitConfig
class InferenceTool(BaseTool):
TOOLKIT = "communication"
def __init__(self):
super().__init__()
self.config = ToolkitConfig.load(self.TOOLKIT, self.tool_name)
self.network = Network(
{
"base_url": f"{os.environ.get('LEON_HOST')}:{os.environ.get('LEON_PORT')}/api/v1"
}
)
@property
def tool_name(self) -> str:
return "inference"
@property
def toolkit(self) -> str:
return self.TOOLKIT
@property
def description(self) -> str:
return self.config.get("description", "")
def completion(
self,
prompt: str,
system_prompt: Optional[str] = None,
temperature: Optional[float] = None,
max_tokens: Optional[int] = None,
thought_tokens_budget: Optional[int] = None,
disable_thinking: Optional[bool] = None,
reasoning_mode: Optional[Literal["off", "guarded", "on"]] = None,
track_provider_errors: Optional[bool] = None,
) -> Dict[str, Any]:
response = self.network.request(
{
"url": "/inference",
"method": "POST",
"data": {
"prompt": prompt,
"systemPrompt": system_prompt,
"temperature": temperature,
"maxTokens": max_tokens,
"thoughtTokensBudget": thought_tokens_budget,
"disableThinking": disable_thinking,
"reasoningMode": reasoning_mode,
"trackProviderErrors": track_provider_errors,
},
}
)
return response["data"]
def structured_completion(
self,
prompt: str,
json_schema: Dict[str, Any],
system_prompt: Optional[str] = None,
temperature: Optional[float] = None,
max_tokens: Optional[int] = None,
thought_tokens_budget: Optional[int] = None,
disable_thinking: Optional[bool] = None,
reasoning_mode: Optional[Literal["off", "guarded", "on"]] = None,
track_provider_errors: Optional[bool] = None,
) -> Dict[str, Any]:
response = self.network.request(
{
"url": "/inference",
"method": "POST",
"data": {
"prompt": prompt,
"systemPrompt": system_prompt,
"temperature": temperature,
"maxTokens": max_tokens,
"thoughtTokensBudget": thought_tokens_budget,
"jsonSchema": json_schema,
"disableThinking": disable_thinking,
"reasoningMode": reasoning_mode,
"trackProviderErrors": track_provider_errors,
},
}
)
return response["data"]
+101
View File
@@ -0,0 +1,101 @@
{
"$schema": "../../../schemas/tool-schemas/tool.json",
"tool_id": "inference",
"toolkit_id": "communication",
"name": "Inference",
"description": "A generic Leon workflow inference tool backed by the active workflow LLM provider.",
"author": {
"name": "Louis Grenard",
"email": "louis@getleon.ai",
"url": "https://twitter.com/grenlouis"
},
"functions": {
"completion": {
"description": "Generate a workflow inference completion.",
"parameters": {
"type": "object",
"properties": {
"prompt": {
"type": "string"
},
"options": {
"type": "object",
"properties": {
"system_prompt": {
"type": "string"
},
"temperature": {
"type": "number"
},
"max_tokens": {
"type": "number"
},
"thought_tokens_budget": {
"type": "number"
},
"disable_thinking": {
"type": "boolean"
},
"reasoning_mode": {
"type": "string"
},
"track_provider_errors": {
"type": "boolean"
}
},
"additionalProperties": false
}
},
"required": [
"prompt"
]
}
},
"structuredCompletion": {
"description": "Generate a structured workflow inference completion using a JSON schema.",
"parameters": {
"type": "object",
"properties": {
"prompt": {
"type": "string"
},
"json_schema": {
"type": "object",
"additionalProperties": true
},
"options": {
"type": "object",
"properties": {
"system_prompt": {
"type": "string"
},
"temperature": {
"type": "number"
},
"max_tokens": {
"type": "number"
},
"thought_tokens_budget": {
"type": "number"
},
"disable_thinking": {
"type": "boolean"
},
"reasoning_mode": {
"type": "string"
},
"track_provider_errors": {
"type": "boolean"
}
},
"additionalProperties": false
}
},
"required": [
"prompt",
"json_schema"
]
}
}
}
}
@@ -0,0 +1,3 @@
from .src.python.openrouter_tool import OpenRouterTool
__all__ = ["OpenRouterTool"]
@@ -0,0 +1,4 @@
{
"OPENROUTER_API_KEY": null,
"OPENROUTER_MODEL": "google/gemini-3.1-flash-lite"
}
@@ -0,0 +1 @@
export { default } from './openrouter-tool'
@@ -0,0 +1,340 @@
import { Tool } from '@sdk/base-tool'
import { ToolkitConfig } from '@sdk/toolkit-config'
import { Network, NetworkError } from '@sdk/network'
// Hardcoded default settings for OpenRouter tool
const OPENROUTER_API_KEY: string | null = null
const OPENROUTER_MODEL = 'google/gemini-3.1-flash-lite'
const DEFAULT_SETTINGS: Record<string, unknown> = {
OPENROUTER_API_KEY,
OPENROUTER_MODEL
}
const REQUIRED_SETTINGS = ['OPENROUTER_API_KEY']
interface ChatMessage {
role: string
content: string
}
interface ChatCompletionOptions {
messages: ChatMessage[]
model?: string
temperature?: number
max_tokens?: number
system_prompt?: string
use_structured_output?: boolean
// eslint-disable-next-line @typescript-eslint/no-explicit-any
json_schema?: Record<string, any>
}
interface CompletionOptions {
prompt: string
model?: string
temperature?: number
max_tokens?: number
system_prompt?: string
use_structured_output?: boolean
// eslint-disable-next-line @typescript-eslint/no-explicit-any
json_schema?: Record<string, any>
}
interface StructuredCompletionOptions {
prompt: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
json_schema: Record<string, any>
model?: string
temperature?: number
max_tokens?: number
system_prompt?: string
}
interface ApiResponse {
success: boolean
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data?: any
model_used?: string
error?: string
status_code?: number
}
export default class OpenRouterTool extends Tool {
private static readonly TOOLKIT = 'communication'
private readonly config: ReturnType<typeof ToolkitConfig.load>
private api_key: string | null
private model: string
private readonly network: Network
constructor(apiKey?: string) {
super()
// Load configuration from central toolkits directory
this.config = ToolkitConfig.load(OpenRouterTool.TOOLKIT, this.toolName)
const toolSettings = ToolkitConfig.loadToolSettings(
OpenRouterTool.TOOLKIT,
this.toolName,
DEFAULT_SETTINGS
)
this.settings = toolSettings
this.requiredSettings = apiKey ? [] : REQUIRED_SETTINGS
this.checkRequiredSettings(this.toolName)
// Priority: skill-provided apiKey > toolkit settings > hardcoded default
this.api_key =
apiKey ||
(this.settings['OPENROUTER_API_KEY'] as string) ||
OPENROUTER_API_KEY
// Load model from toolkit settings or hardcoded default
this.model =
(this.settings['OPENROUTER_MODEL'] as string) || OPENROUTER_MODEL
this.network = new Network({ baseURL: 'https://openrouter.ai/api' })
}
get toolName(): string {
return 'openrouter'
}
get toolkit(): string {
return OpenRouterTool.TOOLKIT
}
get description(): string {
return this.config['description']
}
/**
* Set the OpenRouter API key
*/
setApiKey(apiKey: string): void {
this.api_key = apiKey
}
/**
* Send a chat completion request to OpenRouter
*/
async chatCompletion(options: ChatCompletionOptions): Promise<ApiResponse> {
const {
messages,
model,
temperature = 0.7,
max_tokens,
system_prompt,
use_structured_output = false,
json_schema
} = options
if (!this.api_key) {
return {
success: false,
error: 'OpenRouter API key not configured'
}
}
// Use default model if none provided
const finalModel = model || this.model
// Prepare messages with system prompt if provided
const requestMessages = []
if (system_prompt) {
requestMessages.push({ role: 'system', content: system_prompt })
}
requestMessages.push(...messages)
// Prepare request payload
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const payload: any = {
model: finalModel,
messages: requestMessages,
temperature
}
if (max_tokens) {
payload.max_tokens = max_tokens
}
// Add structured output configuration if requested
if (use_structured_output && json_schema) {
payload.response_format = {
type: 'json_schema',
json_schema: {
name: json_schema['name'] || 'response',
strict: true,
schema: json_schema['schema']
}
}
}
try {
const response = await this.network.request({
url: '/v1/chat/completions',
method: 'POST',
headers: {
Authorization: `Bearer ${this.api_key}`,
'Content-Type': 'application/json'
},
data: payload
})
return {
success: true,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: response.data as any,
model_used: finalModel
}
} catch (error: unknown) {
return {
success: false,
error: `OpenRouter API error: ${(error as Error).message}`,
status_code:
error instanceof NetworkError ? error.response.statusCode : undefined
}
}
}
/**
* General text completion for any use case
*/
async completion(options: CompletionOptions): Promise<ApiResponse> {
const {
prompt,
model,
temperature = 0.7,
max_tokens,
system_prompt,
use_structured_output = false,
json_schema
} = options
const messages = [{ role: 'user', content: prompt }]
const response = await this.chatCompletion({
messages,
model: model || this.model,
temperature,
max_tokens,
system_prompt,
use_structured_output,
json_schema
})
if (!response.success) {
return response
}
try {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const content = (response.data as any).choices[0].message.content
return {
success: true,
data: { content },
model_used: response.model_used
}
} catch (error: unknown) {
return {
success: false,
error: `Failed to extract completion: ${(error as Error).message}`
}
}
}
/**
* Generate structured JSON output using OpenRouter's structured outputs feature
*/
async structuredCompletion(
options: StructuredCompletionOptions
): Promise<ApiResponse> {
const {
prompt,
json_schema,
model,
temperature = 0.7,
max_tokens,
system_prompt
} = options
const messages = [{ role: 'user', content: prompt }]
const response = await this.chatCompletion({
messages,
model: model || this.model,
temperature,
max_tokens,
system_prompt,
use_structured_output: true,
json_schema
})
if (!response.success) {
return response
}
try {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const content = (response.data as any).choices[0].message.content
const parsedData =
typeof content === 'string' ? JSON.parse(content) : content
return {
success: true,
data: parsedData,
model_used: response.model_used
}
} catch (error: unknown) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const content = (response.data as any).choices[0]?.message?.content
if (error instanceof SyntaxError) {
// Show raw response preview to help debug JSON parsing errors
const preview =
typeof content === 'string'
? content.substring(0, 500)
: JSON.stringify(content ?? 'null').substring(0, 500)
return {
success: false,
error: `Failed to parse JSON response: ${error.message}. Response preview: ${preview}`
}
} else {
return {
success: false,
error: `Failed to extract completion: ${(error as Error).message}`
}
}
}
}
/**
* Get list of available models from OpenRouter API
*/
async listModels(): Promise<ApiResponse> {
if (!this.api_key) {
return {
success: false,
error: 'OpenRouter API key not configured'
}
}
try {
const response = await this.network.request({
url: '/v1/models',
method: 'GET',
headers: {
Authorization: `Bearer ${this.api_key}`
}
})
return {
success: true,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: { models: (response.data as any).data }
}
} catch (error: unknown) {
return {
success: false,
error: `Failed to fetch models: ${(error as Error).message}`
}
}
}
}
@@ -0,0 +1,272 @@
import json
from typing import Dict, Any, Optional, List
from bridges.python.src.sdk.base_tool import BaseTool
from bridges.python.src.sdk.toolkit_config import ToolkitConfig
from bridges.python.src.sdk.network import Network, NetworkError
# Hardcoded default settings for OpenRouter tool
OPENROUTER_API_KEY = None
OPENROUTER_MODEL = "google/gemini-3.1-flash-lite"
DEFAULT_SETTINGS = {
"OPENROUTER_API_KEY": OPENROUTER_API_KEY,
"OPENROUTER_MODEL": OPENROUTER_MODEL,
}
REQUIRED_SETTINGS = ["OPENROUTER_API_KEY"]
class OpenRouterTool(BaseTool):
"""OpenRouter tool for unified LLM API access across all skills"""
TOOLKIT = "communication"
def __init__(self, api_key: Optional[str] = None):
super().__init__()
self.config = ToolkitConfig.load(self.TOOLKIT, self.tool_name)
tool_settings = ToolkitConfig.load_tool_settings(
self.TOOLKIT, self.tool_name, DEFAULT_SETTINGS
)
self.settings = tool_settings
self.required_settings = [] if api_key else REQUIRED_SETTINGS
self._check_required_settings(self.tool_name)
# Priority: skill-provided api_key > toolkit settings > hardcoded default
self.api_key = api_key or self.settings.get(
"OPENROUTER_API_KEY", OPENROUTER_API_KEY
)
# Load model settings
self.model = self.settings.get("OPENROUTER_MODEL", OPENROUTER_MODEL)
self.network = Network({"base_url": "https://openrouter.ai/api"})
@property
def tool_name(self) -> str:
return "openrouter"
@property
def toolkit(self) -> str:
return self.TOOLKIT
@property
def description(self) -> str:
return self.config["description"]
def set_api_key(self, api_key: str) -> None:
"""Set the OpenRouter API key"""
self.api_key = api_key
def chat_completion(
self,
messages: List[Dict[str, str]],
model: Optional[str] = None,
temperature: float = 0.7,
max_tokens: Optional[int] = None,
system_prompt: Optional[str] = None,
use_structured_output: bool = False,
json_schema: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
"""
Send a chat completion request to OpenRouter
Args:
messages: List of message dictionaries with 'role' and 'content'
model: Model ID (full OpenRouter model ID, e.g. 'google/gemini-3.1-flash-lite')
temperature: Sampling temperature (0-2)
max_tokens: Maximum tokens to generate
system_prompt: System prompt to prepend
use_structured_output: Whether to use OpenRouter's structured outputs
json_schema: JSON schema for structured output (required if use_structured_output=True)
Returns:
Dict with response data or error information
"""
if not self.api_key:
return {"success": False, "error": "OpenRouter API key not configured"}
# Use default model if none provided
model = model or self.model
# Prepare messages with system prompt if provided
request_messages = []
if system_prompt:
request_messages.append({"role": "system", "content": system_prompt})
request_messages.extend(messages)
# Prepare request payload
payload = {
"model": model,
"messages": request_messages,
"temperature": temperature,
}
if max_tokens:
payload["max_tokens"] = max_tokens
# Add structured output configuration if requested
if use_structured_output and json_schema:
payload["response_format"] = {
"type": "json_schema",
"json_schema": {
"name": json_schema.get("name", "response"),
"strict": True,
"schema": json_schema["schema"],
},
}
try:
response = self.network.request(
{
"url": "/v1/chat/completions",
"method": "POST",
"headers": {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
},
"data": payload,
}
)
return {"success": True, "data": response["data"], "model_used": model}
except NetworkError as e:
return {
"success": False,
"error": f"OpenRouter API error: {str(e)}",
"status_code": getattr(e.response, "status_code", None),
}
def completion(
self,
prompt: str,
model: Optional[str] = None,
temperature: float = 0.7,
max_tokens: Optional[int] = None,
system_prompt: Optional[str] = None,
use_structured_output: bool = False,
json_schema: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
"""
General text completion for any use case
Args:
prompt: Text prompt to complete
model: Model ID (full OpenRouter model ID)
temperature: Sampling temperature
max_tokens: Maximum tokens to generate
system_prompt: Optional system prompt
use_structured_output: Whether to use structured outputs
json_schema: JSON schema for structured output
Returns:
Dict with completion result
"""
messages = [{"role": "user", "content": prompt}]
response = self.chat_completion(
messages=messages,
model=model,
temperature=temperature,
max_tokens=max_tokens,
system_prompt=system_prompt,
use_structured_output=use_structured_output,
json_schema=json_schema,
)
if not response["success"]:
return response
try:
content = response["data"]["choices"][0]["message"]["content"]
return {
"success": True,
"content": content,
"model_used": response["model_used"],
}
except (KeyError, IndexError) as e:
return {
"success": False,
"error": f"Failed to extract completion: {str(e)}",
}
def structured_completion(
self,
prompt: str,
json_schema: Dict[str, Any],
model: Optional[str] = None,
temperature: float = 0.7,
max_tokens: Optional[int] = None,
system_prompt: Optional[str] = None,
) -> Dict[str, Any]:
"""
Generate structured JSON output using OpenRouter's structured outputs feature
Args:
prompt: Text prompt to complete
json_schema: JSON schema defining the required output structure
model: Model ID (full OpenRouter model ID)
temperature: Sampling temperature
max_tokens: Maximum tokens to generate
system_prompt: Optional system prompt
Returns:
Dict with parsed JSON result or error
"""
messages = [{"role": "user", "content": prompt}]
response = self.chat_completion(
messages=messages,
model=model,
temperature=temperature,
max_tokens=max_tokens,
system_prompt=system_prompt,
use_structured_output=True,
json_schema=json_schema,
)
if not response["success"]:
return response
try:
content = response["data"]["choices"][0]["message"]["content"]
# With structured outputs, content is already valid JSON
parsed_data = json.loads(content)
return {
"success": True,
"data": parsed_data,
"model_used": response["model_used"],
}
except (KeyError, IndexError) as e:
return {
"success": False,
"error": f"Failed to extract completion: {str(e)}",
}
except json.JSONDecodeError as e:
return {
"success": False,
"error": f"Failed to parse JSON response: {str(e)}",
}
def list_models(self) -> Dict[str, Any]:
"""
Get list of available models from OpenRouter API
Returns:
Dict with models list or error
"""
if not self.api_key:
return {"success": False, "error": "OpenRouter API key not configured"}
try:
response = self.network.request(
{
"url": "/v1/models",
"method": "GET",
"headers": {"Authorization": f"Bearer {self.api_key}"},
}
)
return {"success": True, "models": response["data"]["data"]}
except NetworkError as e:
return {"success": False, "error": f"Failed to fetch models: {str(e)}"}
+162
View File
@@ -0,0 +1,162 @@
{
"$schema": "../../../schemas/tool-schemas/tool.json",
"tool_id": "openrouter",
"toolkit_id": "communication",
"name": "OpenRouter",
"description": "A tool for interacting with various LLMs through the OpenRouter API gateway.",
"icon_name": "route-line",
"author": {
"name": "Louis Grenard",
"email": "louis@getleon.ai",
"url": "https://twitter.com/grenlouis"
},
"functions": {
"chatCompletion": {
"description": "Generate a chat completion using OpenRouter.",
"parameters": {
"type": "object",
"properties": {
"options": {
"type": "object",
"properties": {
"messages": {
"type": "array",
"items": {
"type": "object",
"properties": {
"role": {
"type": "string"
},
"content": {
"type": "string"
}
},
"required": [
"role",
"content"
],
"additionalProperties": false
}
},
"model": {
"type": "string"
},
"temperature": {
"type": "number"
},
"max_tokens": {
"type": "number"
},
"system_prompt": {
"type": "string"
},
"use_structured_output": {
"type": "boolean"
},
"json_schema": {
"type": "object",
"additionalProperties": true
}
},
"required": [
"messages"
],
"additionalProperties": false
}
},
"required": [
"options"
]
}
},
"completion": {
"description": "Generate a completion using OpenRouter.",
"parameters": {
"type": "object",
"properties": {
"options": {
"type": "object",
"properties": {
"prompt": {
"type": "string"
},
"model": {
"type": "string"
},
"temperature": {
"type": "number"
},
"max_tokens": {
"type": "number"
},
"system_prompt": {
"type": "string"
},
"use_structured_output": {
"type": "boolean"
},
"json_schema": {
"type": "object",
"additionalProperties": true
}
},
"required": [
"prompt"
],
"additionalProperties": false
}
},
"required": [
"options"
]
}
},
"structuredCompletion": {
"description": "Generate a structured completion using a JSON schema.",
"parameters": {
"type": "object",
"properties": {
"options": {
"type": "object",
"properties": {
"prompt": {
"type": "string"
},
"json_schema": {
"type": "object",
"additionalProperties": true
},
"model": {
"type": "string"
},
"temperature": {
"type": "number"
},
"max_tokens": {
"type": "number"
},
"system_prompt": {
"type": "string"
}
},
"required": [
"prompt",
"json_schema"
],
"additionalProperties": false
}
},
"required": [
"options"
]
}
},
"listModels": {
"description": "List available OpenRouter models.",
"parameters": {
"type": "object",
"properties": {}
}
}
}
}
+12
View File
@@ -0,0 +1,12 @@
{
"$schema": "../../schemas/toolkit-schemas/toolkit.json",
"name": "Communication",
"description": "Tools for communication and language model interactions.",
"icon_name": "chat-3-line",
"context_files": [
"LEON.md",
"ARCHITECTURE.md",
"MEDIA_PROFILE.md"
],
"tools": []
}