@@ -36,14 +36,14 @@ export class LLMClient {
3636 this . endpoint = endpoint ;
3737 this . model = endpoint . model ;
3838 this . provider = endpoint . provider ;
39- if ( ! endpoint . apiKey && endpoint . provider !== "ollama" ) {
39+ if ( ! endpoint . apiKey && endpoint . provider !== "ollama" && endpoint . provider !== "demo" && endpoint . provider !== "mock" ) {
4040 throw new LLMError (
4141 "No API key for this agent. Set global key or ARROW_<AGENT>_API_KEY / agents.yaml" ,
4242 ) ;
4343 }
4444 this . client = new OpenAI ( {
4545 apiKey : endpoint . apiKey || "ollama" ,
46- baseURL : endpoint . baseUrl ,
46+ baseURL : endpoint . provider === "demo" || endpoint . provider === "mock" ? "http://demo-url" : endpoint . baseUrl ,
4747 timeout : 120_000 ,
4848 maxRetries : 0 ,
4949 } ) ;
@@ -54,6 +54,58 @@ export class LLMClient {
5454 tools ?: OpenAITool [ ] ,
5555 opts ?: { onToken ?: ( t : string ) => void ; stream ?: boolean } ,
5656 ) : Promise < LLMResponse > {
57+ if ( this . provider === "demo" || this . provider === "mock" ) {
58+ // Mock LLM response generator for instant works/tryout!
59+ const userMessage = messages [ messages . length - 1 ] ?. content || "" ;
60+ let replyContent = "Let's explore the workspace and carry out your request." ;
61+ const toolCalls : ToolCall [ ] = [ ] ;
62+
63+ // Determine the kind of reply based on the message content
64+ const lower = typeof userMessage === "string" ? userMessage . toLowerCase ( ) : "" ;
65+ if ( lower . includes ( "[mode=plan]" ) || lower . includes ( "plan" ) ) {
66+ replyContent = `\`\`\`arrow-plan
67+ title: Demo Implementation Plan
68+ summary: A mockup flow to demonstrate clean and fast execution.
69+ steps:
70+ 1. Explore local directories and files.
71+ 2. Setup frontend core elements.
72+ 3. Validate using offline tests.
73+ risks:
74+ - Mock mode doesn't execute actual remote files.
75+ acceptance:
76+ - UI works fine.
77+ - Tests pass with green indicators.
78+ agents:
79+ frontend: Core UI setup
80+ backend: API endpoints mocking
81+ tester: Verify everything
82+ \`\`\`` ;
83+ } else if ( lower . includes ( "[execute]" ) || lower . includes ( "execute" ) || lower . includes ( "confirm" ) ) {
84+ replyContent = `\`\`\`arrow-ready
85+ Verification: Verified that all mock procedures ran fine and the application is highly optimized.
86+ All tests are passing.
87+ \`\`\`` ;
88+ } else if ( lower . includes ( "health" ) || lower . includes ( "status" ) ) {
89+ replyContent = "Everything is functioning correctly under the demo environment." ;
90+ }
91+
92+ if ( opts ?. onToken ) {
93+ // simulate streaming
94+ const parts = replyContent . split ( " " ) ;
95+ for ( const p of parts ) {
96+ opts . onToken ( p + " " ) ;
97+ await Bun . sleep ( 5 ) ;
98+ }
99+ }
100+
101+ return {
102+ content : replyContent ,
103+ toolCalls,
104+ finishReason : "stop" ,
105+ usage : { prompt_tokens : messages . length * 10 , completion_tokens : replyContent . length / 4 }
106+ } ;
107+ }
108+
57109 const stream = Boolean ( opts ?. stream && opts . onToken ) ;
58110 const body : OpenAI . Chat . ChatCompletionCreateParams = {
59111 model : this . model ,
0 commit comments