Compare commits

...

2 Commits

Author SHA1 Message Date
Engel Nyst
236f4fe2c0 Merge branch 'main' into enyst/openhands-types 2025-07-26 22:52:52 +02:00
Engel Nyst
71a2c574d2 split core types package 2025-06-24 13:53:31 +02:00
12 changed files with 626 additions and 0 deletions

30
packages/types/package-lock.json generated Normal file
View File

@@ -0,0 +1,30 @@
{
"name": "@openhands/types",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@openhands/types",
"version": "0.1.0",
"license": "MIT",
"devDependencies": {
"typescript": "^5.8.3"
}
},
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
}
}
}

View File

@@ -0,0 +1,15 @@
{
"name": "@openhands/types",
"version": "0.1.0",
"description": "Shared type definitions and utilities for OpenHands projects",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"watch": "tsc --watch"
},
"devDependencies": {
"typescript": "^5.8.3"
},
"license": "MIT"
}

View File

@@ -0,0 +1,180 @@
import { OpenHandsActionEvent } from "./base";
import { ActionSecurityRisk } from "./security";
export interface UserMessageAction extends OpenHandsActionEvent<"message"> {
source: "user";
args: {
content: string;
image_urls: string[];
};
}
export interface SystemMessageAction extends OpenHandsActionEvent<"system"> {
source: "agent";
args: {
content: string;
tools: Array<Record<string, unknown>> | null;
openhands_version: string | null;
agent_class: string | null;
};
}
export interface CommandAction extends OpenHandsActionEvent<"run"> {
source: "agent" | "user";
args: {
command: string;
security_risk: ActionSecurityRisk;
confirmation_state: "confirmed" | "rejected" | "awaiting_confirmation";
thought: string;
hidden?: boolean;
};
}
export interface AssistantMessageAction
extends OpenHandsActionEvent<"message"> {
source: "agent";
args: {
thought: string;
image_urls: string[] | null;
wait_for_response: boolean;
};
}
export interface IPythonAction extends OpenHandsActionEvent<"run_ipython"> {
source: "agent";
args: {
code: string;
security_risk: ActionSecurityRisk;
confirmation_state: "confirmed" | "rejected" | "awaiting_confirmation";
kernel_init_code: string;
thought: string;
};
}
export interface ThinkAction extends OpenHandsActionEvent<"think"> {
source: "agent";
args: {
thought: string;
};
}
export interface FinishAction extends OpenHandsActionEvent<"finish"> {
source: "agent";
args: {
final_thought: string;
task_completed: "success" | "failure" | "partial";
outputs: Record<string, unknown>;
thought: string;
};
}
export interface DelegateAction extends OpenHandsActionEvent<"delegate"> {
source: "agent";
timeout: number;
args: {
agent: "BrowsingAgent";
inputs: Record<string, string>;
thought: string;
};
}
export interface BrowseAction extends OpenHandsActionEvent<"browse"> {
source: "agent";
args: {
url: string;
thought: string;
};
}
export interface BrowseInteractiveAction
extends OpenHandsActionEvent<"browse_interactive"> {
source: "agent";
timeout: number;
args: {
browser_actions: string;
thought: string | null;
browsergym_send_msg_to_user: string;
};
}
export interface FileReadAction extends OpenHandsActionEvent<"read"> {
source: "agent";
args: {
path: string;
thought: string;
security_risk: ActionSecurityRisk | null;
impl_source?: string;
view_range?: number[] | null;
};
}
export interface FileWriteAction extends OpenHandsActionEvent<"write"> {
source: "agent";
args: {
path: string;
content: string;
thought: string;
};
}
export interface FileEditAction extends OpenHandsActionEvent<"edit"> {
source: "agent";
args: {
path: string;
command?: string;
file_text?: string | null;
view_range?: number[] | null;
old_str?: string | null;
new_str?: string | null;
insert_line?: number | null;
content?: string;
start?: number;
end?: number;
thought: string;
security_risk: ActionSecurityRisk | null;
impl_source?: string;
};
}
export interface RejectAction extends OpenHandsActionEvent<"reject"> {
source: "agent";
args: {
thought: string;
};
}
export interface RecallAction extends OpenHandsActionEvent<"recall"> {
source: "agent";
args: {
recall_type: "workspace_context" | "knowledge";
query: string;
thought: string;
};
}
export interface MCPAction extends OpenHandsActionEvent<"call_tool_mcp"> {
source: "agent";
args: {
name: string;
arguments: Record<string, unknown>;
thought?: string;
};
}
export type OpenHandsAction =
| UserMessageAction
| AssistantMessageAction
| SystemMessageAction
| CommandAction
| IPythonAction
| ThinkAction
| FinishAction
| DelegateAction
| BrowseAction
| BrowseInteractiveAction
| FileReadAction
| FileEditAction
| FileWriteAction
| RejectAction
| RecallAction
| MCPAction;

View File

