["className"];
+ width?: ModalWidth;
}
-export function ModalBody({ testID, children, className }: ModalBodyProps) {
+export function ModalBody({
+ testID,
+ children,
+ className,
+ width = "small",
+}: ModalBodyProps) {
return (
diff --git a/frontend/src/i18n/declaration.ts b/frontend/src/i18n/declaration.ts
index 1cf81f641f..9183f6f5f4 100644
--- a/frontend/src/i18n/declaration.ts
+++ b/frontend/src/i18n/declaration.ts
@@ -326,6 +326,7 @@ export enum I18nKey {
ACTION_MESSAGE$BROWSE = "ACTION_MESSAGE$BROWSE",
ACTION_MESSAGE$BROWSE_INTERACTIVE = "ACTION_MESSAGE$BROWSE_INTERACTIVE",
ACTION_MESSAGE$THINK = "ACTION_MESSAGE$THINK",
+ ACTION_MESSAGE$SYSTEM = "ACTION_MESSAGE$SYSTEM",
OBSERVATION_MESSAGE$RUN = "OBSERVATION_MESSAGE$RUN",
OBSERVATION_MESSAGE$RUN_IPYTHON = "OBSERVATION_MESSAGE$RUN_IPYTHON",
OBSERVATION_MESSAGE$READ = "OBSERVATION_MESSAGE$READ",
@@ -416,4 +417,11 @@ export enum I18nKey {
DIFF_VIEWER$ASK_OH = "DIFF_VIEWER$ASK_OH",
DIFF_VIEWER$NO_CHANGES = "DIFF_VIEWER$NO_CHANGES",
DIFF_VIEWER$WAITING_FOR_RUNTIME = "DIFF_VIEWER$WAITING_FOR_RUNTIME",
+ SYSTEM_MESSAGE_MODAL$TITLE = "SYSTEM_MESSAGE_MODAL$TITLE",
+ SYSTEM_MESSAGE_MODAL$AGENT_CLASS = "SYSTEM_MESSAGE_MODAL$AGENT_CLASS",
+ SYSTEM_MESSAGE_MODAL$OPENHANDS_VERSION = "SYSTEM_MESSAGE_MODAL$OPENHANDS_VERSION",
+ SYSTEM_MESSAGE_MODAL$SYSTEM_MESSAGE_TAB = "SYSTEM_MESSAGE_MODAL$SYSTEM_MESSAGE_TAB",
+ SYSTEM_MESSAGE_MODAL$TOOLS_TAB = "SYSTEM_MESSAGE_MODAL$TOOLS_TAB",
+ SYSTEM_MESSAGE_MODAL$PARAMETERS = "SYSTEM_MESSAGE_MODAL$PARAMETERS",
+ SYSTEM_MESSAGE_MODAL$NO_TOOLS = "SYSTEM_MESSAGE_MODAL$NO_TOOLS",
}
diff --git a/frontend/src/i18n/translation.json b/frontend/src/i18n/translation.json
index 6acf018c17..ef6dedb1b1 100644
--- a/frontend/src/i18n/translation.json
+++ b/frontend/src/i18n/translation.json
@@ -4869,6 +4869,21 @@
"es": "Pensando",
"tr": "Düşünüyor"
},
+ "ACTION_MESSAGE$SYSTEM": {
+ "en": "System Message",
+ "zh-CN": "系统消息",
+ "zh-TW": "系統訊息",
+ "ko-KR": "시스템 메시지",
+ "ja": "システムメッセージ",
+ "no": "Systemmelding",
+ "ar": "رسالة النظام",
+ "de": "Systemnachricht",
+ "fr": "Message Système",
+ "it": "Messaggio di Sistema",
+ "pt": "Mensagem do Sistema",
+ "es": "Mensaje del Sistema",
+ "tr": "Sistem Mesajı"
+ },
"OBSERVATION_MESSAGE$RUN": {
"en": "Ran {{observation.payload.extras.command}}",
"zh-CN": "运行 {{observation.payload.extras.command}}",
@@ -6207,5 +6222,110 @@
"fr": "En attente du démarrage de l'exécution...",
"tr": "Çalışma zamanının başlamasını bekliyor...",
"de": "Warten auf den Start der Laufzeit..."
+ },
+ "SYSTEM_MESSAGE_MODAL$TITLE": {
+ "en": "Agent Tools & Metadata",
+ "zh-CN": "代理工具和元数据",
+ "zh-TW": "代理工具和元數據",
+ "ko-KR": "에이전트 도구 및 메타데이터",
+ "ja": "エージェントツールとメタデータ",
+ "no": "Agent-verktøy og metadata",
+ "ar": "أدوات الوكيل والبيانات الوصفية",
+ "de": "Agent-Tools und Metadaten",
+ "fr": "Outils d'agent et métadonnées",
+ "it": "Strumenti e metadati dell'agente",
+ "pt": "Ferramentas e metadados do agente",
+ "es": "Herramientas y metadatos del agente",
+ "tr": "Ajan Araçları ve Meta Verileri"
+ },
+ "SYSTEM_MESSAGE_MODAL$AGENT_CLASS": {
+ "en": "Agent Class:",
+ "zh-CN": "代理类别:",
+ "zh-TW": "代理類別:",
+ "ko-KR": "에이전트 클래스:",
+ "ja": "エージェントクラス:",
+ "no": "Agent-klasse:",
+ "ar": "فئة الوكيل:",
+ "de": "Agent-Klasse:",
+ "fr": "Classe d'agent :",
+ "it": "Classe agente:",
+ "pt": "Classe do agente:",
+ "es": "Clase de agente:",
+ "tr": "Ajan Sınıfı:"
+ },
+ "SYSTEM_MESSAGE_MODAL$OPENHANDS_VERSION": {
+ "en": "OpenHands Version:",
+ "zh-CN": "OpenHands 版本:",
+ "zh-TW": "OpenHands 版本:",
+ "ko-KR": "OpenHands 버전:",
+ "ja": "OpenHands バージョン:",
+ "no": "OpenHands-versjon:",
+ "ar": "إصدار OpenHands:",
+ "de": "OpenHands-Version:",
+ "fr": "Version OpenHands :",
+ "it": "Versione OpenHands:",
+ "pt": "Versão OpenHands:",
+ "es": "Versión de OpenHands:",
+ "tr": "OpenHands Sürümü:"
+ },
+ "SYSTEM_MESSAGE_MODAL$SYSTEM_MESSAGE_TAB": {
+ "en": "System Message",
+ "zh-CN": "系统消息",
+ "zh-TW": "系統訊息",
+ "ko-KR": "시스템 메시지",
+ "ja": "システムメッセージ",
+ "no": "Systemmelding",
+ "ar": "رسالة النظام",
+ "de": "Systemnachricht",
+ "fr": "Message système",
+ "it": "Messaggio di sistema",
+ "pt": "Mensagem do sistema",
+ "es": "Mensaje del sistema",
+ "tr": "Sistem Mesajı"
+ },
+ "SYSTEM_MESSAGE_MODAL$TOOLS_TAB": {
+ "en": "Available Tools",
+ "zh-CN": "可用工具",
+ "zh-TW": "可用工具",
+ "ko-KR": "사용 가능한 도구",
+ "ja": "利用可能なツール",
+ "no": "Tilgjengelige verktøy",
+ "ar": "الأدوات المتاحة",
+ "de": "Verfügbare Tools",
+ "fr": "Outils disponibles",
+ "it": "Strumenti disponibili",
+ "pt": "Ferramentas disponíveis",
+ "es": "Herramientas disponibles",
+ "tr": "Kullanılabilir Araçlar"
+ },
+ "SYSTEM_MESSAGE_MODAL$PARAMETERS": {
+ "en": "Parameters:",
+ "zh-CN": "参数:",
+ "zh-TW": "參數:",
+ "ko-KR": "매개변수:",
+ "ja": "パラメータ:",
+ "no": "Parametere:",
+ "ar": "المعلمات:",
+ "de": "Parameter:",
+ "fr": "Paramètres :",
+ "it": "Parametri:",
+ "pt": "Parâmetros:",
+ "es": "Parámetros:",
+ "tr": "Parametreler:"
+ },
+ "SYSTEM_MESSAGE_MODAL$NO_TOOLS": {
+ "en": "No tools available for this agent",
+ "zh-CN": "此代理没有可用的工具",
+ "zh-TW": "此代理沒有可用的工具",
+ "ko-KR": "이 에이전트에 사용 가능한 도구가 없습니다",
+ "ja": "このエージェントで利用可能なツールはありません",
+ "no": "Ingen verktøy tilgjengelig for denne agenten",
+ "ar": "لا توجد أدوات متاحة لهذا الوكيل",
+ "de": "Keine Tools für diesen Agenten verfügbar",
+ "fr": "Aucun outil disponible pour cet agent",
+ "it": "Nessuno strumento disponibile per questo agente",
+ "pt": "Nenhuma ferramenta disponível para este agente",
+ "es": "No hay herramientas disponibles para este agente",
+ "tr": "Bu ajan için kullanılabilir araç yok"
}
}
diff --git a/frontend/src/state/chat-slice.ts b/frontend/src/state/chat-slice.ts
index 0d70005ec0..e6b2790f4e 100644
--- a/frontend/src/state/chat-slice.ts
+++ b/frontend/src/state/chat-slice.ts
@@ -11,7 +11,15 @@ import {
RecallObservation,
} from "#/types/core/observations";
-type SliceState = { messages: Message[] };
+type SliceState = {
+ messages: Message[];
+ systemMessage: {
+ content: string;
+ tools: Array> | null;
+ openhands_version: string | null;
+ agent_class: string | null;
+ } | null;
+};
const MAX_CONTENT_LENGTH = 1000;
@@ -25,6 +33,7 @@ const HANDLED_ACTIONS: OpenHandsEventType[] = [
"edit",
"recall",
"think",
+ "system",
];
function getRiskText(risk: ActionSecurityRisk) {
@@ -43,6 +52,7 @@ function getRiskText(risk: ActionSecurityRisk) {
const initialState: SliceState = {
messages: [],
+ systemMessage: null,
};
export const chatSlice = createSlice({
@@ -100,6 +110,18 @@ export const chatSlice = createSlice({
}
const translationID = `ACTION_MESSAGE$${actionID.toUpperCase()}`;
let text = "";
+
+ if (actionID === "system") {
+ // Store the system message in the state
+ state.systemMessage = {
+ content: action.payload.args.content,
+ tools: action.payload.args.tools,
+ openhands_version: action.payload.args.openhands_version,
+ agent_class: action.payload.args.agent_class,
+ };
+ // Don't add a message for system actions
+ return;
+ }
if (actionID === "run") {
text = `Command:\n\`${action.payload.args.command}\``;
} else if (actionID === "run_ipython") {
@@ -295,6 +317,7 @@ export const chatSlice = createSlice({
clearMessages(state: SliceState) {
state.messages = [];
+ state.systemMessage = null;
},
},
});
@@ -307,4 +330,9 @@ export const {
addErrorMessage,
clearMessages,
} = chatSlice.actions;
+
+// Selectors
+export const selectSystemMessage = (state: { chat: SliceState }) =>
+ state.chat.systemMessage;
+
export default chatSlice.reducer;
diff --git a/frontend/src/types/action-type.tsx b/frontend/src/types/action-type.tsx
index 315abcc7b0..f623233ba5 100644
--- a/frontend/src/types/action-type.tsx
+++ b/frontend/src/types/action-type.tsx
@@ -5,6 +5,9 @@ enum ActionType {
// Represents a message from the user or agent.
MESSAGE = "message",
+ // Represents a system message for an agent, including the system prompt and available tools.
+ SYSTEM = "system",
+
// Reads the contents of a file.
READ = "read",
diff --git a/frontend/src/types/core/actions.ts b/frontend/src/types/core/actions.ts
index 6a8bb61792..5010eb3822 100644
--- a/frontend/src/types/core/actions.ts
+++ b/frontend/src/types/core/actions.ts
@@ -9,6 +9,16 @@ export interface UserMessageAction extends OpenHandsActionEvent<"message"> {
};
}
+export interface SystemMessageAction extends OpenHandsActionEvent<"system"> {
+ source: "agent";
+ args: {
+ content: string;
+ tools: Array> | null;
+ openhands_version: string | null;
+ agent_class: string | null;
+ };
+}
+
export interface CommandAction extends OpenHandsActionEvent<"run"> {
source: "agent";
args: {
@@ -145,6 +155,7 @@ export interface RecallAction extends OpenHandsActionEvent<"recall"> {
export type OpenHandsAction =
| UserMessageAction
| AssistantMessageAction
+ | SystemMessageAction
| CommandAction
| IPythonAction
| ThinkAction
diff --git a/frontend/src/types/core/base.ts b/frontend/src/types/core/base.ts
index c52824661f..cb3b27baa9 100644
--- a/frontend/src/types/core/base.ts
+++ b/frontend/src/types/core/base.ts
@@ -1,5 +1,6 @@
export type OpenHandsEventType =
| "message"
+ | "system"
| "agent_state_changed"
| "run"
| "read"
diff --git a/openhands/controller/agent.py b/openhands/controller/agent.py
index 78bdbb126d..034cacf481 100644
--- a/openhands/controller/agent.py
+++ b/openhands/controller/agent.py
@@ -68,7 +68,7 @@ class Agent(ABC):
tools = getattr(self, 'tools', None)
system_message_action = SystemMessageAction(
- content=system_message, tools=tools
+ content=system_message, tools=tools, agent_class=self.name
)
# Set the source attribute
system_message_action._source = EventSource.AGENT # type: ignore
diff --git a/openhands/events/action/message.py b/openhands/events/action/message.py
index 511df18aec..1e8eb7568a 100644
--- a/openhands/events/action/message.py
+++ b/openhands/events/action/message.py
@@ -46,6 +46,7 @@ class SystemMessageAction(Action):
content: str
tools: list[Any] | None = None
openhands_version: str | None = openhands.__version__
+ agent_class: str | None = None
action: ActionType = ActionType.SYSTEM
@property
@@ -57,4 +58,6 @@ class SystemMessageAction(Action):
ret += f'CONTENT: {self.content}'
if self.tools:
ret += f'\nTOOLS: {len(self.tools)} tools available'
+ if self.agent_class:
+ ret += f'\nAGENT_CLASS: {self.agent_class}'
return ret