@sschepis/oboto-agent 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +21 -6
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/oboto-agent.ts
|
|
2
2
|
import { LScriptRuntime } from "@sschepis/lmscript";
|
|
3
3
|
import { aggregateStream } from "@sschepis/llm-wrapper";
|
|
4
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
4
5
|
import { MessageRole as MessageRole2 } from "@sschepis/as-agent";
|
|
5
6
|
|
|
6
7
|
// src/event-bus.ts
|
|
@@ -388,6 +389,7 @@ var ObotoAgent = class _ObotoAgent {
|
|
|
388
389
|
escalating: true
|
|
389
390
|
});
|
|
390
391
|
}
|
|
392
|
+
console.log("[ObotoAgent] Executing with model:", modelName, "| provider:", provider.providerName ?? "unknown");
|
|
391
393
|
await this.executeWithModel(provider, modelName, userInput);
|
|
392
394
|
}
|
|
393
395
|
async triage(userInput) {
|
|
@@ -419,13 +421,14 @@ var ObotoAgent = class _ObotoAgent {
|
|
|
419
421
|
content: typeof m.content === "string" ? m.content : m.content.filter((b) => b.type === "text").map((b) => b.text ?? "").join("\n")
|
|
420
422
|
}));
|
|
421
423
|
const tool = this.routerTool;
|
|
424
|
+
const parametersSchema = tool.parameters ? zodToJsonSchema(tool.parameters, { target: "openApi3" }) : { type: "object", properties: {} };
|
|
422
425
|
const tools = [
|
|
423
426
|
{
|
|
424
427
|
type: "function",
|
|
425
428
|
function: {
|
|
426
429
|
name: tool.name,
|
|
427
430
|
description: tool.description,
|
|
428
|
-
parameters:
|
|
431
|
+
parameters: parametersSchema
|
|
429
432
|
}
|
|
430
433
|
}
|
|
431
434
|
];
|
|
@@ -448,14 +451,26 @@ var ObotoAgent = class _ObotoAgent {
|
|
|
448
451
|
...isLastIteration ? {} : { tools, tool_choice: "auto" }
|
|
449
452
|
};
|
|
450
453
|
let response;
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
454
|
+
try {
|
|
455
|
+
if (useStreaming) {
|
|
456
|
+
response = await this.streamAndAggregate(provider, params);
|
|
457
|
+
} else {
|
|
458
|
+
response = await provider.chat(params);
|
|
459
|
+
}
|
|
460
|
+
} catch (err) {
|
|
461
|
+
console.error("[ObotoAgent] LLM call failed:", err instanceof Error ? err.message : err);
|
|
462
|
+
throw err;
|
|
455
463
|
}
|
|
456
|
-
const choice = response
|
|
464
|
+
const choice = response?.choices?.[0];
|
|
457
465
|
const content = choice?.message?.content ?? "";
|
|
458
466
|
const toolCalls = choice?.message?.tool_calls;
|
|
467
|
+
if (!choice) {
|
|
468
|
+
console.warn("[ObotoAgent] No choices in LLM response:", JSON.stringify(response).substring(0, 500));
|
|
469
|
+
} else if (!content && (!toolCalls || toolCalls.length === 0)) {
|
|
470
|
+
console.warn("[ObotoAgent] Empty response \u2014 no content, no tool_calls. finish_reason:", choice.finish_reason);
|
|
471
|
+
console.warn("[ObotoAgent] Messages sent:", messages.length, "| Model:", modelName);
|
|
472
|
+
console.warn("[ObotoAgent] Tool schema:", JSON.stringify(tools[0]?.function?.parameters).substring(0, 300));
|
|
473
|
+
}
|
|
459
474
|
if (content) {
|
|
460
475
|
this.bus.emit("agent_thought", {
|
|
461
476
|
text: content,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/oboto-agent.ts","../src/event-bus.ts","../src/context-manager.ts","../src/triage.ts","../src/adapters/tools.ts","../src/adapters/llm-wrapper.ts","../src/adapters/memory.ts"],"sourcesContent":["import { LScriptRuntime, type ToolDefinition, type ChatMessage } from \"@sschepis/lmscript\";\nimport type {\n BaseProvider,\n StandardChatParams,\n StandardChatChunk,\n Message as WrapperMessage,\n ToolCall as WrapperToolCall,\n ToolDefinition as WrapperToolDef,\n StandardChatResponse,\n} from \"@sschepis/llm-wrapper\";\nimport { aggregateStream } from \"@sschepis/llm-wrapper\";\nimport type { Session, ConversationMessage } from \"@sschepis/as-agent\";\nimport { MessageRole } from \"@sschepis/as-agent\";\nimport type { ObotoAgentConfig, AgentEventType, AgentEvent, TriageResult } from \"./types.js\";\nimport { AgentEventBus } from \"./event-bus.js\";\nimport { ContextManager } from \"./context-manager.js\";\nimport { createTriageFunction } from \"./triage.js\";\nimport { createRouterTool } from \"./adapters/tools.js\";\nimport { toLmscriptProvider } from \"./adapters/llm-wrapper.js\";\nimport { toChat, createEmptySession } from \"./adapters/memory.js\";\n\ntype EventHandler = (event: AgentEvent) => void;\n\n/**\n * ObotoAgent is the central orchestrator for dual-LLM agent execution.\n *\n * It binds together:\n * - llm-wrapper (LLM communication via local and remote providers)\n * - lmscript (structured/schema-validated calls for triage)\n * - swiss-army-tool (tool execution via Router)\n * - as-agent (session state and conversation history)\n *\n * All interaction flows through an event-driven architecture.\n */\nexport class ObotoAgent {\n private bus = new AgentEventBus();\n private localRuntime: LScriptRuntime;\n private localProvider: BaseProvider;\n private remoteProvider: BaseProvider;\n private contextManager: ContextManager;\n private routerTool: ToolDefinition<any, any>;\n private triageFn: ReturnType<typeof createTriageFunction>;\n private session: Session;\n private isProcessing = false;\n private interrupted = false;\n private systemPrompt: string;\n private maxIterations: number;\n private config: ObotoAgentConfig;\n private onToken?: (token: string) => void;\n\n constructor(config: ObotoAgentConfig) {\n this.config = config;\n this.localProvider = config.localModel;\n this.remoteProvider = config.remoteModel;\n\n // Wrap llm-wrapper providers into lmscript LLMProvider for structured calls (triage)\n const localLmscript = toLmscriptProvider(config.localModel, \"local\");\n this.localRuntime = new LScriptRuntime({ provider: localLmscript });\n\n this.session = config.session ?? createEmptySession();\n this.systemPrompt = config.systemPrompt ?? \"You are a helpful AI assistant with access to tools.\";\n this.maxIterations = config.maxIterations ?? 10;\n this.onToken = config.onToken;\n\n this.contextManager = new ContextManager(\n this.localRuntime,\n config.localModelName,\n config.maxContextTokens ?? 8192\n );\n\n this.routerTool = createRouterTool(config.router);\n this.triageFn = createTriageFunction(config.localModelName);\n\n // Push system prompt into context\n this.contextManager.push({\n role: \"system\",\n content: this.systemPrompt,\n });\n }\n\n // ── Public API ─────────────────────────────────────────────────────\n\n /** Subscribe to agent events. Returns an unsubscribe function. */\n on(type: AgentEventType, handler: EventHandler): () => void {\n return this.bus.on(type, handler);\n }\n\n /** Subscribe to an event for a single emission. */\n once(type: AgentEventType, handler: EventHandler): () => void {\n return this.bus.once(type, handler);\n }\n\n /** Submit user input to the agent. Triggers the execution loop. */\n async submitInput(text: string): Promise<void> {\n if (this.isProcessing) {\n this.interrupt(text);\n return;\n }\n\n this.isProcessing = true;\n this.interrupted = false;\n\n try {\n await this.executionLoop(text);\n } catch (err) {\n this.bus.emit(\"error\", {\n message: err instanceof Error ? err.message : String(err),\n error: err,\n });\n } finally {\n this.isProcessing = false;\n }\n }\n\n /**\n * Interrupt the current execution loop.\n * Optionally inject new directives into the context.\n */\n interrupt(newDirectives?: string): void {\n this.interrupted = true;\n this.bus.emit(\"interruption\", { newDirectives });\n\n if (newDirectives) {\n const msg: ConversationMessage = {\n role: MessageRole.User,\n blocks: [{ kind: \"text\", text: `[INTERRUPTION] ${newDirectives}` }],\n };\n this.session.messages.push(msg);\n this.contextManager.push(toChat(msg));\n this.bus.emit(\"state_updated\", { reason: \"interruption\" });\n }\n }\n\n /** Get the current session state. */\n getSession(): Session {\n return this.session;\n }\n\n /** Whether the agent is currently processing input. */\n get processing(): boolean {\n return this.isProcessing;\n }\n\n /** Remove all event listeners. */\n removeAllListeners(): void {\n this.bus.removeAllListeners();\n }\n\n // ── Internal ───────────────────────────────────────────────────────\n\n private async executionLoop(userInput: string): Promise<void> {\n // 1. Emit user_input and record in session + context\n this.bus.emit(\"user_input\", { text: userInput });\n\n const userMsg: ConversationMessage = {\n role: MessageRole.User,\n blocks: [{ kind: \"text\", text: userInput }],\n };\n this.session.messages.push(userMsg);\n await this.contextManager.push(toChat(userMsg));\n this.bus.emit(\"state_updated\", { reason: \"user_input\" });\n\n // 2. Triage via local LLM (uses lmscript for structured output)\n const triageResult = await this.triage(userInput);\n this.bus.emit(\"triage_result\", triageResult);\n\n if (this.interrupted) return;\n\n // 3. If local can handle directly, emit and return\n if (!triageResult.escalate && triageResult.directResponse) {\n const response = triageResult.directResponse;\n this.bus.emit(\"agent_thought\", { text: response, model: \"local\" });\n\n const assistantMsg: ConversationMessage = {\n role: MessageRole.Assistant,\n blocks: [{ kind: \"text\", text: response }],\n };\n this.session.messages.push(assistantMsg);\n await this.contextManager.push(toChat(assistantMsg));\n this.bus.emit(\"state_updated\", { reason: \"assistant_response\" });\n this.bus.emit(\"turn_complete\", { model: \"local\", escalated: false });\n return;\n }\n\n // 4. Escalate to remote model with tool access\n const provider = triageResult.escalate ? this.remoteProvider : this.localProvider;\n const modelName = triageResult.escalate\n ? this.config.remoteModelName\n : this.config.localModelName;\n\n if (triageResult.escalate) {\n this.bus.emit(\"agent_thought\", {\n text: triageResult.reasoning,\n model: \"local\",\n escalating: true,\n });\n }\n\n await this.executeWithModel(provider, modelName, userInput);\n }\n\n private async triage(userInput: string): Promise<TriageResult> {\n const recentMessages = this.contextManager.getMessages().slice(-5);\n const recentContext = recentMessages\n .map((m) => {\n const text = typeof m.content === \"string\" ? m.content : \"[complex content]\";\n return `${m.role}: ${text}`;\n })\n .join(\"\\n\");\n\n const result = await this.localRuntime.execute(this.triageFn, {\n userInput,\n recentContext,\n availableTools: this.routerTool.description,\n });\n\n return result.data;\n }\n\n /** Maximum characters per tool result before truncation. */\n private static readonly MAX_TOOL_RESULT_CHARS = 8000;\n\n /** Maximum times the same tool+args can repeat before forcing a text response. */\n private static readonly MAX_DUPLICATE_CALLS = 2;\n\n /**\n * Execute the agent loop using llm-wrapper directly.\n * When onToken is configured, uses streaming for real-time token output.\n * No JSON mode, no schema enforcement — just natural chat with tool calling.\n */\n private async executeWithModel(\n provider: BaseProvider,\n modelName: string,\n _userInput: string\n ): Promise<void> {\n const contextMessages = this.contextManager.getMessages();\n\n // Convert lmscript ChatMessages → llm-wrapper Messages\n const messages: WrapperMessage[] = contextMessages.map((m) => ({\n role: m.role,\n content:\n typeof m.content === \"string\"\n ? m.content\n : (m.content as Array<{ type: string; text?: string }>)\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\\n\"),\n }));\n\n const tool = this.routerTool;\n const tools: WrapperToolDef[] = [\n {\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters\n ? JSON.parse(JSON.stringify(tool.parameters))\n : { type: \"object\", properties: {} },\n },\n },\n ];\n\n let totalToolCalls = 0;\n const callHistory: string[] = [];\n const useStreaming = !!this.onToken;\n\n for (let iteration = 1; iteration <= this.maxIterations; iteration++) {\n if (this.interrupted) break;\n\n const isLastIteration = iteration === this.maxIterations;\n\n if (isLastIteration) {\n messages.push({\n role: \"user\",\n content:\n \"You have used all available tool iterations. Please provide your final response now based on what you have gathered so far. Do not call any more tools.\",\n });\n }\n\n const params: StandardChatParams = {\n model: modelName,\n messages: [...messages],\n temperature: 0.7,\n ...(isLastIteration\n ? {}\n : { tools, tool_choice: \"auto\" as const }),\n };\n\n // Call LLM — streaming or non-streaming\n let response: StandardChatResponse;\n if (useStreaming) {\n response = await this.streamAndAggregate(provider, params);\n } else {\n response = await provider.chat(params);\n }\n\n const choice = response.choices[0];\n const content = (choice?.message?.content as string) ?? \"\";\n const toolCalls = choice?.message?.tool_calls;\n\n // Emit thought (the full text for this iteration)\n if (content) {\n this.bus.emit(\"agent_thought\", {\n text: content,\n model: modelName,\n iteration,\n });\n }\n\n // If no tool calls, this is the final response\n if (!toolCalls || toolCalls.length === 0) {\n const assistantMsg: ConversationMessage = {\n role: MessageRole.Assistant,\n blocks: [{ kind: \"text\", text: content }],\n };\n this.session.messages.push(assistantMsg);\n await this.contextManager.push(toChat(assistantMsg));\n this.bus.emit(\"state_updated\", { reason: \"assistant_response\" });\n this.bus.emit(\"turn_complete\", {\n model: modelName,\n escalated: true,\n iterations: iteration,\n toolCalls: totalToolCalls,\n });\n return;\n }\n\n // Append assistant message (with tool_calls) to conversation\n messages.push({\n role: \"assistant\",\n content: content || null,\n tool_calls: toolCalls,\n });\n\n // Execute each tool call\n const toolResults: Array<{ command: string; success: boolean }> = [];\n\n for (const tc of toolCalls) {\n if (this.interrupted) break;\n\n let args: Record<string, unknown>;\n try {\n args = JSON.parse(tc.function.arguments);\n } catch {\n args = {};\n }\n\n const command = (args.command as string) ?? tc.function.name;\n const kwargs = (args.kwargs as Record<string, unknown>) ?? {};\n\n // Detect duplicate tool calls\n const callSig = JSON.stringify({ command, kwargs });\n const dupeCount = callHistory.filter((s) => s === callSig).length;\n callHistory.push(callSig);\n\n if (dupeCount >= ObotoAgent.MAX_DUPLICATE_CALLS) {\n messages.push({\n role: \"tool\",\n tool_call_id: tc.id,\n content: `You already called \"${command}\" with these arguments ${dupeCount} time(s) and received the result. Do not repeat this call. Use the data you already have to proceed.`,\n });\n this.bus.emit(\"tool_execution_complete\", {\n command,\n kwargs,\n result: \"[duplicate call blocked]\",\n });\n toolResults.push({ command, success: false });\n totalToolCalls++;\n continue;\n }\n\n this.bus.emit(\"tool_execution_start\", { command, kwargs });\n\n let result: string;\n let success = true;\n try {\n result = await tool.execute(args);\n } catch (err) {\n result = `Error: ${err instanceof Error ? err.message : String(err)}`;\n success = false;\n }\n\n // Truncate large results\n const resultStr = typeof result === \"string\" ? result : JSON.stringify(result);\n const truncated =\n resultStr.length > ObotoAgent.MAX_TOOL_RESULT_CHARS\n ? resultStr.slice(0, ObotoAgent.MAX_TOOL_RESULT_CHARS) +\n `\\n\\n[... truncated ${resultStr.length - ObotoAgent.MAX_TOOL_RESULT_CHARS} characters. Use the data above to proceed.]`\n : resultStr;\n\n this.bus.emit(\"tool_execution_complete\", { command, kwargs, result: truncated });\n toolResults.push({ command, success });\n totalToolCalls++;\n\n messages.push({\n role: \"tool\",\n tool_call_id: tc.id,\n content: truncated,\n });\n }\n\n // Emit tool round summary\n this.bus.emit(\"tool_round_complete\", {\n iteration,\n tools: toolResults,\n totalToolCalls,\n });\n }\n\n // Exhausted iterations fallback\n const fallbackMsg: ConversationMessage = {\n role: MessageRole.Assistant,\n blocks: [{ kind: \"text\", text: \"I reached the maximum number of iterations. Here is what I have so far.\" }],\n };\n this.session.messages.push(fallbackMsg);\n await this.contextManager.push(toChat(fallbackMsg));\n this.bus.emit(\"state_updated\", { reason: \"max_iterations\" });\n this.bus.emit(\"turn_complete\", {\n model: modelName,\n escalated: true,\n iterations: this.maxIterations,\n toolCalls: totalToolCalls,\n });\n }\n\n /**\n * Stream an LLM call, emitting tokens in real-time, then aggregate into\n * a full StandardChatResponse (including accumulated tool calls).\n */\n private async streamAndAggregate(\n provider: BaseProvider,\n params: StandardChatParams\n ): Promise<StandardChatResponse> {\n const stream = provider.stream({ ...params, stream: true });\n\n // Collect chunks while emitting tokens\n const chunks: StandardChatChunk[] = [];\n for await (const chunk of stream) {\n chunks.push(chunk);\n\n // Emit text tokens in real-time\n const delta = chunk.choices?.[0]?.delta;\n if (delta?.content) {\n this.onToken!(delta.content);\n this.bus.emit(\"token\", { text: delta.content });\n }\n }\n\n // Replay collected chunks through aggregateStream to build full response\n async function* replay(): AsyncIterable<StandardChatChunk> {\n for (const c of chunks) yield c;\n }\n return aggregateStream(replay());\n }\n}\n","import type { AgentEventType, AgentEvent } from \"./types.js\";\n\ntype EventHandler = (event: AgentEvent) => void;\n\n/**\n * Platform-agnostic typed event bus.\n * Uses a plain Map instead of Node.js EventEmitter for browser/Deno/Bun compatibility.\n */\nexport class AgentEventBus {\n private listeners = new Map<AgentEventType, Set<EventHandler>>();\n\n /** Subscribe to an event type. Returns an unsubscribe function. */\n on(type: AgentEventType, handler: EventHandler): () => void {\n if (!this.listeners.has(type)) {\n this.listeners.set(type, new Set());\n }\n this.listeners.get(type)!.add(handler);\n return () => this.off(type, handler);\n }\n\n /** Unsubscribe a handler from an event type. */\n off(type: AgentEventType, handler: EventHandler): void {\n this.listeners.get(type)?.delete(handler);\n }\n\n /** Subscribe to an event type for a single emission. */\n once(type: AgentEventType, handler: EventHandler): () => void {\n const wrapper: EventHandler = (event) => {\n this.off(type, wrapper);\n handler(event);\n };\n return this.on(type, wrapper);\n }\n\n /** Emit an event to all subscribers. */\n emit(type: AgentEventType, payload: unknown): void {\n const event: AgentEvent = {\n type,\n payload,\n timestamp: Date.now(),\n };\n const handlers = this.listeners.get(type);\n if (handlers) {\n for (const handler of handlers) {\n handler(event);\n }\n }\n }\n\n /** Remove all listeners for all event types. */\n removeAllListeners(): void {\n this.listeners.clear();\n }\n}\n","import { z } from \"zod\";\nimport { ContextStack, type LScriptRuntime, type ChatMessage, type LScriptFunction } from \"@sschepis/lmscript\";\n\nconst SummarySchema = z.object({\n summary: z.string().describe(\"A dense summary of the conversation so far\"),\n});\n\ntype SummaryInput = { conversation: string };\n\n/**\n * Manages the sliding context window with automatic summarization.\n * Wraps lmscript's ContextStack and uses the local LLM for compression.\n */\nexport class ContextManager {\n private stack: ContextStack;\n private summarizeFn: LScriptFunction<SummaryInput, typeof SummarySchema>;\n\n constructor(\n private localRuntime: LScriptRuntime,\n localModelName: string,\n maxTokens: number\n ) {\n this.stack = new ContextStack({\n maxTokens,\n pruneStrategy: \"summarize\",\n });\n\n this.summarizeFn = {\n name: \"summarize_context\",\n model: localModelName,\n system:\n \"You are a summarization engine. Compress the given conversation into a dense, factual summary that preserves all key information, decisions, and context needed for continued operation. Be concise but thorough.\",\n prompt: ({ conversation }) => conversation,\n schema: SummarySchema,\n temperature: 0.2,\n maxRetries: 1,\n };\n\n this.stack.setSummarizer(async (messages: ChatMessage[]) => {\n const conversation = messages\n .map((m) => {\n const text =\n typeof m.content === \"string\"\n ? m.content\n : m.content\n .filter((b) => b.type === \"text\")\n .map((b) => (b as { text: string }).text)\n .join(\" \");\n return `${m.role}: ${text}`;\n })\n .join(\"\\n\");\n\n const result = await this.localRuntime.execute(this.summarizeFn, {\n conversation,\n });\n return result.data.summary;\n });\n }\n\n /** Append a message to the context. Triggers pruning if over budget. */\n async push(message: ChatMessage): Promise<void> {\n await this.stack.push(message);\n }\n\n /** Append multiple messages. */\n async pushAll(messages: ChatMessage[]): Promise<void> {\n await this.stack.pushAll(messages);\n }\n\n /** Get all messages in the current context window. */\n getMessages(): ChatMessage[] {\n return this.stack.getMessages();\n }\n\n /** Get estimated token count. */\n getTokenCount(): number {\n return this.stack.getTokenCount();\n }\n\n /** Clear all context. */\n clear(): void {\n this.stack.clear();\n }\n}\n","import { z } from \"zod\";\nimport type { LScriptFunction } from \"@sschepis/lmscript\";\n\n/** Zod schema for structured triage output. */\nexport const TriageSchema = z.object({\n escalate: z\n .boolean()\n .describe(\"True if the request needs a powerful model, false if answerable directly\"),\n reasoning: z\n .string()\n .describe(\"Brief explanation of the triage decision\"),\n directResponse: z\n .string()\n .optional()\n .describe(\"Direct answer if the request can be handled without escalation\"),\n});\n\nexport type TriageInput = {\n userInput: string;\n recentContext: string;\n availableTools: string;\n};\n\nconst TRIAGE_SYSTEM = `You are a fast triage classifier for an AI agent system.\nYour job is to decide whether a user's request can be answered directly (simple queries,\ncasual chat, short lookups) or needs to be escalated to a more powerful model\n(complex reasoning, multi-step tool usage, code generation, analysis).\n\nRules:\n- If the request is a greeting, simple question, or casual conversation: respond directly.\n- If the request needs tool calls, code analysis, or multi-step reasoning: escalate.\n- If unsure, escalate. It's better to over-escalate than to give a poor direct answer.\n- Keep directResponse under 200 words when answering directly.\n\nRespond with JSON matching the schema.`;\n\n/**\n * Create an LScriptFunction for local-LLM triage classification.\n * The local model evaluates whether input needs escalation to the remote model.\n */\nexport function createTriageFunction(\n modelName: string\n): LScriptFunction<TriageInput, typeof TriageSchema> {\n return {\n name: \"triage\",\n model: modelName,\n system: TRIAGE_SYSTEM,\n prompt: ({ userInput, recentContext, availableTools }) =>\n `Recent context:\\n${recentContext}\\n\\nAvailable tools: ${availableTools}\\n\\nUser: ${userInput}`,\n schema: TriageSchema,\n temperature: 0.1,\n maxRetries: 1,\n };\n}\n","import { z } from \"zod\";\nimport type { Router } from \"@sschepis/swiss-army-tool\";\nimport { generateToolSchema } from \"@sschepis/swiss-army-tool\";\nimport type { ToolDefinition } from \"@sschepis/lmscript\";\nimport type { BranchNode } from \"@sschepis/swiss-army-tool\";\n\n/** Parameter schema for the omni-tool bridge. */\nconst RouterToolParams = z.object({\n command: z.string().describe(\n \"The command or menu path (e.g., 'help', 'filesystem read', 'db query')\"\n ),\n kwargs: z\n .record(z.unknown())\n .optional()\n .default({})\n .describe(\"Key-value arguments for the command\"),\n});\n\n/**\n * Bridge a swiss-army-tool Router into an lmscript ToolDefinition.\n *\n * The LLM sees a single tool (\"terminal_interface\") with `command` and `kwargs`\n * parameters. When called, it routes through the swiss-army-tool command tree.\n */\nexport function createRouterTool(\n router: Router,\n root?: BranchNode\n): ToolDefinition<typeof RouterToolParams, string> {\n const schema = generateToolSchema({ root });\n\n return {\n name: schema.name,\n description: schema.description,\n parameters: RouterToolParams,\n execute: async (params) => {\n return router.execute(params.command, params.kwargs ?? {});\n },\n };\n}\n","import type { LLMProvider, LLMRequest, LLMResponse } from \"@sschepis/lmscript\";\nimport type {\n BaseProvider,\n StandardChatParams,\n Message,\n ToolDefinition as WrapperToolDef,\n} from \"@sschepis/llm-wrapper\";\n\n/**\n * Adapt a llm-wrapper BaseProvider into lmscript's LLMProvider interface.\n *\n * This allows lmscript's LScriptRuntime to use llm-wrapper providers for\n * structured calls (e.g. triage) that need schema validation.\n */\nexport function toLmscriptProvider(\n provider: BaseProvider,\n name?: string\n): LLMProvider {\n return {\n name: name ?? provider.providerName,\n\n async chat(request: LLMRequest): Promise<LLMResponse> {\n // Convert lmscript messages → llm-wrapper messages\n const messages: Message[] = request.messages.map((m) => ({\n role: m.role,\n content:\n typeof m.content === \"string\"\n ? m.content\n : m.content\n .filter((b) => b.type === \"text\")\n .map((b) => (b as { type: \"text\"; text: string }).text)\n .join(\"\\n\"),\n }));\n\n // Convert lmscript tools → llm-wrapper tool definitions\n let tools: WrapperToolDef[] | undefined;\n if (request.tools && request.tools.length > 0) {\n tools = request.tools.map((t) => ({\n type: \"function\" as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameters as Record<string, unknown>,\n },\n }));\n }\n\n const params: StandardChatParams = {\n model: request.model,\n messages,\n temperature: request.temperature,\n ...(tools ? { tools } : {}),\n ...(request.jsonMode\n ? { response_format: { type: \"json_object\" as const } }\n : {}),\n };\n\n const response = await provider.chat(params);\n const choice = response.choices[0];\n\n // Convert tool calls back to lmscript format\n let toolCalls: LLMResponse[\"toolCalls\"];\n if (choice?.message?.tool_calls) {\n toolCalls = choice.message.tool_calls.map((tc) => ({\n id: tc.id,\n name: tc.function.name,\n arguments: tc.function.arguments,\n }));\n }\n\n return {\n content: (choice?.message?.content as string) ?? \"\",\n usage: response.usage\n ? {\n promptTokens: response.usage.prompt_tokens,\n completionTokens: response.usage.completion_tokens,\n totalTokens: response.usage.total_tokens,\n }\n : undefined,\n toolCalls,\n };\n },\n };\n}\n","import {\n MessageRole,\n type ConversationMessage,\n type ContentBlock as AsContentBlock,\n type Session,\n} from \"@sschepis/as-agent\";\nimport type { ChatMessage, Role } from \"@sschepis/lmscript\";\n\nconst ROLE_TO_STRING: Record<MessageRole, Role> = {\n [MessageRole.System]: \"system\",\n [MessageRole.User]: \"user\",\n [MessageRole.Assistant]: \"assistant\",\n [MessageRole.Tool]: \"user\",\n};\n\nconst STRING_TO_ROLE: Record<Role, MessageRole> = {\n system: MessageRole.System,\n user: MessageRole.User,\n assistant: MessageRole.Assistant,\n};\n\n/** Extract plain text from as-agent content blocks. */\nfunction blocksToText(blocks: AsContentBlock[]): string {\n return blocks\n .map((b) => {\n switch (b.kind) {\n case \"text\":\n return b.text;\n case \"tool_use\":\n return `[Tool call: ${b.name}(${b.input})]`;\n case \"tool_result\":\n return b.isError\n ? `[Tool error (${b.toolName}): ${b.output}]`\n : `[Tool result (${b.toolName}): ${b.output}]`;\n }\n })\n .join(\"\\n\");\n}\n\n/** Convert an as-agent ConversationMessage to an lmscript ChatMessage. */\nexport function toChat(msg: ConversationMessage): ChatMessage {\n return {\n role: ROLE_TO_STRING[msg.role] ?? \"user\",\n content: blocksToText(msg.blocks),\n };\n}\n\n/** Convert an lmscript ChatMessage to an as-agent ConversationMessage. */\nexport function fromChat(msg: ChatMessage): ConversationMessage {\n const text = typeof msg.content === \"string\"\n ? msg.content\n : msg.content\n .filter((b) => b.type === \"text\")\n .map((b) => (b as { text: string }).text)\n .join(\"\\n\");\n\n return {\n role: STRING_TO_ROLE[msg.role] ?? MessageRole.User,\n blocks: [{ kind: \"text\", text }],\n };\n}\n\n/** Convert an entire as-agent Session to an array of lmscript ChatMessages. */\nexport function sessionToHistory(session: Session): ChatMessage[] {\n return session.messages.map(toChat);\n}\n\n/** Create an empty as-agent Session. */\nexport function createEmptySession(): Session {\n return { version: 1, messages: [] };\n}\n"],"mappings":"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","names":["MessageRole","z","z","MessageRole"]}
|
|
1
|
+
{"version":3,"sources":["../src/oboto-agent.ts","../src/event-bus.ts","../src/context-manager.ts","../src/triage.ts","../src/adapters/tools.ts","../src/adapters/llm-wrapper.ts","../src/adapters/memory.ts"],"sourcesContent":["import { LScriptRuntime, type ToolDefinition, type ChatMessage } from \"@sschepis/lmscript\";\nimport type {\n BaseProvider,\n StandardChatParams,\n StandardChatChunk,\n Message as WrapperMessage,\n ToolCall as WrapperToolCall,\n ToolDefinition as WrapperToolDef,\n StandardChatResponse,\n} from \"@sschepis/llm-wrapper\";\nimport { aggregateStream } from \"@sschepis/llm-wrapper\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport type { Session, ConversationMessage } from \"@sschepis/as-agent\";\nimport { MessageRole } from \"@sschepis/as-agent\";\nimport type { ObotoAgentConfig, AgentEventType, AgentEvent, TriageResult } from \"./types.js\";\nimport { AgentEventBus } from \"./event-bus.js\";\nimport { ContextManager } from \"./context-manager.js\";\nimport { createTriageFunction } from \"./triage.js\";\nimport { createRouterTool } from \"./adapters/tools.js\";\nimport { toLmscriptProvider } from \"./adapters/llm-wrapper.js\";\nimport { toChat, createEmptySession } from \"./adapters/memory.js\";\n\ntype EventHandler = (event: AgentEvent) => void;\n\n/**\n * ObotoAgent is the central orchestrator for dual-LLM agent execution.\n *\n * It binds together:\n * - llm-wrapper (LLM communication via local and remote providers)\n * - lmscript (structured/schema-validated calls for triage)\n * - swiss-army-tool (tool execution via Router)\n * - as-agent (session state and conversation history)\n *\n * All interaction flows through an event-driven architecture.\n */\nexport class ObotoAgent {\n private bus = new AgentEventBus();\n private localRuntime: LScriptRuntime;\n private localProvider: BaseProvider;\n private remoteProvider: BaseProvider;\n private contextManager: ContextManager;\n private routerTool: ToolDefinition<any, any>;\n private triageFn: ReturnType<typeof createTriageFunction>;\n private session: Session;\n private isProcessing = false;\n private interrupted = false;\n private systemPrompt: string;\n private maxIterations: number;\n private config: ObotoAgentConfig;\n private onToken?: (token: string) => void;\n\n constructor(config: ObotoAgentConfig) {\n this.config = config;\n this.localProvider = config.localModel;\n this.remoteProvider = config.remoteModel;\n\n // Wrap llm-wrapper providers into lmscript LLMProvider for structured calls (triage)\n const localLmscript = toLmscriptProvider(config.localModel, \"local\");\n this.localRuntime = new LScriptRuntime({ provider: localLmscript });\n\n this.session = config.session ?? createEmptySession();\n this.systemPrompt = config.systemPrompt ?? \"You are a helpful AI assistant with access to tools.\";\n this.maxIterations = config.maxIterations ?? 10;\n this.onToken = config.onToken;\n\n this.contextManager = new ContextManager(\n this.localRuntime,\n config.localModelName,\n config.maxContextTokens ?? 8192\n );\n\n this.routerTool = createRouterTool(config.router);\n this.triageFn = createTriageFunction(config.localModelName);\n\n // Push system prompt into context\n this.contextManager.push({\n role: \"system\",\n content: this.systemPrompt,\n });\n }\n\n // ── Public API ─────────────────────────────────────────────────────\n\n /** Subscribe to agent events. Returns an unsubscribe function. */\n on(type: AgentEventType, handler: EventHandler): () => void {\n return this.bus.on(type, handler);\n }\n\n /** Subscribe to an event for a single emission. */\n once(type: AgentEventType, handler: EventHandler): () => void {\n return this.bus.once(type, handler);\n }\n\n /** Submit user input to the agent. Triggers the execution loop. */\n async submitInput(text: string): Promise<void> {\n if (this.isProcessing) {\n this.interrupt(text);\n return;\n }\n\n this.isProcessing = true;\n this.interrupted = false;\n\n try {\n await this.executionLoop(text);\n } catch (err) {\n this.bus.emit(\"error\", {\n message: err instanceof Error ? err.message : String(err),\n error: err,\n });\n } finally {\n this.isProcessing = false;\n }\n }\n\n /**\n * Interrupt the current execution loop.\n * Optionally inject new directives into the context.\n */\n interrupt(newDirectives?: string): void {\n this.interrupted = true;\n this.bus.emit(\"interruption\", { newDirectives });\n\n if (newDirectives) {\n const msg: ConversationMessage = {\n role: MessageRole.User,\n blocks: [{ kind: \"text\", text: `[INTERRUPTION] ${newDirectives}` }],\n };\n this.session.messages.push(msg);\n this.contextManager.push(toChat(msg));\n this.bus.emit(\"state_updated\", { reason: \"interruption\" });\n }\n }\n\n /** Get the current session state. */\n getSession(): Session {\n return this.session;\n }\n\n /** Whether the agent is currently processing input. */\n get processing(): boolean {\n return this.isProcessing;\n }\n\n /** Remove all event listeners. */\n removeAllListeners(): void {\n this.bus.removeAllListeners();\n }\n\n // ── Internal ───────────────────────────────────────────────────────\n\n private async executionLoop(userInput: string): Promise<void> {\n // 1. Emit user_input and record in session + context\n this.bus.emit(\"user_input\", { text: userInput });\n\n const userMsg: ConversationMessage = {\n role: MessageRole.User,\n blocks: [{ kind: \"text\", text: userInput }],\n };\n this.session.messages.push(userMsg);\n await this.contextManager.push(toChat(userMsg));\n this.bus.emit(\"state_updated\", { reason: \"user_input\" });\n\n // 2. Triage via local LLM (uses lmscript for structured output)\n const triageResult = await this.triage(userInput);\n this.bus.emit(\"triage_result\", triageResult);\n\n if (this.interrupted) return;\n\n // 3. If local can handle directly, emit and return\n if (!triageResult.escalate && triageResult.directResponse) {\n const response = triageResult.directResponse;\n this.bus.emit(\"agent_thought\", { text: response, model: \"local\" });\n\n const assistantMsg: ConversationMessage = {\n role: MessageRole.Assistant,\n blocks: [{ kind: \"text\", text: response }],\n };\n this.session.messages.push(assistantMsg);\n await this.contextManager.push(toChat(assistantMsg));\n this.bus.emit(\"state_updated\", { reason: \"assistant_response\" });\n this.bus.emit(\"turn_complete\", { model: \"local\", escalated: false });\n return;\n }\n\n // 4. Escalate to remote model with tool access\n const provider = triageResult.escalate ? this.remoteProvider : this.localProvider;\n const modelName = triageResult.escalate\n ? this.config.remoteModelName\n : this.config.localModelName;\n\n if (triageResult.escalate) {\n this.bus.emit(\"agent_thought\", {\n text: triageResult.reasoning,\n model: \"local\",\n escalating: true,\n });\n }\n\n console.log(\"[ObotoAgent] Executing with model:\", modelName, \"| provider:\", provider.providerName ?? \"unknown\");\n await this.executeWithModel(provider, modelName, userInput);\n }\n\n private async triage(userInput: string): Promise<TriageResult> {\n const recentMessages = this.contextManager.getMessages().slice(-5);\n const recentContext = recentMessages\n .map((m) => {\n const text = typeof m.content === \"string\" ? m.content : \"[complex content]\";\n return `${m.role}: ${text}`;\n })\n .join(\"\\n\");\n\n const result = await this.localRuntime.execute(this.triageFn, {\n userInput,\n recentContext,\n availableTools: this.routerTool.description,\n });\n\n return result.data;\n }\n\n /** Maximum characters per tool result before truncation. */\n private static readonly MAX_TOOL_RESULT_CHARS = 8000;\n\n /** Maximum times the same tool+args can repeat before forcing a text response. */\n private static readonly MAX_DUPLICATE_CALLS = 2;\n\n /**\n * Execute the agent loop using llm-wrapper directly.\n * When onToken is configured, uses streaming for real-time token output.\n * No JSON mode, no schema enforcement — just natural chat with tool calling.\n */\n private async executeWithModel(\n provider: BaseProvider,\n modelName: string,\n _userInput: string\n ): Promise<void> {\n const contextMessages = this.contextManager.getMessages();\n\n // Convert lmscript ChatMessages → llm-wrapper Messages\n const messages: WrapperMessage[] = contextMessages.map((m) => ({\n role: m.role,\n content:\n typeof m.content === \"string\"\n ? m.content\n : (m.content as Array<{ type: string; text?: string }>)\n .filter((b) => b.type === \"text\")\n .map((b) => b.text ?? \"\")\n .join(\"\\n\"),\n }));\n\n const tool = this.routerTool;\n // Convert Zod schema → JSON Schema for the LLM\n const parametersSchema = tool.parameters\n ? (zodToJsonSchema(tool.parameters, { target: \"openApi3\" }) as Record<string, unknown>)\n : { type: \"object\", properties: {} };\n const tools: WrapperToolDef[] = [\n {\n type: \"function\",\n function: {\n name: tool.name,\n description: tool.description,\n parameters: parametersSchema,\n },\n },\n ];\n\n let totalToolCalls = 0;\n const callHistory: string[] = [];\n const useStreaming = !!this.onToken;\n\n for (let iteration = 1; iteration <= this.maxIterations; iteration++) {\n if (this.interrupted) break;\n\n const isLastIteration = iteration === this.maxIterations;\n\n if (isLastIteration) {\n messages.push({\n role: \"user\",\n content:\n \"You have used all available tool iterations. Please provide your final response now based on what you have gathered so far. Do not call any more tools.\",\n });\n }\n\n const params: StandardChatParams = {\n model: modelName,\n messages: [...messages],\n temperature: 0.7,\n ...(isLastIteration\n ? {}\n : { tools, tool_choice: \"auto\" as const }),\n };\n\n // Call LLM — streaming or non-streaming\n let response: StandardChatResponse;\n try {\n if (useStreaming) {\n response = await this.streamAndAggregate(provider, params);\n } else {\n response = await provider.chat(params);\n }\n } catch (err) {\n // Log and re-throw so submitInput's catch can emit the error event\n console.error(\"[ObotoAgent] LLM call failed:\", err instanceof Error ? err.message : err);\n throw err;\n }\n\n const choice = response?.choices?.[0];\n const content = (choice?.message?.content as string) ?? \"\";\n const toolCalls = choice?.message?.tool_calls;\n\n // Diagnostic: log if response looks wrong\n if (!choice) {\n console.warn(\"[ObotoAgent] No choices in LLM response:\", JSON.stringify(response).substring(0, 500));\n } else if (!content && (!toolCalls || toolCalls.length === 0)) {\n console.warn(\"[ObotoAgent] Empty response — no content, no tool_calls. finish_reason:\", choice.finish_reason);\n console.warn(\"[ObotoAgent] Messages sent:\", messages.length, \"| Model:\", modelName);\n console.warn(\"[ObotoAgent] Tool schema:\", JSON.stringify(tools[0]?.function?.parameters).substring(0, 300));\n }\n\n // Emit thought (the full text for this iteration)\n if (content) {\n this.bus.emit(\"agent_thought\", {\n text: content,\n model: modelName,\n iteration,\n });\n }\n\n // If no tool calls, this is the final response\n if (!toolCalls || toolCalls.length === 0) {\n const assistantMsg: ConversationMessage = {\n role: MessageRole.Assistant,\n blocks: [{ kind: \"text\", text: content }],\n };\n this.session.messages.push(assistantMsg);\n await this.contextManager.push(toChat(assistantMsg));\n this.bus.emit(\"state_updated\", { reason: \"assistant_response\" });\n this.bus.emit(\"turn_complete\", {\n model: modelName,\n escalated: true,\n iterations: iteration,\n toolCalls: totalToolCalls,\n });\n return;\n }\n\n // Append assistant message (with tool_calls) to conversation\n messages.push({\n role: \"assistant\",\n content: content || null,\n tool_calls: toolCalls,\n });\n\n // Execute each tool call\n const toolResults: Array<{ command: string; success: boolean }> = [];\n\n for (const tc of toolCalls) {\n if (this.interrupted) break;\n\n let args: Record<string, unknown>;\n try {\n args = JSON.parse(tc.function.arguments);\n } catch {\n args = {};\n }\n\n const command = (args.command as string) ?? tc.function.name;\n const kwargs = (args.kwargs as Record<string, unknown>) ?? {};\n\n // Detect duplicate tool calls\n const callSig = JSON.stringify({ command, kwargs });\n const dupeCount = callHistory.filter((s) => s === callSig).length;\n callHistory.push(callSig);\n\n if (dupeCount >= ObotoAgent.MAX_DUPLICATE_CALLS) {\n messages.push({\n role: \"tool\",\n tool_call_id: tc.id,\n content: `You already called \"${command}\" with these arguments ${dupeCount} time(s) and received the result. Do not repeat this call. Use the data you already have to proceed.`,\n });\n this.bus.emit(\"tool_execution_complete\", {\n command,\n kwargs,\n result: \"[duplicate call blocked]\",\n });\n toolResults.push({ command, success: false });\n totalToolCalls++;\n continue;\n }\n\n this.bus.emit(\"tool_execution_start\", { command, kwargs });\n\n let result: string;\n let success = true;\n try {\n result = await tool.execute(args);\n } catch (err) {\n result = `Error: ${err instanceof Error ? err.message : String(err)}`;\n success = false;\n }\n\n // Truncate large results\n const resultStr = typeof result === \"string\" ? result : JSON.stringify(result);\n const truncated =\n resultStr.length > ObotoAgent.MAX_TOOL_RESULT_CHARS\n ? resultStr.slice(0, ObotoAgent.MAX_TOOL_RESULT_CHARS) +\n `\\n\\n[... truncated ${resultStr.length - ObotoAgent.MAX_TOOL_RESULT_CHARS} characters. Use the data above to proceed.]`\n : resultStr;\n\n this.bus.emit(\"tool_execution_complete\", { command, kwargs, result: truncated });\n toolResults.push({ command, success });\n totalToolCalls++;\n\n messages.push({\n role: \"tool\",\n tool_call_id: tc.id,\n content: truncated,\n });\n }\n\n // Emit tool round summary\n this.bus.emit(\"tool_round_complete\", {\n iteration,\n tools: toolResults,\n totalToolCalls,\n });\n }\n\n // Exhausted iterations fallback\n const fallbackMsg: ConversationMessage = {\n role: MessageRole.Assistant,\n blocks: [{ kind: \"text\", text: \"I reached the maximum number of iterations. Here is what I have so far.\" }],\n };\n this.session.messages.push(fallbackMsg);\n await this.contextManager.push(toChat(fallbackMsg));\n this.bus.emit(\"state_updated\", { reason: \"max_iterations\" });\n this.bus.emit(\"turn_complete\", {\n model: modelName,\n escalated: true,\n iterations: this.maxIterations,\n toolCalls: totalToolCalls,\n });\n }\n\n /**\n * Stream an LLM call, emitting tokens in real-time, then aggregate into\n * a full StandardChatResponse (including accumulated tool calls).\n */\n private async streamAndAggregate(\n provider: BaseProvider,\n params: StandardChatParams\n ): Promise<StandardChatResponse> {\n const stream = provider.stream({ ...params, stream: true });\n\n // Collect chunks while emitting tokens\n const chunks: StandardChatChunk[] = [];\n for await (const chunk of stream) {\n chunks.push(chunk);\n\n // Emit text tokens in real-time\n const delta = chunk.choices?.[0]?.delta;\n if (delta?.content) {\n this.onToken!(delta.content);\n this.bus.emit(\"token\", { text: delta.content });\n }\n }\n\n // Replay collected chunks through aggregateStream to build full response\n async function* replay(): AsyncIterable<StandardChatChunk> {\n for (const c of chunks) yield c;\n }\n return aggregateStream(replay());\n }\n}\n","import type { AgentEventType, AgentEvent } from \"./types.js\";\n\ntype EventHandler = (event: AgentEvent) => void;\n\n/**\n * Platform-agnostic typed event bus.\n * Uses a plain Map instead of Node.js EventEmitter for browser/Deno/Bun compatibility.\n */\nexport class AgentEventBus {\n private listeners = new Map<AgentEventType, Set<EventHandler>>();\n\n /** Subscribe to an event type. Returns an unsubscribe function. */\n on(type: AgentEventType, handler: EventHandler): () => void {\n if (!this.listeners.has(type)) {\n this.listeners.set(type, new Set());\n }\n this.listeners.get(type)!.add(handler);\n return () => this.off(type, handler);\n }\n\n /** Unsubscribe a handler from an event type. */\n off(type: AgentEventType, handler: EventHandler): void {\n this.listeners.get(type)?.delete(handler);\n }\n\n /** Subscribe to an event type for a single emission. */\n once(type: AgentEventType, handler: EventHandler): () => void {\n const wrapper: EventHandler = (event) => {\n this.off(type, wrapper);\n handler(event);\n };\n return this.on(type, wrapper);\n }\n\n /** Emit an event to all subscribers. */\n emit(type: AgentEventType, payload: unknown): void {\n const event: AgentEvent = {\n type,\n payload,\n timestamp: Date.now(),\n };\n const handlers = this.listeners.get(type);\n if (handlers) {\n for (const handler of handlers) {\n handler(event);\n }\n }\n }\n\n /** Remove all listeners for all event types. */\n removeAllListeners(): void {\n this.listeners.clear();\n }\n}\n","import { z } from \"zod\";\nimport { ContextStack, type LScriptRuntime, type ChatMessage, type LScriptFunction } from \"@sschepis/lmscript\";\n\nconst SummarySchema = z.object({\n summary: z.string().describe(\"A dense summary of the conversation so far\"),\n});\n\ntype SummaryInput = { conversation: string };\n\n/**\n * Manages the sliding context window with automatic summarization.\n * Wraps lmscript's ContextStack and uses the local LLM for compression.\n */\nexport class ContextManager {\n private stack: ContextStack;\n private summarizeFn: LScriptFunction<SummaryInput, typeof SummarySchema>;\n\n constructor(\n private localRuntime: LScriptRuntime,\n localModelName: string,\n maxTokens: number\n ) {\n this.stack = new ContextStack({\n maxTokens,\n pruneStrategy: \"summarize\",\n });\n\n this.summarizeFn = {\n name: \"summarize_context\",\n model: localModelName,\n system:\n \"You are a summarization engine. Compress the given conversation into a dense, factual summary that preserves all key information, decisions, and context needed for continued operation. Be concise but thorough.\",\n prompt: ({ conversation }) => conversation,\n schema: SummarySchema,\n temperature: 0.2,\n maxRetries: 1,\n };\n\n this.stack.setSummarizer(async (messages: ChatMessage[]) => {\n const conversation = messages\n .map((m) => {\n const text =\n typeof m.content === \"string\"\n ? m.content\n : m.content\n .filter((b) => b.type === \"text\")\n .map((b) => (b as { text: string }).text)\n .join(\" \");\n return `${m.role}: ${text}`;\n })\n .join(\"\\n\");\n\n const result = await this.localRuntime.execute(this.summarizeFn, {\n conversation,\n });\n return result.data.summary;\n });\n }\n\n /** Append a message to the context. Triggers pruning if over budget. */\n async push(message: ChatMessage): Promise<void> {\n await this.stack.push(message);\n }\n\n /** Append multiple messages. */\n async pushAll(messages: ChatMessage[]): Promise<void> {\n await this.stack.pushAll(messages);\n }\n\n /** Get all messages in the current context window. */\n getMessages(): ChatMessage[] {\n return this.stack.getMessages();\n }\n\n /** Get estimated token count. */\n getTokenCount(): number {\n return this.stack.getTokenCount();\n }\n\n /** Clear all context. */\n clear(): void {\n this.stack.clear();\n }\n}\n","import { z } from \"zod\";\nimport type { LScriptFunction } from \"@sschepis/lmscript\";\n\n/** Zod schema for structured triage output. */\nexport const TriageSchema = z.object({\n escalate: z\n .boolean()\n .describe(\"True if the request needs a powerful model, false if answerable directly\"),\n reasoning: z\n .string()\n .describe(\"Brief explanation of the triage decision\"),\n directResponse: z\n .string()\n .optional()\n .describe(\"Direct answer if the request can be handled without escalation\"),\n});\n\nexport type TriageInput = {\n userInput: string;\n recentContext: string;\n availableTools: string;\n};\n\nconst TRIAGE_SYSTEM = `You are a fast triage classifier for an AI agent system.\nYour job is to decide whether a user's request can be answered directly (simple queries,\ncasual chat, short lookups) or needs to be escalated to a more powerful model\n(complex reasoning, multi-step tool usage, code generation, analysis).\n\nRules:\n- If the request is a greeting, simple question, or casual conversation: respond directly.\n- If the request needs tool calls, code analysis, or multi-step reasoning: escalate.\n- If unsure, escalate. It's better to over-escalate than to give a poor direct answer.\n- Keep directResponse under 200 words when answering directly.\n\nRespond with JSON matching the schema.`;\n\n/**\n * Create an LScriptFunction for local-LLM triage classification.\n * The local model evaluates whether input needs escalation to the remote model.\n */\nexport function createTriageFunction(\n modelName: string\n): LScriptFunction<TriageInput, typeof TriageSchema> {\n return {\n name: \"triage\",\n model: modelName,\n system: TRIAGE_SYSTEM,\n prompt: ({ userInput, recentContext, availableTools }) =>\n `Recent context:\\n${recentContext}\\n\\nAvailable tools: ${availableTools}\\n\\nUser: ${userInput}`,\n schema: TriageSchema,\n temperature: 0.1,\n maxRetries: 1,\n };\n}\n","import { z } from \"zod\";\nimport type { Router } from \"@sschepis/swiss-army-tool\";\nimport { generateToolSchema } from \"@sschepis/swiss-army-tool\";\nimport type { ToolDefinition } from \"@sschepis/lmscript\";\nimport type { BranchNode } from \"@sschepis/swiss-army-tool\";\n\n/** Parameter schema for the omni-tool bridge. */\nconst RouterToolParams = z.object({\n command: z.string().describe(\n \"The command or menu path (e.g., 'help', 'filesystem read', 'db query')\"\n ),\n kwargs: z\n .record(z.unknown())\n .optional()\n .default({})\n .describe(\"Key-value arguments for the command\"),\n});\n\n/**\n * Bridge a swiss-army-tool Router into an lmscript ToolDefinition.\n *\n * The LLM sees a single tool (\"terminal_interface\") with `command` and `kwargs`\n * parameters. When called, it routes through the swiss-army-tool command tree.\n */\nexport function createRouterTool(\n router: Router,\n root?: BranchNode\n): ToolDefinition<typeof RouterToolParams, string> {\n const schema = generateToolSchema({ root });\n\n return {\n name: schema.name,\n description: schema.description,\n parameters: RouterToolParams,\n execute: async (params) => {\n return router.execute(params.command, params.kwargs ?? {});\n },\n };\n}\n","import type { LLMProvider, LLMRequest, LLMResponse } from \"@sschepis/lmscript\";\nimport type {\n BaseProvider,\n StandardChatParams,\n Message,\n ToolDefinition as WrapperToolDef,\n} from \"@sschepis/llm-wrapper\";\n\n/**\n * Adapt a llm-wrapper BaseProvider into lmscript's LLMProvider interface.\n *\n * This allows lmscript's LScriptRuntime to use llm-wrapper providers for\n * structured calls (e.g. triage) that need schema validation.\n */\nexport function toLmscriptProvider(\n provider: BaseProvider,\n name?: string\n): LLMProvider {\n return {\n name: name ?? provider.providerName,\n\n async chat(request: LLMRequest): Promise<LLMResponse> {\n // Convert lmscript messages → llm-wrapper messages\n const messages: Message[] = request.messages.map((m) => ({\n role: m.role,\n content:\n typeof m.content === \"string\"\n ? m.content\n : m.content\n .filter((b) => b.type === \"text\")\n .map((b) => (b as { type: \"text\"; text: string }).text)\n .join(\"\\n\"),\n }));\n\n // Convert lmscript tools → llm-wrapper tool definitions\n let tools: WrapperToolDef[] | undefined;\n if (request.tools && request.tools.length > 0) {\n tools = request.tools.map((t) => ({\n type: \"function\" as const,\n function: {\n name: t.name,\n description: t.description,\n parameters: t.parameters as Record<string, unknown>,\n },\n }));\n }\n\n const params: StandardChatParams = {\n model: request.model,\n messages,\n temperature: request.temperature,\n ...(tools ? { tools } : {}),\n ...(request.jsonMode\n ? { response_format: { type: \"json_object\" as const } }\n : {}),\n };\n\n const response = await provider.chat(params);\n const choice = response.choices[0];\n\n // Convert tool calls back to lmscript format\n let toolCalls: LLMResponse[\"toolCalls\"];\n if (choice?.message?.tool_calls) {\n toolCalls = choice.message.tool_calls.map((tc) => ({\n id: tc.id,\n name: tc.function.name,\n arguments: tc.function.arguments,\n }));\n }\n\n return {\n content: (choice?.message?.content as string) ?? \"\",\n usage: response.usage\n ? {\n promptTokens: response.usage.prompt_tokens,\n completionTokens: response.usage.completion_tokens,\n totalTokens: response.usage.total_tokens,\n }\n : undefined,\n toolCalls,\n };\n },\n };\n}\n","import {\n MessageRole,\n type ConversationMessage,\n type ContentBlock as AsContentBlock,\n type Session,\n} from \"@sschepis/as-agent\";\nimport type { ChatMessage, Role } from \"@sschepis/lmscript\";\n\nconst ROLE_TO_STRING: Record<MessageRole, Role> = {\n [MessageRole.System]: \"system\",\n [MessageRole.User]: \"user\",\n [MessageRole.Assistant]: \"assistant\",\n [MessageRole.Tool]: \"user\",\n};\n\nconst STRING_TO_ROLE: Record<Role, MessageRole> = {\n system: MessageRole.System,\n user: MessageRole.User,\n assistant: MessageRole.Assistant,\n};\n\n/** Extract plain text from as-agent content blocks. */\nfunction blocksToText(blocks: AsContentBlock[]): string {\n return blocks\n .map((b) => {\n switch (b.kind) {\n case \"text\":\n return b.text;\n case \"tool_use\":\n return `[Tool call: ${b.name}(${b.input})]`;\n case \"tool_result\":\n return b.isError\n ? `[Tool error (${b.toolName}): ${b.output}]`\n : `[Tool result (${b.toolName}): ${b.output}]`;\n }\n })\n .join(\"\\n\");\n}\n\n/** Convert an as-agent ConversationMessage to an lmscript ChatMessage. */\nexport function toChat(msg: ConversationMessage): ChatMessage {\n return {\n role: ROLE_TO_STRING[msg.role] ?? \"user\",\n content: blocksToText(msg.blocks),\n };\n}\n\n/** Convert an lmscript ChatMessage to an as-agent ConversationMessage. */\nexport function fromChat(msg: ChatMessage): ConversationMessage {\n const text = typeof msg.content === \"string\"\n ? msg.content\n : msg.content\n .filter((b) => b.type === \"text\")\n .map((b) => (b as { text: string }).text)\n .join(\"\\n\");\n\n return {\n role: STRING_TO_ROLE[msg.role] ?? MessageRole.User,\n blocks: [{ kind: \"text\", text }],\n };\n}\n\n/** Convert an entire as-agent Session to an array of lmscript ChatMessages. */\nexport function sessionToHistory(session: Session): ChatMessage[] {\n return session.messages.map(toChat);\n}\n\n/** Create an empty as-agent Session. */\nexport function createEmptySession(): Session {\n return { version: 1, messages: [] };\n}\n"],"mappings":"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","names":["MessageRole","z","z","MessageRole"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sschepis/oboto-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Event-driven dual-LLM orchestration library for autonomous AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -40,23 +40,24 @@
|
|
|
40
40
|
"dist"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"zod": "^3.23.0"
|
|
43
|
+
"zod": "^3.23.0",
|
|
44
|
+
"zod-to-json-schema": "^3.25.2"
|
|
44
45
|
},
|
|
45
46
|
"peerDependencies": {
|
|
47
|
+
"@sschepis/as-agent": "^0.1.0",
|
|
46
48
|
"@sschepis/llm-wrapper": "^0.1.0",
|
|
47
49
|
"@sschepis/lmscript": "^0.1.0",
|
|
48
|
-
"@sschepis/swiss-army-tool": "^0.1.0"
|
|
49
|
-
"@sschepis/as-agent": "^0.1.0"
|
|
50
|
+
"@sschepis/swiss-army-tool": "^0.1.0"
|
|
50
51
|
},
|
|
51
52
|
"optionalDependencies": {
|
|
52
53
|
"@aleph-ai/tinyaleph": "^1.7.0",
|
|
53
54
|
"@sschepis/resolang": "^0.5.0"
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
57
|
+
"@sschepis/as-agent": "file:../claw-code/assembly",
|
|
56
58
|
"@sschepis/llm-wrapper": "file:../llm-wrapper",
|
|
57
59
|
"@sschepis/lmscript": "file:../lmscript",
|
|
58
60
|
"@sschepis/swiss-army-tool": "file:../swiss-army-tool",
|
|
59
|
-
"@sschepis/as-agent": "file:../claw-code/assembly",
|
|
60
61
|
"tsup": "^8.0.0",
|
|
61
62
|
"typescript": "^5.5.0",
|
|
62
63
|
"vitest": "^2.0.0"
|