@@ -0,0 +1,15 @@
export enum AgentState {
INIT = "INIT",
RUNNING = "RUNNING",
AWAITING_USER_INPUT = "AWAITING_USER_INPUT",
PAUSED = "PAUSED",
LOADING = "LOADING",
STOPPED = "STOPPED",
FINISHED = "FINISHED",
REJECTED = "REJECTED",
ERROR = "ERROR",
AWAITING_USER_CONFIRMATION = "AWAITING_USER_CONFIRMATION",
USER_CONFIRMED = "USER_CONFIRMED",
USER_REJECTED = "USER_REJECTED",
RATE_LIMITED = "RATE_LIMITED",
}

View File

@@ -0,0 +1,44 @@
export type OpenHandsEventType =
| "message"
| "system"
| "agent_state_changed"
| "change_agent_state"
| "run"
| "read"
| "write"
| "edit"
| "run_ipython"
| "delegate"
| "browse"
| "browse_interactive"
| "reject"
| "think"
| "finish"
| "error"
| "recall"
| "mcp"
| "call_tool_mcp"
| "user_rejected";
export type OpenHandsSourceType = "agent" | "user" | "environment";
interface OpenHandsBaseEvent {
id: number;
source: OpenHandsSourceType;
message: string;
timestamp: string; // ISO 8601
}
export interface OpenHandsActionEvent<T extends OpenHandsEventType>
extends OpenHandsBaseEvent {
action: T;
args: Record<string, unknown>;
}
export interface OpenHandsObservationEvent<T extends OpenHandsEventType>
extends OpenHandsBaseEvent {
cause: number;
observation: T;
content: string;
extras: Record<string, unknown>;
}

View File

@@ -0,0 +1,82 @@
import { OpenHandsParsedEvent } from ".";
import {
UserMessageAction,
AssistantMessageAction,
OpenHandsAction,
SystemMessageAction,
CommandAction,
} from "./actions";
import {
AgentStateChangeObservation,
CommandObservation,
ErrorObservation,
MCPObservation,
OpenHandsObservation,
} from "./observations";
import { StatusUpdate } from "./variances";
export const isOpenHandsAction = (
event: OpenHandsParsedEvent,
): event is OpenHandsAction => "action" in event;
export const isOpenHandsObservation = (
event: OpenHandsParsedEvent,
): event is OpenHandsObservation => "observation" in event;
export const isUserMessage = (
event: OpenHandsParsedEvent,
): event is UserMessageAction =>
isOpenHandsAction(event) &&
event.source === "user" &&
event.action === "message";
export const isAssistantMessage = (
event: OpenHandsParsedEvent,
): event is AssistantMessageAction =>
isOpenHandsAction(event) &&
event.source === "agent" &&
(event.action === "message" || event.action === "finish");
export const isErrorObservation = (
event: OpenHandsParsedEvent,
): event is ErrorObservation =>
isOpenHandsObservation(event) && event.observation === "error";
export const isCommandAction = (
event: OpenHandsParsedEvent,
): event is CommandAction => isOpenHandsAction(event) && event.action === "run";
export const isAgentStateChangeObservation = (
event: OpenHandsParsedEvent,
): event is AgentStateChangeObservation =>
isOpenHandsObservation(event) && event.observation === "agent_state_changed";
export const isCommandObservation = (
event: OpenHandsParsedEvent,
): event is CommandObservation =>
isOpenHandsObservation(event) && event.observation === "run";
export const isFinishAction = (
event: OpenHandsParsedEvent,
): event is AssistantMessageAction =>
isOpenHandsAction(event) && event.action === "finish";
export const isSystemMessage = (
event: OpenHandsParsedEvent,
): event is SystemMessageAction =>
isOpenHandsAction(event) && event.action === "system";
export const isRejectObservation = (
event: OpenHandsParsedEvent,
): event is OpenHandsObservation =>
isOpenHandsObservation(event) && event.observation === "user_rejected";
export const isMcpObservation = (
event: OpenHandsParsedEvent,
): event is MCPObservation =>
isOpenHandsObservation(event) && event.observation === "mcp";
export const isStatusUpdate = (
event: OpenHandsParsedEvent,
): event is StatusUpdate =>
"status_update" in event && "type" in event && "id" in event;

View File

@@ -0,0 +1,8 @@
import { OpenHandsAction } from "./actions";
import { OpenHandsObservation } from "./observations";
import { OpenHandsVariance } from "./variances";
export type OpenHandsParsedEvent =
| OpenHandsAction
| OpenHandsObservation
| OpenHandsVariance;

View File

