Skip to content
Closed
Show file tree
Hide file tree
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
92 changes: 92 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
export type {
AgentBannerEvent,
AgentCommand,
AgentContextUsageEvent,
AgentDebugEvent,
AgentErrorAttempt,
AgentErrorEvent,
AgentEvent,
AgentInputEvent,
AgentLoop,
AgentPlanEvent,
AgentPlanProgressEvent,
AgentQueue,
AgentRuntime,
AgentRuntimeOptions,
AgentStatusEvent,
AgentStatusLevel,
AssistantMessageEvent,
CommandExecutionDetails,
CommandExecutionResult,
CommandPreview,
CommandResultEvent,
ContextUsageSummary,
ConversationMessage,
HistoryCompactorLike,
OpenAIClientLike,
OpenAgentToolCall,
PlanProgressSummary,
PlanStatus,
PlanStep,
RequestInputEvent,
SchemaValidationErrorDescriptor,
SchemaValidationFailedEvent,
} from './src/agent/loop.js';

export {
createAgentLoop,
createAgentRuntime,
extractOpenAgentToolCall,
extractResponseText,
} from './src/agent/loop.js';

export const MODEL: any;
export const getOpenAIClient: any;
export const resetOpenAIClient: any;
export const startThinking: any;
export const stopThinking: any;
export const formatElapsedTime: any;
export const createInterface: any;
export const askHuman: any;
export const ESCAPE_EVENT: any;
export const display: any;
export const wrapStructuredContent: any;
export const renderMarkdownMessage: any;
export const renderPlan: any;
export const renderMessage: any;
export const renderCommand: any;
export const renderPlanProgress: any;
export const renderRemainingContext: any;
export const runCommand: any;
export const CommandApprovalService: any;
export const sessionApprovalService: any;
export const loadPreapprovedConfig: any;
export const isPreapprovedCommand: any;
export const isSessionApproved: any;
export const approveForSession: any;
export const resetSessionApprovals: any;
export const __commandSignature: any;
export const PREAPPROVED_CFG: any;
export const applyFilter: any;
export const tailLines: any;
export const shellSplit: any;
export const findAgentFiles: any;
export const buildAgentsPrompt: any;
export const BASE_SYSTEM_PROMPT: any;
export const SYSTEM_PROMPT: any;
export const createWebSocketBinding: any;
export const setStartupFlags: any;
export const parseStartupFlagsFromArgv: any;
export const applyStartupFlagsFromArgv: any;
export const runCommandAndTrack: any;
export const agentLoop: any;

declare const _default: {
[key: string]: unknown;
createAgentLoop: typeof createAgentLoop;
createAgentRuntime: typeof createAgentRuntime;
extractOpenAgentToolCall: typeof extractOpenAgentToolCall;
extractResponseText: typeof extractResponseText;
};

export default _default;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "Simple Node.JS based AI agent",
"type": "module",
"main": "index.js",
"types": "index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/asynkron/OpenAgent"
Expand Down
1 change: 1 addition & 0 deletions src/agent/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
## Key Modules

- `loop.js` — orchestrates the event-driven runtime: manages plan snapshots, queues inputs/outputs, handles OpenAI calls, applies filters, and coordinates cancellation.
- `loop.d.ts` — type declaration describing the runtime event stream, command payloads, and factory options for consumers that need TypeScript support.
- `approvalManager.js` — centralizes auto-approval checks (allowlist/session flags) and human prompts; the constructor normalizes optional collaborators once so runtime logic can invoke them without repetitive type guards.
- `commandExecution.js` — normalizes assistant commands before dispatching to the default executor and tracks runtime metadata.
- `commands/` subdirectory — houses the default execute strategy used for all shell invocations.
Expand Down
251 changes: 251 additions & 0 deletions src/agent/loop.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
/**
* Conversational role metadata attached to history entries exchanged with the model.
*/
export interface ConversationMessage {
role: string;
content: unknown;
}

/** Summary describing how much of the current context window is consumed. */
export interface ContextUsageSummary {
total: number | null;
used: number;
remaining: number | null;
percentRemaining: number | null;
}

export type AgentStatusLevel = 'info' | 'warn';

export interface AgentStatusEvent {
type: 'status';
level: AgentStatusLevel;
message: string;
details?: string;
}

export interface AgentErrorAttempt {
strategy: string;
message: string;
}

export interface AgentErrorEvent {
type: 'error';
message: string;
details?: string;
raw?: string;
attempts?: readonly AgentErrorAttempt[];
}

export interface AgentDebugEvent {
type: 'debug';
payload: unknown;
}

export interface AgentBannerEvent {
type: 'banner';
title: string;
}

export interface AgentThinkingEvent {
type: 'thinking';
state: 'start' | 'stop';
}

export interface AgentContextUsageEvent {
type: 'context-usage';
usage: ContextUsageSummary;
}

export type PlanStatus = 'pending' | 'running' | 'completed';

