UNPKG

@autifyhq/muon

Version:

Muon - AI-Powered Playwright Test Coding Agent with Advanced Test Fixing Capabilities

155 lines (154 loc) 5.27 kB
import { MuonAuth } from './auth.js'; import { StreamingMuonAgent, } from './streaming-agent.js'; class MuonQueryImpl { constructor(agent, generator) { this.agent = agent; this.generator = generator; } async next() { return this.generator.next(); } async return(value) { return this.generator.return(value); } async throw(e) { return this.generator.throw(e); } [Symbol.asyncIterator]() { return this.generator; } abort() { this.agent.abort(); } async interrupt() { this.agent.abort(); } } export function muonQuery(prompt, options = {}) { const apiKey = options.apiKey || process.env.MUON_API_KEY; const serverUrl = options.serverUrl || process.env.MUON_SERVER_URL || 'http://127.0.0.1:3001'; let accessToken = options.accessToken; let auth; // If no API key and no access token provided, try to load from device flow auth if (!apiKey && !accessToken) { try { auth = new MuonAuth(serverUrl); const tokens = auth.getTokens(); if (tokens) { accessToken = tokens.accessToken; } } catch (_error) { // Ignore auth loading errors, we'll handle auth requirement below } } // Require either API key or access token if (!apiKey && !accessToken) { throw new Error('Authentication is required to use Muon Agent.\n' + 'Option 1: Run "muon login" to authenticate via OAuth\n' + 'Option 2: Set MUON_API_KEY environment variable or pass apiKey in options.\n' + `Get your API key from: ${serverUrl}/keys`); } const agent = new StreamingMuonAgent({ serverUrl, apiKey, accessToken, auth, projectPath: options.projectPath || '.', agentType: options.agentType, nlstepMode: options.nlstepMode, ...options, }); const generator = agent.query(prompt); return new MuonQueryImpl(agent, generator); } // Direct nlstep execution function export async function muonNLStep(request, options = {}) { const apiKey = options.apiKey || process.env.MUON_API_KEY; const serverUrl = options.serverUrl || process.env.MUON_SERVER_URL || 'http://127.0.0.1:3001'; let accessToken = options.accessToken; let auth; // If no API key and no access token provided, try to load from device flow auth if (!apiKey && !accessToken) { try { auth = new MuonAuth(serverUrl); const tokens = auth.getTokens(); if (tokens) { accessToken = tokens.accessToken; } } catch (_error) { // Ignore auth loading errors, we'll handle auth requirement below } } // Require either API key or access token if (!apiKey && !accessToken) { throw new Error('Authentication is required to use Muon NLStep.\n' + 'Option 1: Run "muon login" to authenticate via OAuth\n' + 'Option 2: Set MUON_API_KEY environment variable or pass apiKey in options.\n' + `Get your API key from: ${serverUrl}/keys`); } const agent = new StreamingMuonAgent({ serverUrl, apiKey, accessToken, auth, projectPath: options.projectPath, agentType: options.agentType, }); return agent.executeNLStep(request); } // Convenience function for simple usage export async function muonTask(prompt, options = {}) { const query = muonQuery(prompt, options); let lastResult = ''; const iterator = query[Symbol.asyncIterator](); while (true) { const result = await iterator.next(); if (result.done) { // Generator completed - return the last assistant message content return lastResult; } else { // Process yielded message const message = result.value; if (message.type === 'assistant' && message.content) { lastResult = message.content; } } } } // Stream processing utilities export async function muonStream(prompt, onMessage, options = {}) { const query = muonQuery(prompt, options); try { // Manually iterate to capture the return value const iterator = query[Symbol.asyncIterator](); while (true) { const result = await iterator.next(); if (result.done) { // Generator completed - result.value contains the MuonResultMessage return result.value; } else { // Yield message - process it onMessage(result.value); } } } catch (error) { // Handle any errors during iteration if (error && typeof error === 'object' && 'type' in error && error.type === 'result') { return error; } // Return error result for unexpected errors return { type: 'result', subtype: 'error', duration_ms: 0, session_id: '', error: error instanceof Error ? error.message : String(error), }; } } export { StreamingMuonAgent };