@@ -0,0 +1,163 @@
import { AgentState } from "./agent-state";
import { OpenHandsObservationEvent } from "./base";
export interface AgentStateChangeObservation
extends OpenHandsObservationEvent<"agent_state_changed"> {
source: "agent";
extras: {
agent_state: AgentState;
reason?: string;
};
}
export interface CommandObservation extends OpenHandsObservationEvent<"run"> {
source: "agent" | "user";
extras: {
command: string;
hidden?: boolean;
metadata: Record<string, unknown>;
};
}
export interface IPythonObservation
extends OpenHandsObservationEvent<"run_ipython"> {
source: "agent";
extras: {
code: string;
image_urls?: string[];
};
}
export interface DelegateObservation
extends OpenHandsObservationEvent<"delegate"> {
source: "agent";
extras: {
outputs: Record<string, unknown>;
};
}
export interface BrowseObservation extends OpenHandsObservationEvent<"browse"> {
source: "agent";
extras: {
url: string;
screenshot: string;
error: boolean;
open_page_urls: string[];
active_page_index: number;
dom_object: Record<string, unknown>;
axtree_object: Record<string, unknown>;
extra_element_properties: Record<string, unknown>;
last_browser_action: string;
last_browser_action_error: unknown;
focused_element_bid: string;
};
}
export interface BrowseInteractiveObservation
extends OpenHandsObservationEvent<"browse_interactive"> {
source: "agent";
extras: {
url: string;
screenshot: string;
error: boolean;
open_page_urls: string[];
active_page_index: number;
dom_object: Record<string, unknown>;
axtree_object: Record<string, unknown>;
extra_element_properties: Record<string, unknown>;
last_browser_action: string;
last_browser_action_error: unknown;
focused_element_bid: string;
};
}
export interface WriteObservation extends OpenHandsObservationEvent<"write"> {
source: "agent";
extras: {
path: string;
content: string;
};
}
export interface ReadObservation extends OpenHandsObservationEvent<"read"> {
source: "agent";
extras: {
path: string;
impl_source: string;
};
}
export interface EditObservation extends OpenHandsObservationEvent<"edit"> {
source: "agent";
extras: {
path: string;
diff: string;
impl_source: string;
};
}
export interface ErrorObservation extends OpenHandsObservationEvent<"error"> {
source: "user";
extras: {
error_id?: string;
};
}
export interface AgentThinkObservation
extends OpenHandsObservationEvent<"think"> {
source: "agent";
extras: {
thought: string;
};
}
export interface MicroagentKnowledge {
name: string;
trigger: string;
content: string;
}
export interface RecallObservation extends OpenHandsObservationEvent<"recall"> {
source: "agent";
extras: {
recall_type?: "workspace_context" | "knowledge";
repo_name?: string;
repo_directory?: string;
repo_instructions?: string;
runtime_hosts?: Record<string, number>;
custom_secrets_descriptions?: Record<string, string>;
additional_agent_instructions?: string;
date?: string;
microagent_knowledge?: MicroagentKnowledge[];
};
}
export interface MCPObservation extends OpenHandsObservationEvent<"mcp"> {
source: "agent";
extras: {
name: string;
arguments: Record<string, unknown>;
};
}
export interface UserRejectedObservation
extends OpenHandsObservationEvent<"user_rejected"> {
source: "agent";
extras: Record<string, unknown>;
}
export type OpenHandsObservation =
| AgentStateChangeObservation
| AgentThinkObservation
| CommandObservation
| IPythonObservation
| DelegateObservation
| BrowseObservation
| BrowseInteractiveObservation
| WriteObservation
| ReadObservation
| EditObservation
| ErrorObservation
| RecallObservation
| MCPObservation
| UserRejectedObservation;

View File

@@ -0,0 +1,6 @@
export enum ActionSecurityRisk {
UNKNOWN = -1,
LOW = 0,
MEDIUM = 1,
HIGH = 2,
}

View File

@@ -0,0 +1,47 @@
/** Variances are types which do not conform to the current event pattern */
export interface TokenConfigSuccess {
status: "ok" | number;
token: string;
}
interface TokenConfigError {
status: 401;
}
type TokenConfig = TokenConfigSuccess | TokenConfigError;
export interface InitConfig {
action: "initialize";
args: {
AGENT: string;
CONFIRMATION_MODE: boolean;
LANGUAGE: string;
LLM_API_KEY_SET: boolean;
LLM_MODEL: string;
};
token?: string;
latest_event_id?: unknown; // Not sure what this is
}
// Bare minimum event type sent from the client
interface LocalUserMessageAction {
action: "message";
args: {
content: string;
image_urls: string[];
};
}
export interface StatusUpdate {
status_update: true;
type: "error";
id: string;
message: string;
}
export type OpenHandsVariance =
| TokenConfig
| InitConfig
| LocalUserMessageAction
| StatusUpdate;

View File

@@ -0,0 +1,9 @@
// Export all types and utilities from core directory
export * from './core/base';
export * from './core/guards';
export * from './core/actions';
export * from './core/observations';
export * from './core/variances';
export * from './core/index';
export * from './core/security';
export * from './core/agent-state';

View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
"lib": [
"dom",
"dom.iterable",
"es2022"
],
"target": "es2022",
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"emitDeclarationOnly": false,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": false
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}