@@ -8,6 +8,7 @@ import './index.css';
88import { LanguageModelV1Prompt } from "ai"
99import { createAnthropic } from "@ai-sdk/anthropic"
1010import { createOpenAI } from "@ai-sdk/openai"
11+ import { createEffect } from 'solid-js' ;
1112
1213const root = document . getElementById ( 'root' ) ;
1314
@@ -20,7 +21,7 @@ if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
2021render ( ( ) => < App /> , root ! ) ;
2122
2223const anthropic = createAnthropic ( {
23- apiKey : "{ANTHROPIC_API_KEY}" ,
24+ apiKey : import . meta . env . VITE_ANTHROPIC_API_KEY || "{ANTHROPIC_API_KEY}" ,
2425 headers : {
2526 "anthropic-dangerous-direct-browser-access" : "true"
2627 } ,
@@ -40,7 +41,7 @@ const providerMetadata = {
4041 } ,
4142}
4243
43- const OPENCONTROL_ENDPOINT = "mcp"
44+ const OPENCONTROL_ENDPOINT = import . meta . env . VITE_OPENCONTROL_ENDPOINT || "mcp"
4445const toolDefs = await fetch ( OPENCONTROL_ENDPOINT , {
4546 method : "POST" ,
4647 headers : {
@@ -56,6 +57,8 @@ const toolDefs = await fetch(OPENCONTROL_ENDPOINT, {
5657 . then ( ( response ) => response . result . tools )
5758
5859function App ( ) {
60+ let root : HTMLDivElement | undefined
61+
5962 const [ store , setStore ] = createStore < {
6063 prompt : LanguageModelV1Prompt
6164 } > ( {
@@ -71,9 +74,27 @@ function App() {
7174 } ,
7275 } ,
7376 } ,
77+ {
78+ role : "system" ,
79+ content : `The current date is ${ new Date ( ) . toDateString ( ) } ` ,
80+ providerMetadata : {
81+ anthropic : {
82+ cacheControl : {
83+ type : "ephemeral" ,
84+ } ,
85+ } ,
86+ } ,
87+ }
7488 ] ,
7589 } )
7690
91+ createEffect ( ( ) => {
92+ const messages = store . prompt
93+ console . log ( "scrolling to bottom" )
94+ root ?. scrollTo ( 0 , root ?. scrollHeight )
95+ return messages . length
96+ } , 0 )
97+
7798 async function send ( message : string ) {
7899 setStore ( "prompt" ,
79100 store . prompt . length ,
@@ -89,80 +110,85 @@ function App() {
89110 }
90111 )
91112 while ( true ) {
92- const result = await provider . doGenerate ( {
93- prompt : store . prompt ,
94- mode : {
95- type : "regular" ,
96- tools : toolDefs . map ( ( tool : any ) => ( {
97- type : "function" ,
98- name : tool . name ,
99- description : tool . description ,
100- parameters : {
101- ...tool . inputSchema ,
102- } ,
103- } ) ) ,
104- } ,
105- inputFormat : "messages" ,
106- temperature : 1 ,
107- } )
108- console . log ( result )
109-
110- if ( result . text ) {
111- setStore ( "prompt" , store . prompt . length , {
112- role : "assistant" ,
113- content : [ {
114- type : "text" ,
115- text : result . text ,
116- } ]
113+ try {
114+ const result = await provider . doGenerate ( {
115+ prompt : store . prompt ,
116+ mode : {
117+ type : "regular" ,
118+ tools : toolDefs . map ( ( tool : any ) => ( {
119+ type : "function" ,
120+ name : tool . name ,
121+ description : tool . description ,
122+ parameters : {
123+ ...tool . inputSchema ,
124+ } ,
125+ } ) ) ,
126+ } ,
127+ inputFormat : "messages" ,
128+ temperature : 1 ,
117129 } )
118- }
119130
120- if ( result . finishReason === "stop" )
121- break
122- if ( result . finishReason === "tool-calls" ) {
123- for ( const item of result . toolCalls ! ) {
124- console . log ( "calling tool" , item . toolName , item . args )
131+ if ( result . text ) {
125132 setStore ( "prompt" , store . prompt . length , {
126133 role : "assistant" ,
127- content : result . toolCalls ! . map ( item => ( {
128- type : "tool-call" ,
129- toolName : item . toolName ,
130- args : JSON . parse ( item . args ) ,
131- toolCallId : item . toolCallId ,
132- } ) )
133- } )
134- const response = await fetch ( OPENCONTROL_ENDPOINT , {
135- method : "POST" ,
136- headers : {
137- "Content-Type" : "application/json" ,
138- } ,
139- body : JSON . stringify ( {
140- jsonrpc : "2.0" ,
141- id : "2" ,
142- method : "tools/call" ,
143- params : {
144- name : item . toolName ,
145- arguments : JSON . parse ( item . args ) ,
146- } ,
147- } ) ,
148- } ) . then ( ( response ) => response . json ( ) )
149- setStore ( "prompt" , store . prompt . length , {
150- role : "tool" ,
151134 content : [ {
152- type : "tool-result" ,
153- toolName : item . toolName ,
154- toolCallId : item . toolCallId ,
155- result : response ,
156- } ] ,
135+ type : "text" ,
136+ text : result . text ,
137+ } ]
157138 } )
158139 }
140+
141+ if ( result . finishReason === "stop" )
142+ break
143+ if ( result . finishReason === "tool-calls" ) {
144+ for ( const item of result . toolCalls ! ) {
145+ console . log ( "calling tool" , item . toolName , item . args )
146+ setStore ( "prompt" , store . prompt . length , {
147+ role : "assistant" ,
148+ content : result . toolCalls ! . map ( item => ( {
149+ type : "tool-call" ,
150+ toolName : item . toolName ,
151+ args : JSON . parse ( item . args ) ,
152+ toolCallId : item . toolCallId ,
153+ } ) )
154+ } )
155+ const response = await fetch ( OPENCONTROL_ENDPOINT , {
156+ method : "POST" ,
157+ headers : {
158+ "Content-Type" : "application/json" ,
159+ } ,
160+ body : JSON . stringify ( {
161+ jsonrpc : "2.0" ,
162+ id : "2" ,
163+ method : "tools/call" ,
164+ params : {
165+ name : item . toolName ,
166+ arguments : JSON . parse ( item . args ) ,
167+ } ,
168+ } ) ,
169+ } ) . then ( ( response ) => response . json ( ) )
170+ setStore ( "prompt" , store . prompt . length , {
171+ role : "tool" ,
172+ content : [ {
173+ type : "tool-result" ,
174+ toolName : item . toolName ,
175+ toolCallId : item . toolCallId ,
176+ result : response . result . content ,
177+ } ] ,
178+ } )
179+ }
180+ }
181+ } catch {
182+ await new Promise ( resolve => setTimeout ( resolve , 1000 ) )
183+ continue
159184 }
160185 }
161186 }
162187
163188
189+
164190 return (
165- < div data-component = "root" >
191+ < div data-component = "root" ref = { root } >
166192 < div data-component = "messages" >
167193 < For each = { store . prompt } >
168194 { ( item ) => (
0 commit comments