shreyask commited on
Commit
3ef03bf
·
verified ·
1 Parent(s): 108f72f

remove default tools and make the get started page dynamic. Added public folder

Browse files
.gitignore CHANGED
@@ -22,3 +22,4 @@ dist-ssr
22
  *.njsproj
23
  *.sln
24
  *.sw?
 
 
22
  *.njsproj
23
  *.sln
24
  *.sw?
25
+ package-lock.json
public/liquidai-logo.svg ADDED
public/thumbnail.png ADDED

Git LFS Details

  • SHA256: 389f1e853f6f9be5fcad644a6092e4283a004072598ffdba0d9da6b6d7d6d751
  • Pointer size: 131 Bytes
  • Size of remote file: 624 kB
src/App.tsx CHANGED
@@ -35,7 +35,7 @@ import {
35
  import { DEFAULT_SYSTEM_PROMPT } from "./constants/systemPrompt";
36
  import { DB_NAME, STORE_NAME, SETTINGS_STORE_NAME } from "./constants/db";
37
 
38
- import { DEFAULT_TOOLS, TEMPLATE } from "./tools";
39
  import ToolResultRenderer from "./components/ToolResultRenderer";
40
  import ToolCallIndicator from "./components/ToolCallIndicator";
41
  import ToolItem from "./components/ToolItem";
@@ -123,23 +123,7 @@ const App: React.FC = () => {
123
  const loadTools = useCallback(async (): Promise<void> => {
124
  const db = await getDB();
125
  const allTools: Tool[] = await db.getAll(STORE_NAME);
126
- if (allTools.length === 0) {
127
- const defaultTools: Tool[] = Object.entries(DEFAULT_TOOLS).map(
128
- ([name, code], id) => ({
129
- id,
130
- name,
131
- code,
132
- enabled: true,
133
- isCollapsed: false,
134
- })
135
- );
136
- const tx = db.transaction(STORE_NAME, "readwrite");
137
- await Promise.all(defaultTools.map((tool) => tx.store.put(tool)));
138
- await tx.done;
139
- setTools(defaultTools);
140
- } else {
141
- setTools(allTools.map((t) => ({ ...t, isCollapsed: false })));
142
- }
143
 
144
  // Load MCP tools and merge them
145
  const mcpTools = getMCPToolsAsOriginalTools();
@@ -386,12 +370,15 @@ const App: React.FC = () => {
386
  );
387
  }
388
 
389
- results.push({
390
  call,
391
  result: parsedResult,
392
  renderer: rendererCode,
393
- input: namedParams,
394
- });
 
 
 
395
  } catch (error) {
396
  const errorMessage = getErrorMessage(error);
397
  results.push({ call, error: errorMessage });
@@ -720,7 +707,17 @@ const App: React.FC = () => {
720
  className="flex-grow bg-gray-800 rounded-lg p-4 overflow-y-auto mb-4 space-y-4"
721
  >
722
  {messages.length === 0 && isReady ? (
723
- <ExamplePrompts onExampleClick={handleExampleClick} />
 
 
 
 
 
 
 
 
 
 
724
  ) : (
725
  messages.map((msg, index) => {
726
  const key = `${msg.role}-${index}`;
 
35
  import { DEFAULT_SYSTEM_PROMPT } from "./constants/systemPrompt";
36
  import { DB_NAME, STORE_NAME, SETTINGS_STORE_NAME } from "./constants/db";
37
 
38
+ import { TEMPLATE } from "./tools";
39
  import ToolResultRenderer from "./components/ToolResultRenderer";
40
  import ToolCallIndicator from "./components/ToolCallIndicator";
41
  import ToolItem from "./components/ToolItem";
 
123
  const loadTools = useCallback(async (): Promise<void> => {
124
  const db = await getDB();
125
  const allTools: Tool[] = await db.getAll(STORE_NAME);
126
+ setTools(allTools.map((t) => ({ ...t, isCollapsed: false })));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
  // Load MCP tools and merge them
129
  const mcpTools = getMCPToolsAsOriginalTools();
 
370
  );
371
  }
372
 
373
+ const renderInfo: RenderInfo = {
374
  call,
375
  result: parsedResult,
376
  renderer: rendererCode,
377
+ };
378
+ if (namedParams && Object.keys(namedParams).length > 0) {
379
+ renderInfo.input = namedParams;
380
+ }
381
+ results.push(renderInfo);
382
  } catch (error) {
383
  const errorMessage = getErrorMessage(error);
384
  results.push({ call, error: errorMessage });
 
707
  className="flex-grow bg-gray-800 rounded-lg p-4 overflow-y-auto mb-4 space-y-4"
708
  >
709
  {messages.length === 0 && isReady ? (
710
+ <ExamplePrompts
711
+ examples={tools
712
+ .filter((tool) => tool.enabled)
713
+ .map((tool) => ({
714
+ icon: "🛠️",
715
+ displayText: tool.name,
716
+ messageText: `${tool.name}()`,
717
+ }))
718
+ .filter((ex) => ex.displayText)}
719
+ onExampleClick={handleExampleClick}
720
+ />
721
  ) : (
722
  messages.map((msg, index) => {
723
  const key = `${msg.role}-${index}`;
src/components/ExamplePrompts.tsx CHANGED
@@ -9,32 +9,45 @@ interface ExamplePromptsProps {
9
  const ExamplePrompts: React.FC<ExamplePromptsProps> = ({
10
  examples,
11
  onExampleClick,
12
- }) => (
13
- <div className="flex flex-col items-center justify-center h-full space-y-6">
14
- <div className="text-center mb-6">
15
- <h2 className="text-2xl font-semibold text-gray-300 mb-1">
16
- Try an example
17
- </h2>
18
- <p className="text-sm text-gray-500">Click one to get started</p>
19
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
- <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 max-w-2xl w-full px-4">
22
- {(examples || DEFAULT_EXAMPLES).map((example, index) => (
23
- <button
24
- key={index}
25
- onClick={() => onExampleClick(example.messageText)}
26
- className="flex items-center gap-3 p-4 bg-gray-700 hover:bg-gray-600 rounded-lg transition-colors text-left group cursor-pointer"
27
- >
28
- <span className="text-xl flex-shrink-0 group-hover:scale-110 transition-transform">
29
- {example.icon}
30
- </span>
31
- <span className="text-sm text-gray-200 group-hover:text-white transition-colors">
32
- {example.displayText}
33
- </span>
34
- </button>
35
- ))}
 
36
  </div>
37
- </div>
38
- );
39
 
40
  export default ExamplePrompts;
 
9
  const ExamplePrompts: React.FC<ExamplePromptsProps> = ({
10
  examples,
11
  onExampleClick,
12
+ }) => {
13
+ // If examples are provided, use them. Otherwise, generate from enabled tools.
14
+ let dynamicExamples = examples;
15
+ if (!dynamicExamples) {
16
+ // Try to get tools from props (if passed as examples)
17
+ dynamicExamples = undefined;
18
+ }
19
+ // If still undefined, fallback to DEFAULT_EXAMPLES
20
+ if (!dynamicExamples) {
21
+ dynamicExamples = DEFAULT_EXAMPLES;
22
+ }
23
+
24
+ return (
25
+ <div className="flex flex-col items-center justify-center h-full space-y-6">
26
+ <div className="text-center mb-6">
27
+ <h2 className="text-2xl font-semibold text-gray-300 mb-1">
28
+ Try an example
29
+ </h2>
30
+ <p className="text-sm text-gray-500">Click one to get started</p>
31
+ </div>
32
 
33
+ <div className="grid grid-cols-1 sm:grid-cols-2 gap-3 max-w-2xl w-full px-4">
34
+ {dynamicExamples.map((example, index) => (
35
+ <button
36
+ key={index}
37
+ onClick={() => onExampleClick(example.messageText)}
38
+ className="flex items-center gap-3 p-4 bg-gray-700 hover:bg-gray-600 rounded-lg transition-colors text-left group cursor-pointer"
39
+ >
40
+ <span className="text-xl flex-shrink-0 group-hover:scale-110 transition-transform">
41
+ {example.icon}
42
+ </span>
43
+ <span className="text-sm text-gray-200 group-hover:text-white transition-colors">
44
+ {example.displayText}
45
+ </span>
46
+ </button>
47
+ ))}
48
+ </div>
49
  </div>
50
+ );
51
+ };
52
 
53
  export default ExamplePrompts;
src/tools/get_location.js DELETED
@@ -1,84 +0,0 @@
1
- /**
2
- * Get the user's current location using the browser's geolocation API.
3
- * @returns {Promise<{ latitude: number, longitude: number }>} The current position { latitude, longitude }.
4
- */
5
- export async function get_location() {
6
- return new Promise((resolve, reject) => {
7
- if (!navigator.geolocation) {
8
- reject("Geolocation not supported.");
9
- return;
10
- }
11
- navigator.geolocation.getCurrentPosition(
12
- (pos) =>
13
- resolve({
14
- latitude: pos.coords.latitude,
15
- longitude: pos.coords.longitude,
16
- }),
17
- (err) => reject(err.message || "Geolocation error"),
18
- );
19
- });
20
- }
21
-
22
- export default (input, output) =>
23
- React.createElement(
24
- "div",
25
- { className: "bg-green-50 border border-green-200 rounded-lg p-4" },
26
- React.createElement(
27
- "div",
28
- { className: "flex items-center mb-2" },
29
- React.createElement(
30
- "div",
31
- {
32
- className:
33
- "w-8 h-8 bg-green-100 rounded-full flex items-center justify-center mr-3",
34
- },
35
- "📍",
36
- ),
37
- React.createElement(
38
- "h3",
39
- { className: "text-green-900 font-semibold" },
40
- "Location",
41
- ),
42
- ),
43
- output?.latitude && output?.longitude
44
- ? React.createElement(
45
- "div",
46
- { className: "space-y-1 text-sm" },
47
- React.createElement(
48
- "p",
49
- { className: "text-green-700" },
50
- React.createElement(
51
- "span",
52
- { className: "font-medium" },
53
- "Latitude: ",
54
- ),
55
- output.latitude.toFixed(6),
56
- ),
57
- React.createElement(
58
- "p",
59
- { className: "text-green-700" },
60
- React.createElement(
61
- "span",
62
- { className: "font-medium" },
63
- "Longitude: ",
64
- ),
65
- output.longitude.toFixed(6),
66
- ),
67
- React.createElement(
68
- "a",
69
- {
70
- href: `https://maps.google.com?q=${output.latitude},${output.longitude}`,
71
- target: "_blank",
72
- rel: "noopener noreferrer",
73
- className:
74
- "inline-block mt-2 text-green-600 hover:text-green-800 underline text-xs",
75
- },
76
- "View on Google Maps",
77
- ),
78
- )
79
- : React.createElement(
80
- "p",
81
- { className: "text-green-700 text-sm" },
82
- JSON.stringify(output),
83
- ),
84
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/tools/get_time.js DELETED
@@ -1,51 +0,0 @@
1
- /**
2
- * Get the current date and time.
3
- * @returns {{ iso: string, local: string }} The current date and time as ISO and local time strings.
4
- */
5
- export function get_time() {
6
- const now = new Date();
7
- return {
8
- iso: now.toISOString(),
9
- local: now.toLocaleString(undefined, {
10
- dateStyle: "full",
11
- timeStyle: "long",
12
- }),
13
- };
14
- }
15
-
16
- export default (input, output) =>
17
- React.createElement(
18
- "div",
19
- { className: "bg-amber-50 border border-amber-200 rounded-lg p-4" },
20
- React.createElement(
21
- "div",
22
- { className: "flex items-center mb-2" },
23
- React.createElement(
24
- "div",
25
- {
26
- className:
27
- "w-8 h-8 bg-amber-100 rounded-full flex items-center justify-center mr-3",
28
- },
29
- "🕐",
30
- ),
31
- React.createElement(
32
- "h3",
33
- { className: "text-amber-900 font-semibold" },
34
- "Current Time",
35
- ),
36
- ),
37
- React.createElement(
38
- "div",
39
- { className: "text-sm space-y-1" },
40
- React.createElement(
41
- "p",
42
- { className: "text-amber-700 font-mono" },
43
- output.local,
44
- ),
45
- React.createElement(
46
- "p",
47
- { className: "text-amber-600 text-xs" },
48
- new Date(output.iso).toLocaleString(),
49
- ),
50
- ),
51
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/tools/math_eval.js DELETED
@@ -1,54 +0,0 @@
1
- /**
2
- * Evaluate a math expression.
3
- * @param {string} expression - The math expression (e.g., "2 + 2 * (3 - 1)").
4
- * @returns {number} The result of the expression.
5
- */
6
- export function math_eval(expression) {
7
- // Only allow numbers, spaces, and math symbols: + - * / % ( ) .
8
- if (!/^[\d\s+\-*/%.()]+$/.test(expression)) {
9
- throw new Error("Invalid characters in expression.");
10
- }
11
- return Function('"use strict";return (' + expression + ")")();
12
- }
13
-
14
- export default (input, output) =>
15
- React.createElement(
16
- "div",
17
- { className: "bg-emerald-50 border border-emerald-200 rounded-lg p-4" },
18
- React.createElement(
19
- "div",
20
- { className: "flex items-center mb-2" },
21
- React.createElement(
22
- "div",
23
- {
24
- className:
25
- "w-8 h-8 bg-emerald-100 rounded-full flex items-center justify-center mr-3",
26
- },
27
- "🧮",
28
- ),
29
- React.createElement(
30
- "h3",
31
- { className: "text-emerald-900 font-semibold" },
32
- "Math Evaluation",
33
- ),
34
- ),
35
- React.createElement(
36
- "div",
37
- { className: "text-center" },
38
- React.createElement(
39
- "div",
40
- { className: "text-lg font-mono text-emerald-700 mb-1" },
41
- input.expression || "Unknown expression",
42
- ),
43
- React.createElement(
44
- "div",
45
- { className: "text-2xl font-bold text-emerald-600 mb-1" },
46
- `= ${output}`,
47
- ),
48
- React.createElement(
49
- "p",
50
- { className: "text-emerald-500 text-xs" },
51
- "Calculation result",
52
- ),
53
- ),
54
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/tools/open_webpage.js DELETED
@@ -1,49 +0,0 @@
1
- /**
2
- * Open a webpage
3
- * @param {string} src - The URL of the webpage.
4
- * @returns {string} The validated URL.
5
- */
6
- export function open_webpage(src) {
7
- try {
8
- const urlObj = new URL(src);
9
- if (!["http:", "https:"].includes(urlObj.protocol)) {
10
- throw new Error("Only HTTP and HTTPS URLs are allowed.");
11
- }
12
- return urlObj.href;
13
- } catch (error) {
14
- throw new Error("Invalid URL provided.");
15
- }
16
- }
17
-
18
- export default (input, output) => {
19
- return React.createElement(
20
- "div",
21
- { className: "bg-blue-50 border border-blue-200 rounded-lg p-4" },
22
- React.createElement(
23
- "div",
24
- { className: "flex items-center mb-2" },
25
- React.createElement(
26
- "div",
27
- {
28
- className:
29
- "w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center mr-3",
30
- },
31
- "🌐",
32
- ),
33
- React.createElement(
34
- "h3",
35
- { className: "text-blue-900 font-semibold" },
36
- "Web Page",
37
- ),
38
- ),
39
- React.createElement("iframe", {
40
- src: output,
41
- className: "w-full border border-blue-300 rounded",
42
- width: 480,
43
- height: 360,
44
- title: "Embedded content",
45
- allow: "autoplay",
46
- frameBorder: "0",
47
- }),
48
- );
49
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/tools/random_number.js DELETED
@@ -1,51 +0,0 @@
1
- /**
2
- * Generate a random integer between min and max (inclusive).
3
- * @param {number} min - Minimum value (inclusive).
4
- * @param {number} max - Maximum value (inclusive).
5
- * @returns {number} A random integer.
6
- */
7
- export function random_number(min, max) {
8
- min = Math.ceil(Number(min));
9
- max = Math.floor(Number(max));
10
- if (isNaN(min) || isNaN(max) || min > max) {
11
- throw new Error("Invalid min or max value.");
12
- }
13
- return Math.floor(Math.random() * (max - min + 1)) + min;
14
- }
15
-
16
- export default (input, output) =>
17
- React.createElement(
18
- "div",
19
- { className: "bg-indigo-50 border border-indigo-200 rounded-lg p-4" },
20
- React.createElement(
21
- "div",
22
- { className: "flex items-center mb-2" },
23
- React.createElement(
24
- "div",
25
- {
26
- className:
27
- "w-8 h-8 bg-indigo-100 rounded-full flex items-center justify-center mr-3",
28
- },
29
- "🎲",
30
- ),
31
- React.createElement(
32
- "h3",
33
- { className: "text-indigo-900 font-semibold" },
34
- "Random Number",
35
- ),
36
- ),
37
- React.createElement(
38
- "div",
39
- { className: "text-center" },
40
- React.createElement(
41
- "div",
42
- { className: "text-3xl font-bold text-indigo-600 mb-1" },
43
- output,
44
- ),
45
- React.createElement(
46
- "p",
47
- { className: "text-indigo-500 text-xs" },
48
- `Range: ${input.min || "?"} - ${input.max || "?"}`,
49
- ),
50
- ),
51
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/tools/sleep.js DELETED
@@ -1,45 +0,0 @@
1
- /**
2
- * Sleep for a given number of seconds.
3
- * @param {number} seconds - The number of seconds to sleep.
4
- * @return {void}
5
- */
6
- export async function sleep(seconds) {
7
- return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
8
- }
9
-
10
- export default (input, output) =>
11
- React.createElement(
12
- "div",
13
- { className: "bg-purple-50 border border-purple-200 rounded-lg p-4" },
14
- React.createElement(
15
- "div",
16
- { className: "flex items-center mb-2" },
17
- React.createElement(
18
- "div",
19
- {
20
- className:
21
- "w-8 h-8 bg-purple-100 rounded-full flex items-center justify-center mr-3",
22
- },
23
- "😴",
24
- ),
25
- React.createElement(
26
- "h3",
27
- { className: "text-purple-900 font-semibold" },
28
- "Sleep",
29
- ),
30
- ),
31
- React.createElement(
32
- "div",
33
- { className: "text-sm space-y-1" },
34
- React.createElement(
35
- "p",
36
- { className: "text-purple-700 font-medium" },
37
- `Slept for ${input.seconds || "unknown"} seconds`,
38
- ),
39
- React.createElement(
40
- "p",
41
- { className: "text-purple-600 text-xs" },
42
- output,
43
- ),
44
- ),
45
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/tools/speak.js DELETED
@@ -1,58 +0,0 @@
1
- /**
2
- * Speak text using the browser's speech synthesis API.
3
- * @param {string} text - The text to speak.
4
- * @param {string} [voice] - The name of the voice to use (optional).
5
- * @return {void}
6
- */
7
- export function speak(text, voice = undefined) {
8
- const utter = new window.SpeechSynthesisUtterance(text);
9
- if (voice) {
10
- const voices = window.speechSynthesis.getVoices();
11
- const match = voices.find((v) => v.name === voice);
12
- if (match) utter.voice = match;
13
- }
14
- window.speechSynthesis.speak(utter);
15
- }
16
-
17
- export default (input, output) =>
18
- React.createElement(
19
- "div",
20
- { className: "bg-blue-50 border border-blue-200 rounded-lg p-4" },
21
- React.createElement(
22
- "div",
23
- { className: "flex items-center mb-2" },
24
- React.createElement(
25
- "div",
26
- {
27
- className:
28
- "w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center mr-3",
29
- },
30
- "🔊",
31
- ),
32
- React.createElement(
33
- "h3",
34
- { className: "text-blue-900 font-semibold" },
35
- "Speech Synthesis",
36
- ),
37
- ),
38
- React.createElement(
39
- "div",
40
- { className: "text-sm space-y-1" },
41
- React.createElement(
42
- "p",
43
- { className: "text-blue-700 font-medium" },
44
- `Speaking: "${input.text || "Unknown text"}"`,
45
- ),
46
- input.voice &&
47
- React.createElement(
48
- "p",
49
- { className: "text-blue-600 text-xs" },
50
- `Voice: ${input.voice}`,
51
- ),
52
- React.createElement(
53
- "p",
54
- { className: "text-blue-600 text-xs" },
55
- typeof output === "string" ? output : "Speech completed successfully",
56
- ),
57
- ),
58
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/tools/template.js DELETED
@@ -1,47 +0,0 @@
1
- /**
2
- * Description of the tool.
3
- * @param {any} parameter1 - Description of the first parameter.
4
- * @param {any} parameter2 - Description of the second parameter.
5
- * @returns {any} Description of the return value.
6
- */
7
- export function new_tool(parameter1, parameter2) {
8
- // TODO: Implement the tool logic here
9
- return true; // Placeholder return value
10
- }
11
-
12
- export default (input, output) =>
13
- React.createElement(
14
- "div",
15
- { className: "bg-amber-50 border border-amber-200 rounded-lg p-4" },
16
- React.createElement(
17
- "div",
18
- { className: "flex items-center mb-2" },
19
- React.createElement(
20
- "div",
21
- {
22
- className:
23
- "w-8 h-8 bg-amber-100 rounded-full flex items-center justify-center mr-3",
24
- },
25
- "🛠️",
26
- ),
27
- React.createElement(
28
- "h3",
29
- { className: "text-amber-900 font-semibold" },
30
- "Tool Name",
31
- ),
32
- ),
33
- React.createElement(
34
- "div",
35
- { className: "text-sm space-y-1" },
36
- React.createElement(
37
- "p",
38
- { className: "text-amber-700 font-medium" },
39
- `Input: ${JSON.stringify(input)}`,
40
- ),
41
- React.createElement(
42
- "p",
43
- { className: "text-amber-600 text-xs" },
44
- `Output: ${output}`,
45
- ),
46
- ),
47
- );