@gui-chat-plugin/exa 0.1.0

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/README.md ADDED
@@ -0,0 +1,112 @@
1
+ # @gui-chat-plugin/exa
2
+
3
+ [![npm version](https://badge.fury.io/js/%40gui-chat-plugin%2Fexa.svg)](https://www.npmjs.com/package/@gui-chat-plugin/exa)
4
+
5
+ Exa web search plugin for GUI Chat applications. Search the web using Exa API for high-quality, relevant results.
6
+
7
+ ## Features
8
+
9
+ - High-quality web search via Exa API
10
+ - Text content and highlights extraction
11
+ - Domain filtering (include/exclude)
12
+ - Date range filtering
13
+ - Result count configuration
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ yarn add @gui-chat-plugin/exa
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ### Vue Integration
24
+
25
+ ```typescript
26
+ // In src/tools/index.ts
27
+ import ExaPlugin from "@gui-chat-plugin/exa/vue";
28
+
29
+ const pluginList = [
30
+ // ... other plugins
31
+ ExaPlugin,
32
+ ];
33
+
34
+ // In src/main.ts
35
+ import "@gui-chat-plugin/exa/style.css";
36
+ ```
37
+
38
+ ### Core-only Usage
39
+
40
+ ```typescript
41
+ import { executeExa, TOOL_DEFINITION } from "@gui-chat-plugin/exa";
42
+
43
+ // Search the web
44
+ const result = await executeExa(context, {
45
+ query: "TypeScript best practices 2025",
46
+ numResults: 5,
47
+ includeText: true,
48
+ });
49
+ ```
50
+
51
+ ## API
52
+
53
+ ### ExaArgs
54
+
55
+ ```typescript
56
+ interface ExaArgs {
57
+ query: string;
58
+ numResults?: number; // 1-10, default: 5
59
+ includeText?: boolean; // Include page content
60
+ fetchHighlights?: boolean; // Include relevant snippets
61
+ includeDomains?: string[]; // Only search these domains
62
+ excludeDomains?: string[]; // Exclude these domains
63
+ startPublishedDate?: string; // ISO date format
64
+ endPublishedDate?: string; // ISO date format
65
+ }
66
+ ```
67
+
68
+ ### ExaSearchResult
69
+
70
+ ```typescript
71
+ interface ExaSearchResult {
72
+ title: string;
73
+ url: string;
74
+ text?: string;
75
+ highlights?: string[];
76
+ publishedDate?: string;
77
+ author?: string;
78
+ score?: number;
79
+ }
80
+ ```
81
+
82
+ ## Configuration
83
+
84
+ The plugin requires an Exa API key. Configure it via `hasExaApiKey` in your app's start response.
85
+
86
+ ## Development
87
+
88
+ ```bash
89
+ # Install dependencies
90
+ yarn install
91
+
92
+ # Run demo
93
+ yarn dev
94
+
95
+ # Build
96
+ yarn build
97
+
98
+ # Lint
99
+ yarn lint
100
+ ```
101
+
102
+ ## Test Prompts
103
+
104
+ Try these prompts to test the plugin:
105
+
106
+ 1. "Search for the latest developments in quantum computing"
107
+ 2. "Find articles about TypeScript best practices in 2025"
108
+ 3. "Search for tutorials on building Vue.js applications"
109
+
110
+ ## License
111
+
112
+ MIT
@@ -0,0 +1,53 @@
1
+ export declare const TOOL_NAME = "searchWeb";
2
+ export declare const TOOL_DEFINITION: {
3
+ type: "function";
4
+ name: string;
5
+ description: string;
6
+ parameters: {
7
+ type: "object";
8
+ properties: {
9
+ query: {
10
+ type: string;
11
+ description: string;
12
+ };
13
+ numResults: {
14
+ type: string;
15
+ description: string;
16
+ minimum: number;
17
+ maximum: number;
18
+ };
19
+ includeText: {
20
+ type: string;
21
+ description: string;
22
+ };
23
+ fetchHighlights: {
24
+ type: string;
25
+ description: string;
26
+ };
27
+ includeDomains: {
28
+ type: string;
29
+ description: string;
30
+ items: {
31
+ type: string;
32
+ };
33
+ };
34
+ excludeDomains: {
35
+ type: string;
36
+ description: string;
37
+ items: {
38
+ type: string;
39
+ };
40
+ };
41
+ startPublishedDate: {
42
+ type: string;
43
+ description: string;
44
+ };
45
+ endPublishedDate: {
46
+ type: string;
47
+ description: string;
48
+ };
49
+ };
50
+ required: string[];
51
+ };
52
+ };
53
+ //# sourceMappingURL=definition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/core/definition.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,cAAc,CAAC;AAErC,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmD3B,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from "./types";
2
+ export * from "./definition";
3
+ export * from "./plugin";
4
+ export { samples } from "./samples";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ToolContext, ToolPluginCore } from "gui-chat-protocol";
2
+ import type { ExaArgs, ExaResult } from "./types";
3
+ import { TOOL_NAME, TOOL_DEFINITION } from "./definition";
4
+ export declare const searchExa: (context: ToolContext, args: ExaArgs) => Promise<ExaResult>;
5
+ export declare const pluginCore: ToolPluginCore<never, import("./types").ExaJsonData, ExaArgs>;
6
+ export { TOOL_NAME, TOOL_DEFINITION };
7
+ export declare const executeExa: (context: ToolContext, args: ExaArgs) => Promise<ExaResult>;
8
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/core/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE1D,eAAO,MAAM,SAAS,GACpB,SAAS,WAAW,EACpB,MAAM,OAAO,KACZ,OAAO,CAAC,SAAS,CAmCnB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,cAAc,CAAC,KAAK,EAAE,OAAO,SAAS,EAAE,WAAW,EAAE,OAAO,CAQpF,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AACtC,eAAO,MAAM,UAAU,YAlDZ,WAAW,QACd,OAAO,KACZ,OAAO,CAAC,SAAS,CAgDe,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ToolSample } from "gui-chat-protocol";
2
+ export declare const samples: ToolSample[];
3
+ //# sourceMappingURL=samples.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"samples.d.ts","sourceRoot":"","sources":["../../src/core/samples.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,eAAO,MAAM,OAAO,EAAE,UAAU,EAgB/B,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ToolResult } from "gui-chat-protocol";
2
+ export interface ExaSearchResult {
3
+ title: string;
4
+ url: string;
5
+ text?: string;
6
+ highlights?: string[];
7
+ publishedDate?: string;
8
+ author?: string;
9
+ score?: number;
10
+ }
11
+ export interface ExaJsonData {
12
+ query: string;
13
+ results: ExaSearchResult[];
14
+ }
15
+ export type ExaResult = ToolResult<never, ExaJsonData>;
16
+ export interface ExaArgs {
17
+ query: string;
18
+ numResults?: number;
19
+ includeText?: boolean;
20
+ fetchHighlights?: boolean;
21
+ includeDomains?: string[];
22
+ excludeDomains?: string[];
23
+ startPublishedDate?: string;
24
+ endPublishedDate?: string;
25
+ }
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;AAEvD,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B"}
package/dist/core.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n="searchWeb",i={type:"function",name:n,description:"Search the web using Exa API for high-quality, relevant results",parameters:{type:"object",properties:{query:{type:"string",description:"The search query to find relevant web content"},numResults:{type:"number",description:"Number of results to return (default: 5, max: 10)",minimum:1,maximum:10},includeText:{type:"boolean",description:"Whether to include page text content in results (default: true)"},fetchHighlights:{type:"boolean",description:"Whether to include query-relevant highlights from the content"},includeDomains:{type:"array",description:"Only search within these domains",items:{type:"string"}},excludeDomains:{type:"array",description:"Exclude results from these domains",items:{type:"string"}},startPublishedDate:{type:"string",description:"Only include results published after this date (ISO format: 2025-01-01)"},endPublishedDate:{type:"string",description:"Only include results published before this date (ISO format: 2025-01-01)"}},required:["query"]}},r=async(t,s)=>{const{query:a}=s;if(!t.app?.searchExa)return{message:"searchExa function not available",instructions:"Acknowledge that the search failed due to a technical error."};try{const e=await t.app.searchExa(s);return e.success&&e.results?{message:`Found ${e.results.length} relevant results for "${a}"`,jsonData:{query:a,results:e.results},instructions:"Acknowledge that the search was successful and provide a very short summary, focusing only on the most relevant information."}:{message:e.error||"Exa search failed",instructions:"Acknowledge that the search failed and suggest trying a different query."}}catch(e){return{message:`Exa search failed: ${e instanceof Error?e.message:"Unknown error"}`,instructions:"Acknowledge that the search failed due to a technical error."}}},o={toolDefinition:i,execute:r,generatingMessage:"Searching the web...",waitingMessage:"Tell the user that you are searching for relevant information.",isEnabled:t=>!!t?.hasExaApiKey,delayAfterExecution:3e3,backends:["search"]},c=r,u=[{name:"AI News",args:{query:"latest artificial intelligence news 2025",numResults:5}},{name:"Programming Tutorial",args:{query:"TypeScript best practices tutorial",numResults:3,includeText:!0}}];exports.TOOL_DEFINITION=i;exports.TOOL_NAME=n;exports.executeExa=c;exports.pluginCore=o;exports.samples=u;exports.searchExa=r;
package/dist/core.js ADDED
@@ -0,0 +1,102 @@
1
+ const a = "searchWeb", i = {
2
+ type: "function",
3
+ name: a,
4
+ description: "Search the web using Exa API for high-quality, relevant results",
5
+ parameters: {
6
+ type: "object",
7
+ properties: {
8
+ query: {
9
+ type: "string",
10
+ description: "The search query to find relevant web content"
11
+ },
12
+ numResults: {
13
+ type: "number",
14
+ description: "Number of results to return (default: 5, max: 10)",
15
+ minimum: 1,
16
+ maximum: 10
17
+ },
18
+ includeText: {
19
+ type: "boolean",
20
+ description: "Whether to include page text content in results (default: true)"
21
+ },
22
+ fetchHighlights: {
23
+ type: "boolean",
24
+ description: "Whether to include query-relevant highlights from the content"
25
+ },
26
+ includeDomains: {
27
+ type: "array",
28
+ description: "Only search within these domains",
29
+ items: { type: "string" }
30
+ },
31
+ excludeDomains: {
32
+ type: "array",
33
+ description: "Exclude results from these domains",
34
+ items: { type: "string" }
35
+ },
36
+ startPublishedDate: {
37
+ type: "string",
38
+ description: "Only include results published after this date (ISO format: 2025-01-01)"
39
+ },
40
+ endPublishedDate: {
41
+ type: "string",
42
+ description: "Only include results published before this date (ISO format: 2025-01-01)"
43
+ }
44
+ },
45
+ required: ["query"]
46
+ }
47
+ }, n = async (t, r) => {
48
+ const { query: s } = r;
49
+ if (!t.app?.searchExa)
50
+ return {
51
+ message: "searchExa function not available",
52
+ instructions: "Acknowledge that the search failed due to a technical error."
53
+ };
54
+ try {
55
+ const e = await t.app.searchExa(r);
56
+ return e.success && e.results ? {
57
+ message: `Found ${e.results.length} relevant results for "${s}"`,
58
+ jsonData: { query: s, results: e.results },
59
+ instructions: "Acknowledge that the search was successful and provide a very short summary, focusing only on the most relevant information."
60
+ } : {
61
+ message: e.error || "Exa search failed",
62
+ instructions: "Acknowledge that the search failed and suggest trying a different query."
63
+ };
64
+ } catch (e) {
65
+ return {
66
+ message: `Exa search failed: ${e instanceof Error ? e.message : "Unknown error"}`,
67
+ instructions: "Acknowledge that the search failed due to a technical error."
68
+ };
69
+ }
70
+ }, o = {
71
+ toolDefinition: i,
72
+ execute: n,
73
+ generatingMessage: "Searching the web...",
74
+ waitingMessage: "Tell the user that you are searching for relevant information.",
75
+ isEnabled: (t) => !!t?.hasExaApiKey,
76
+ delayAfterExecution: 3e3,
77
+ backends: ["search"]
78
+ }, c = n, u = [
79
+ {
80
+ name: "AI News",
81
+ args: {
82
+ query: "latest artificial intelligence news 2025",
83
+ numResults: 5
84
+ }
85
+ },
86
+ {
87
+ name: "Programming Tutorial",
88
+ args: {
89
+ query: "TypeScript best practices tutorial",
90
+ numResults: 3,
91
+ includeText: !0
92
+ }
93
+ }
94
+ ];
95
+ export {
96
+ i as TOOL_DEFINITION,
97
+ a as TOOL_NAME,
98
+ c as executeExa,
99
+ o as pluginCore,
100
+ u as samples,
101
+ n as searchExa
102
+ };
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./core.cjs");exports.TOOL_DEFINITION=e.TOOL_DEFINITION;exports.TOOL_NAME=e.TOOL_NAME;exports.executeExa=e.executeExa;exports.pluginCore=e.pluginCore;exports.samples=e.samples;exports.searchExa=e.searchExa;
@@ -0,0 +1,2 @@
1
+ export * from "./core";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import { TOOL_DEFINITION as a, TOOL_NAME as r, executeExa as x, pluginCore as E, samples as o, searchExa as p } from "./core.js";
2
+ export {
3
+ a as TOOL_DEFINITION,
4
+ r as TOOL_NAME,
5
+ x as executeExa,
6
+ E as pluginCore,
7
+ o as samples,
8
+ p as searchExa
9
+ };
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-blue-600:oklch(54.6% .245 262.881);--color-blue-800:oklch(42.4% .199 265.638);--color-purple-50:oklch(97.7% .014 308.299);--color-purple-600:oklch(55.8% .288 302.321);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-white:#fff;--spacing:.25rem;--container-4xl:56rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.mx-auto{margin-inline:auto}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.line-clamp-3{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.flex{display:flex}.h-full{height:100%}.w-full{width:100%}.max-w-4xl{max-width:var(--container-4xl)}.flex-1{flex:1}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*6)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*6)*calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.rounded{border-radius:.25rem}.rounded-lg{border-radius:var(--radius-lg)}.border{border-style:var(--tw-border-style);border-width:1px}.border-gray-200{border-color:var(--color-gray-200)}.bg-purple-50{background-color:var(--color-purple-50)}.bg-white{background-color:var(--color-white)}.p-4{padding:calc(var(--spacing)*4)}.p-6{padding:calc(var(--spacing)*6)}.text-center{text-align:center}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-blue-600{color:var(--color-blue-600)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-purple-600{color:var(--color-purple-600)}.italic{font-style:italic}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media(hover:hover){.hover\:text-blue-800:hover{color:var(--color-blue-800)}.hover\:underline:hover{text-decoration-line:underline}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
@@ -0,0 +1,9 @@
1
+ import type { ToolResult } from "gui-chat-protocol";
2
+ import type { ExaJsonData } from "../core/types";
3
+ type __VLS_Props = {
4
+ result: ToolResult<unknown, ExaJsonData>;
5
+ };
6
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
7
+ declare const _default: typeof __VLS_export;
8
+ export default _default;
9
+ //# sourceMappingURL=Preview.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Preview.vue.d.ts","sourceRoot":"","sources":["../../src/vue/Preview.vue"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;CAC1C,CAAC;AAkDF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -0,0 +1,9 @@
1
+ import type { ToolResult } from "gui-chat-protocol";
2
+ import type { ExaJsonData } from "../core/types";
3
+ type __VLS_Props = {
4
+ selectedResult: ToolResult<unknown, ExaJsonData>;
5
+ };
6
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
7
+ declare const _default: typeof __VLS_export;
8
+ export default _default;
9
+ //# sourceMappingURL=View.vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"View.vue.d.ts","sourceRoot":"","sources":["../../src/vue/View.vue"],"names":[],"mappings":"AA+DA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,KAAK,WAAW,GAAG;IACjB,cAAc,EAAE,UAAU,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;CAClD,CAAC;AAmJF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -0,0 +1,15 @@
1
+ import "../style.css";
2
+ import type { ToolPlugin } from "gui-chat-protocol/vue";
3
+ import type { ExaJsonData, ExaArgs } from "../core/types";
4
+ import View from "./View.vue";
5
+ import Preview from "./Preview.vue";
6
+ export declare const plugin: ToolPlugin<never, ExaJsonData, ExaArgs>;
7
+ export type { ExaSearchResult, ExaJsonData, ExaArgs, ExaResult } from "../core/types";
8
+ export { TOOL_NAME, TOOL_DEFINITION, executeExa, pluginCore, } from "../core/plugin";
9
+ export { samples } from "../core/samples";
10
+ export { View, Preview };
11
+ declare const _default: {
12
+ plugin: ToolPlugin<never, ExaJsonData, ExaArgs, import("gui-chat-protocol/vue").InputHandler, Record<string, unknown>>;
13
+ };
14
+ export default _default;
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vue/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG1D,OAAO,IAAI,MAAM,YAAY,CAAC;AAC9B,OAAO,OAAO,MAAM,eAAe,CAAC;AAEpC,eAAO,MAAM,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAK1D,CAAC;AAEF,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEtF,OAAO,EACL,SAAS,EACT,eAAe,EACf,UAAU,EACV,UAAU,GACX,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;;;;AAEzB,wBAA0B"}
package/dist/vue.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const l=require("./core.cjs"),e=require("vue"),u={class:"w-full h-full overflow-auto p-6 bg-white"},p={class:"max-w-4xl mx-auto"},h={class:"text-2xl font-bold text-gray-800 mb-6"},g={key:0,class:"text-lg font-normal text-gray-600"},x={key:0,class:"space-y-6"},_={class:"flex items-start justify-between"},y={class:"flex-1"},k={class:"text-lg font-semibold text-blue-600 hover:text-blue-800"},E=["href"],f={class:"text-sm text-gray-500 mt-1"},v={key:0,class:"text-gray-700 mt-2 line-clamp-3"},N={key:1,class:"mt-3"},B={class:"space-y-1"},D={key:2,class:"text-xs text-gray-400 mt-2"},r=e.defineComponent({__name:"View",props:{selectedResult:{}},setup(s){return(n,o)=>(e.openBlock(),e.createElementBlock("div",u,[e.createElementVNode("div",p,[e.createElementVNode("h2",h,[o[0]||(o[0]=e.createTextVNode(" Search Results ",-1)),s.selectedResult.jsonData&&s.selectedResult.jsonData.query?(e.openBlock(),e.createElementBlock("span",g,' for "'+e.toDisplayString(s.selectedResult.jsonData.query)+'" ',1)):e.createCommentVNode("",!0)]),s.selectedResult.jsonData?(e.openBlock(),e.createElementBlock("div",x,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(s.selectedResult.jsonData.results||[],(t,i)=>(e.openBlock(),e.createElementBlock("div",{key:i,class:"border border-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow"},[e.createElementVNode("div",_,[e.createElementVNode("div",y,[e.createElementVNode("h3",k,[e.createElementVNode("a",{href:t.url,target:"_blank",class:"hover:underline"},e.toDisplayString(t.title),9,E)]),e.createElementVNode("p",f,e.toDisplayString(t.url),1),t.text?(e.openBlock(),e.createElementBlock("p",v,e.toDisplayString(t.text),1)):e.createCommentVNode("",!0),t.highlights&&t.highlights.length?(e.openBlock(),e.createElementBlock("div",N,[o[1]||(o[1]=e.createElementVNode("p",{class:"text-sm font-medium text-gray-600 mb-1"},"Key highlights:",-1)),e.createElementVNode("div",B,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.highlights.slice(0,3),(d,m)=>(e.openBlock(),e.createElementBlock("p",{key:m,class:"text-sm text-gray-600 italic"},' "'+e.toDisplayString(d)+'" ',1))),128))])])):e.createCommentVNode("",!0),t.publishedDate?(e.openBlock(),e.createElementBlock("p",D," Published: "+e.toDisplayString(new Date(t.publishedDate).toLocaleDateString()),1)):e.createCommentVNode("",!0)])])]))),128))])):e.createCommentVNode("",!0)])]))}}),V={class:"text-center p-4 bg-purple-50 rounded"},b={class:"text-xs text-gray-600 mt-1 truncate"},a=e.defineComponent({__name:"Preview",props:{result:{}},setup(s){function n(o){if(!o)return"";const t=o.match(/relevant results for "([^"]+)"/);return t?t[1]:o}return(o,t)=>(e.openBlock(),e.createElementBlock("div",V,[t[0]||(t[0]=e.createElementVNode("div",{class:"text-purple-600 font-medium"},"Search Result",-1)),e.createElementVNode("div",b,e.toDisplayString(s.result.jsonData?.query||n(s.result.message)),1)]))}}),c={...l.pluginCore,viewComponent:r,previewComponent:a,samples:l.samples},w={plugin:c};exports.TOOL_DEFINITION=l.TOOL_DEFINITION;exports.TOOL_NAME=l.TOOL_NAME;exports.executeExa=l.executeExa;exports.pluginCore=l.pluginCore;exports.samples=l.samples;exports.Preview=a;exports.View=r;exports.default=w;exports.plugin=c;
package/dist/vue.js ADDED
@@ -0,0 +1,96 @@
1
+ import { samples as _, pluginCore as g } from "./core.js";
2
+ import { TOOL_DEFINITION as A, TOOL_NAME as K, executeExa as Q } from "./core.js";
3
+ import { defineComponent as u, createElementBlock as e, openBlock as s, createElementVNode as o, createCommentVNode as r, createTextVNode as p, toDisplayString as l, Fragment as c, renderList as d } from "vue";
4
+ const y = { class: "w-full h-full overflow-auto p-6 bg-white" }, f = { class: "max-w-4xl mx-auto" }, v = { class: "text-2xl font-bold text-gray-800 mb-6" }, b = {
5
+ key: 0,
6
+ class: "text-lg font-normal text-gray-600"
7
+ }, w = {
8
+ key: 0,
9
+ class: "space-y-6"
10
+ }, D = { class: "flex items-start justify-between" }, k = { class: "flex-1" }, R = { class: "text-lg font-semibold text-blue-600 hover:text-blue-800" }, j = ["href"], N = { class: "text-sm text-gray-500 mt-1" }, C = {
11
+ key: 0,
12
+ class: "text-gray-700 mt-2 line-clamp-3"
13
+ }, E = {
14
+ key: 1,
15
+ class: "mt-3"
16
+ }, O = { class: "space-y-1" }, V = {
17
+ key: 2,
18
+ class: "text-xs text-gray-400 mt-2"
19
+ }, L = /* @__PURE__ */ u({
20
+ __name: "View",
21
+ props: {
22
+ selectedResult: {}
23
+ },
24
+ setup(a) {
25
+ return (i, n) => (s(), e("div", y, [
26
+ o("div", f, [
27
+ o("h2", v, [
28
+ n[0] || (n[0] = p(" Search Results ", -1)),
29
+ a.selectedResult.jsonData && a.selectedResult.jsonData.query ? (s(), e("span", b, ' for "' + l(a.selectedResult.jsonData.query) + '" ', 1)) : r("", !0)
30
+ ]),
31
+ a.selectedResult.jsonData ? (s(), e("div", w, [
32
+ (s(!0), e(c, null, d(a.selectedResult.jsonData.results || [], (t, h) => (s(), e("div", {
33
+ key: h,
34
+ class: "border border-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow"
35
+ }, [
36
+ o("div", D, [
37
+ o("div", k, [
38
+ o("h3", R, [
39
+ o("a", {
40
+ href: t.url,
41
+ target: "_blank",
42
+ class: "hover:underline"
43
+ }, l(t.title), 9, j)
44
+ ]),
45
+ o("p", N, l(t.url), 1),
46
+ t.text ? (s(), e("p", C, l(t.text), 1)) : r("", !0),
47
+ t.highlights && t.highlights.length ? (s(), e("div", E, [
48
+ n[1] || (n[1] = o("p", { class: "text-sm font-medium text-gray-600 mb-1" }, "Key highlights:", -1)),
49
+ o("div", O, [
50
+ (s(!0), e(c, null, d(t.highlights.slice(0, 3), (m, x) => (s(), e("p", {
51
+ key: x,
52
+ class: "text-sm text-gray-600 italic"
53
+ }, ' "' + l(m) + '" ', 1))), 128))
54
+ ])
55
+ ])) : r("", !0),
56
+ t.publishedDate ? (s(), e("p", V, " Published: " + l(new Date(t.publishedDate).toLocaleDateString()), 1)) : r("", !0)
57
+ ])
58
+ ])
59
+ ]))), 128))
60
+ ])) : r("", !0)
61
+ ])
62
+ ]));
63
+ }
64
+ }), S = { class: "text-center p-4 bg-purple-50 rounded" }, T = { class: "text-xs text-gray-600 mt-1 truncate" }, q = /* @__PURE__ */ u({
65
+ __name: "Preview",
66
+ props: {
67
+ result: {}
68
+ },
69
+ setup(a) {
70
+ function i(n) {
71
+ if (!n) return "";
72
+ const t = n.match(/relevant results for "([^"]+)"/);
73
+ return t ? t[1] : n;
74
+ }
75
+ return (n, t) => (s(), e("div", S, [
76
+ t[0] || (t[0] = o("div", { class: "text-purple-600 font-medium" }, "Search Result", -1)),
77
+ o("div", T, l(a.result.jsonData?.query || i(a.result.message)), 1)
78
+ ]));
79
+ }
80
+ }), F = {
81
+ ...g,
82
+ viewComponent: L,
83
+ previewComponent: q,
84
+ samples: _
85
+ }, $ = { plugin: F };
86
+ export {
87
+ q as Preview,
88
+ A as TOOL_DEFINITION,
89
+ K as TOOL_NAME,
90
+ L as View,
91
+ $ as default,
92
+ Q as executeExa,
93
+ F as plugin,
94
+ g as pluginCore,
95
+ _ as samples
96
+ };
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@gui-chat-plugin/exa",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Exa web search plugin for GUI Chat applications",
6
+ "author": "receptron",
7
+ "license": "MIT",
8
+ "main": "./dist/index.cjs",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.cjs"
16
+ },
17
+ "./vue": {
18
+ "types": "./dist/vue/index.d.ts",
19
+ "import": "./dist/vue.js",
20
+ "require": "./dist/vue.cjs"
21
+ },
22
+ "./style.css": "./dist/style.css"
23
+ },
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "scripts": {
28
+ "dev": "vite",
29
+ "build": "vite build && vue-tsc -p tsconfig.build.json --emitDeclarationOnly",
30
+ "typecheck": "vue-tsc --noEmit",
31
+ "lint": "eslint src"
32
+ },
33
+ "dependencies": {
34
+ "gui-chat-protocol": "^0.0.1"
35
+ },
36
+ "devDependencies": {
37
+ "@tailwindcss/vite": "^4.1.0",
38
+ "@vitejs/plugin-vue": "^6.0.0",
39
+ "eslint": "^9.0.0",
40
+ "tailwindcss": "^4.1.0",
41
+ "typescript": "^5.8.0",
42
+ "vite": "^7.0.0",
43
+ "vue": "^3.5.0",
44
+ "vue-tsc": "^3.0.0"
45
+ },
46
+ "peerDependencies": {
47
+ "vue": "^3.5.0"
48
+ }
49
+ }