export interface PlanStep {
step: string;
title: string;
status: PlanStatus;
substeps?: PlanStep[];
[key: string]: unknown;
}

export interface AgentPlanEvent {
type: 'plan';
plan: PlanStep[];
}

export interface PlanProgressSummary {
completedSteps: number;
remainingSteps: number;
totalSteps: number;
ratio: number;
}

export interface AgentPlanProgressEvent {
type: 'plan-progress';
progress: PlanProgressSummary;
}

export interface AssistantMessageEvent {
type: 'assistant-message';
message: string;
}

export interface RequestInputEvent {
type: 'request-input';
prompt: string;
metadata: Record<string, unknown>;
}

export interface SchemaValidationErrorDescriptor {
path: string;
message: string;
keyword: string;
instancePath: string;
params: Record<string, unknown>;
}

export interface SchemaValidationFailedEvent {
type: 'schema_validation_failed';
message: string;
errors: SchemaValidationErrorDescriptor[];
raw?: string;
}

export interface CommandPreview {
stdout: string;
stderr: string;
stdoutPreview: string;
stderrPreview: string;
}

export interface AgentCommand {
reason?: string;
shell?: string;
run?: string;
cwd?: string;
timeout_sec?: number;
filter_regex?: string;
tail_lines?: number;
[key: string]: unknown;
}

export interface CommandExecutionResult {
stdout?: string;
stderr?: string;
exit_code?: number | null;
runtime_ms?: number;
killed?: boolean;
[key: string]: unknown;
}

export interface CommandExecutionDetails {
type: string;
command: AgentCommand;
[key: string]: unknown;
}

export interface CommandResultEvent {
type: 'command-result';
command: AgentCommand;
result: CommandExecutionResult;
preview: CommandPreview;
execution: CommandExecutionDetails;
}

export type AgentEvent =
| AgentStatusEvent
| AgentErrorEvent
| AgentDebugEvent
| AgentBannerEvent
| AgentThinkingEvent
| AgentContextUsageEvent
| AgentPlanEvent
| AgentPlanProgressEvent
| AssistantMessageEvent
| RequestInputEvent
| SchemaValidationFailedEvent
| CommandResultEvent;

export type AgentInputEvent =
| { type: 'prompt'; prompt: string }
| { type: 'cancel'; payload?: unknown };

export interface HistoryCompactorLike {
compactIfNeeded?(options: { history: ConversationMessage[] }):
| boolean
| Promise<boolean>
| void
| Promise<void>;
}

export interface OpenAIClientLike {
responses?: {
create?: (...args: unknown[]) => Promise<unknown>;
};
[key: string]: unknown;
}

export interface AgentRuntimeOptions {
systemPrompt?: string;
systemPromptAugmentation?: string;
getClient?: () => OpenAIClientLike;
model?: string;
runCommandFn?: (
command: string,
cwd: string,
timeout: number,
shell?: string,
) => Promise<CommandExecutionResult>;
applyFilterFn?: (text: string, pattern?: string) => string;
tailLinesFn?: (text: string, lineCount?: number) => string;
isPreapprovedCommandFn?: (command: AgentCommand) => boolean | Promise<boolean>;
isSessionApprovedFn?: (command: AgentCommand) => boolean | Promise<boolean>;
approveForSessionFn?: (command: AgentCommand) => void | Promise<void>;
preapprovedCfg?: unknown;
getAutoApproveFlag?: () => boolean;
getNoHumanFlag?: () => boolean;
getPlanMergeFlag?: () => boolean;
getDebugFlag?: () => boolean;
setNoHumanFlag?: (value: boolean) => void;
emitAutoApproveStatus?: boolean;
createHistoryCompactorFn?: (context: {
openai: OpenAIClientLike;
currentModel: string;
}) => HistoryCompactorLike | null | undefined;
}

export interface AgentQueue<T> extends AsyncIterable<T> {
next(): Promise<T | undefined>;
push(value: T): boolean;
close(): void;
[Symbol.asyncIterator](): AsyncIterableIterator<T>;
}

export interface AgentRuntime {
outputs: AgentQueue<AgentEvent>;
inputs: AgentQueue<AgentInputEvent>;
start(): Promise<void>;
submitPrompt(value: string): boolean;
cancel(payload?: unknown): boolean;
}

export type AgentLoop = () => Promise<void>;

export function createAgentRuntime(options?: AgentRuntimeOptions): AgentRuntime;
export function createAgentLoop(options?: AgentRuntimeOptions): AgentLoop;

export interface OpenAgentToolCall {
name: 'open-agent';
call_id: string | null;
arguments: string;
}

export function extractOpenAgentToolCall(response: unknown): OpenAgentToolCall | null;
export function extractResponseText(response: unknown): string;

declare const _default: {
createAgentLoop: typeof createAgentLoop;
createAgentRuntime: typeof createAgentRuntime;
extractOpenAgentToolCall: typeof extractOpenAgentToolCall;
extractResponseText: typeof extractResponseText;
};

export default _default;