@gui-chat-plugin/text-response 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,87 @@
1
+ # @gui-chat-plugin/text-response
2
+
3
+ Text Response plugin for GUI Chat applications. Provides markdown rendering with role-based styling for displaying text content from assistants, users, and systems.
4
+
5
+ ## Features
6
+
7
+ - Markdown rendering with GitHub Flavored Markdown support
8
+ - Role-based styling (assistant, user, system)
9
+ - JSON auto-detection and syntax highlighting
10
+ - `<think>` block processing for AI reasoning display
11
+ - Inline text editing capability
12
+ - Transport kind indicator
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ yarn add @gui-chat-plugin/text-response
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Vue Integration
23
+
24
+ ```typescript
25
+ // In src/tools/index.ts
26
+ import TextResponsePlugin from "@gui-chat-plugin/text-response/vue";
27
+
28
+ const pluginList = [
29
+ // ... other plugins
30
+ TextResponsePlugin,
31
+ ];
32
+
33
+ // In src/main.ts
34
+ import "@gui-chat-plugin/text-response/style.css";
35
+ ```
36
+
37
+ ### Core-only Usage
38
+
39
+ ```typescript
40
+ import { executeTextResponse, TOOL_DEFINITION } from "@gui-chat-plugin/text-response";
41
+
42
+ // Execute the tool
43
+ const result = await executeTextResponse(context, {
44
+ text: "Hello, **world**!",
45
+ role: "assistant",
46
+ });
47
+ ```
48
+
49
+ ## API
50
+
51
+ ### TextResponseData
52
+
53
+ ```typescript
54
+ interface TextResponseData {
55
+ text: string;
56
+ role?: "assistant" | "system" | "user";
57
+ transportKind?: string;
58
+ }
59
+ ```
60
+
61
+ ### Tool Arguments
62
+
63
+ | Argument | Type | Required | Description |
64
+ |----------|------|----------|-------------|
65
+ | `text` | string | Yes | Plain text or markdown content to display |
66
+ | `role` | "assistant" \| "system" \| "user" | No | Speaker role for styling |
67
+ | `transportKind` | string | No | Identifier for the transport provider |
68
+
69
+ ## Development
70
+
71
+ ```bash
72
+ # Install dependencies
73
+ yarn install
74
+
75
+ # Run demo
76
+ yarn dev
77
+
78
+ # Build
79
+ yarn build
80
+
81
+ # Lint
82
+ yarn lint
83
+ ```
84
+
85
+ ## License
86
+
87
+ MIT
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Text Response Plugin - Tool Definition
3
+ */
4
+ import type { ToolDefinition } from "gui-chat-protocol";
5
+ export declare const TOOL_NAME = "text-response";
6
+ export declare const TOOL_DEFINITION: ToolDefinition;
7
+ export declare const SYSTEM_PROMPT = "";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Text Response Plugin - Core Entry Point
3
+ */
4
+ export type { TextResponseData, TextResponseArgs } from "./types";
5
+ export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT, executeTextResponse, pluginCore, } from "./plugin";
6
+ export { samples } from "./samples";
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Text Response Plugin Core
3
+ */
4
+ import type { ToolPluginCore, ToolContext, ToolResult } from "gui-chat-protocol";
5
+ import type { TextResponseData, TextResponseArgs } from "./types";
6
+ export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT } from "./definition";
7
+ export declare const executeTextResponse: (_context: ToolContext, args: TextResponseArgs) => Promise<ToolResult<TextResponseData, unknown>>;
8
+ export declare const pluginCore: ToolPluginCore<TextResponseData, unknown, TextResponseArgs>;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Text Response Plugin - Samples
3
+ */
4
+ import type { ToolSample } from "gui-chat-protocol";
5
+ export declare const samples: ToolSample[];
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Text Response Plugin - Type Definitions
3
+ */
4
+ export interface TextResponseData {
5
+ text: string;
6
+ role?: "assistant" | "system" | "user";
7
+ transportKind?: string;
8
+ }
9
+ export type TextResponseArgs = TextResponseData;
package/dist/core.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index.cjs");exports.SYSTEM_PROMPT=e.SYSTEM_PROMPT;exports.TOOL_DEFINITION=e.TOOL_DEFINITION;exports.TOOL_NAME=e.TOOL_NAME;exports.executeTextResponse=e.executeTextResponse;exports.pluginCore=e.pluginCore;exports.samples=e.samples;
package/dist/core.js ADDED
@@ -0,0 +1,9 @@
1
+ import { SYSTEM_PROMPT as T, TOOL_DEFINITION as o, TOOL_NAME as p, executeTextResponse as s, pluginCore as r, samples as t } from "./index.js";
2
+ export {
3
+ T as SYSTEM_PROMPT,
4
+ o as TOOL_DEFINITION,
5
+ p as TOOL_NAME,
6
+ s as executeTextResponse,
7
+ r as pluginCore,
8
+ t as samples
9
+ };
package/dist/index.cjs ADDED
@@ -0,0 +1,32 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t="text-response",s={type:"function",name:t,description:"Render plain text content from the assistant.",parameters:{type:"object",properties:{text:{type:"string",description:"Plain text content to display to the user."},role:{type:"string",enum:["assistant","system","user"],description:"Speaker role of the message."},transportKind:{type:"string",description:"Identifier for the transport or provider that produced the message."}},required:["text"]}},n="",a=async(i,e)=>({data:{text:e.text,role:e.role,transportKind:e.transportKind},message:e.text}),o={toolDefinition:s,execute:a,generatingMessage:"Processing...",isEnabled:()=>!1,systemPrompt:n},r=[{name:"Simple Text",args:{text:"Hello, this is a simple text response from the assistant.",role:"assistant"}},{name:"System Message",args:{text:"System: Configuration has been updated successfully.",role:"system"}},{name:"User Message",args:{text:"User: What is the weather like today?",role:"user"}},{name:"Markdown Content",args:{text:`# Markdown Example
2
+
3
+ This demonstrates **bold** and *italic* text.
4
+
5
+ ## Features
6
+ - List item 1
7
+ - List item 2
8
+ - List item 3
9
+
10
+ ### Code Example
11
+ \`\`\`javascript
12
+ function hello() {
13
+ console.log("Hello, World!");
14
+ }
15
+ \`\`\`
16
+
17
+ > This is a blockquote with important information.
18
+
19
+ | Column A | Column B |
20
+ |----------|----------|
21
+ | Data 1 | Data 2 |
22
+ | Data 3 | Data 4 |
23
+ `,role:"assistant"}},{name:"JSON Data",args:{text:JSON.stringify({name:"Example",version:"1.0.0",features:["markdown","json","roles"]},null,2),role:"assistant"}},{name:"Think Block",args:{text:`Let me analyze this problem.
24
+
25
+ <think>
26
+ First, I need to consider the requirements:
27
+ 1. The solution should be efficient
28
+ 2. It must handle edge cases
29
+ 3. Code should be readable
30
+ </think>
31
+
32
+ Based on my analysis, here's my recommendation...`,role:"assistant"}},{name:"With Transport",args:{text:"This response came from a specific transport provider.",role:"assistant",transportKind:"openai-realtime"}}];exports.SYSTEM_PROMPT=n;exports.TOOL_DEFINITION=s;exports.TOOL_NAME=t;exports.executeTextResponse=a;exports.pluginCore=o;exports.samples=r;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Text Response Plugin - Main Entry Point
3
+ */
4
+ export type { TextResponseData, TextResponseArgs } from "./core/types";
5
+ export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT, executeTextResponse, pluginCore, } from "./core/plugin";
6
+ export { samples } from "./core/samples";
package/dist/index.js ADDED
@@ -0,0 +1,136 @@
1
+ const t = "text-response", s = {
2
+ type: "function",
3
+ name: t,
4
+ description: "Render plain text content from the assistant.",
5
+ parameters: {
6
+ type: "object",
7
+ properties: {
8
+ text: {
9
+ type: "string",
10
+ description: "Plain text content to display to the user."
11
+ },
12
+ role: {
13
+ type: "string",
14
+ enum: ["assistant", "system", "user"],
15
+ description: "Speaker role of the message."
16
+ },
17
+ transportKind: {
18
+ type: "string",
19
+ description: "Identifier for the transport or provider that produced the message."
20
+ }
21
+ },
22
+ required: ["text"]
23
+ }
24
+ }, a = "", n = async (o, e) => ({
25
+ data: {
26
+ text: e.text,
27
+ role: e.role,
28
+ transportKind: e.transportKind
29
+ },
30
+ message: e.text
31
+ }), r = {
32
+ toolDefinition: s,
33
+ execute: n,
34
+ generatingMessage: "Processing...",
35
+ // Never advertise this pseudo tool to the LLM; only the client uses it.
36
+ isEnabled: () => !1,
37
+ systemPrompt: a
38
+ }, i = [
39
+ {
40
+ name: "Simple Text",
41
+ args: {
42
+ text: "Hello, this is a simple text response from the assistant.",
43
+ role: "assistant"
44
+ }
45
+ },
46
+ {
47
+ name: "System Message",
48
+ args: {
49
+ text: "System: Configuration has been updated successfully.",
50
+ role: "system"
51
+ }
52
+ },
53
+ {
54
+ name: "User Message",
55
+ args: {
56
+ text: "User: What is the weather like today?",
57
+ role: "user"
58
+ }
59
+ },
60
+ {
61
+ name: "Markdown Content",
62
+ args: {
63
+ text: `# Markdown Example
64
+
65
+ This demonstrates **bold** and *italic* text.
66
+
67
+ ## Features
68
+ - List item 1
69
+ - List item 2
70
+ - List item 3
71
+
72
+ ### Code Example
73
+ \`\`\`javascript
74
+ function hello() {
75
+ console.log("Hello, World!");
76
+ }
77
+ \`\`\`
78
+
79
+ > This is a blockquote with important information.
80
+
81
+ | Column A | Column B |
82
+ |----------|----------|
83
+ | Data 1 | Data 2 |
84
+ | Data 3 | Data 4 |
85
+ `,
86
+ role: "assistant"
87
+ }
88
+ },
89
+ {
90
+ name: "JSON Data",
91
+ args: {
92
+ text: JSON.stringify(
93
+ {
94
+ name: "Example",
95
+ version: "1.0.0",
96
+ features: ["markdown", "json", "roles"]
97
+ },
98
+ null,
99
+ 2
100
+ ),
101
+ role: "assistant"
102
+ }
103
+ },
104
+ {
105
+ name: "Think Block",
106
+ args: {
107
+ text: `Let me analyze this problem.
108
+
109
+ <think>
110
+ First, I need to consider the requirements:
111
+ 1. The solution should be efficient
112
+ 2. It must handle edge cases
113
+ 3. Code should be readable
114
+ </think>
115
+
116
+ Based on my analysis, here's my recommendation...`,
117
+ role: "assistant"
118
+ }
119
+ },
120
+ {
121
+ name: "With Transport",
122
+ args: {
123
+ text: "This response came from a specific transport provider.",
124
+ role: "assistant",
125
+ transportKind: "openai-realtime"
126
+ }
127
+ }
128
+ ];
129
+ export {
130
+ a as SYSTEM_PROMPT,
131
+ s as TOOL_DEFINITION,
132
+ t as TOOL_NAME,
133
+ n as executeTextResponse,
134
+ r as pluginCore,
135
+ i as samples
136
+ };
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-leading:initial;--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;--tw-outline-style:solid}}}@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-green-50:oklch(98.2% .018 155.826);--color-green-200:oklch(92.5% .084 155.995);--color-green-700:oklch(52.7% .154 150.069);--color-blue-50:oklch(97% .014 254.604);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-700:oklch(48.8% .243 264.376);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-200:oklch(87% .065 274.039);--color-indigo-700:oklch(45.7% .24 277.023);--color-purple-50:oklch(97.7% .014 308.299);--color-purple-200:oklch(90.2% .063 306.703);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--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-gray-900:oklch(21% .034 264.665);--color-white:#fff;--spacing:.25rem;--container-3xl:48rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-medium:500;--font-weight-bold:700;--leading-snug:1.375;--leading-relaxed:1.625;--radius-md:.375rem;--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}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-5{margin-bottom:calc(var(--spacing)*5)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.line-clamp-5{-webkit-line-clamp:5;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.h-96{height:calc(var(--spacing)*96)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-\[200px\]{max-width:200px}.max-w-none{max-width:none}.flex-shrink{flex-shrink:1}.border-collapse{border-collapse:collapse}.cursor-pointer{cursor:pointer}.resize{resize:both}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.gap-2{gap:calc(var(--spacing)*2)}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}.rounded{border-radius:.25rem}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-blue-200{border-color:var(--color-blue-200)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-green-200{border-color:var(--color-green-200)}.border-indigo-200{border-color:var(--color-indigo-200)}.border-purple-200{border-color:var(--color-purple-200)}.bg-blue-50{background-color:var(--color-blue-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-green-50{background-color:var(--color-green-50)}.bg-indigo-100{background-color:var(--color-indigo-100)}.bg-purple-50{background-color:var(--color-purple-50)}.bg-white{background-color:var(--color-white)}.p-5{padding:calc(var(--spacing)*5)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.px-4{padding-inline:calc(var(--spacing)*4)}.py-2{padding-block:calc(var(--spacing)*2)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.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)}.whitespace-pre-wrap{white-space:pre-wrap}.text-blue-700{color:var(--color-blue-700)}.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-gray-900{color:var(--color-gray-900)}.text-green-700{color:var(--color-green-700)}.text-indigo-700{color:var(--color-indigo-700)}.italic{font-style:italic}.shadow-md{--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)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px 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)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media(hover:hover){.hover\:bg-indigo-200:hover{background-color:var(--color-indigo-200)}}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@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}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}.markdown-content[data-v-298aef9f] h1{font-size:2rem;font-weight:700;margin-top:1em;margin-bottom:.5em}.markdown-content[data-v-298aef9f] h2{font-size:1.75rem;font-weight:700;margin-top:1em;margin-bottom:.5em}.markdown-content[data-v-298aef9f] h3{font-size:1.5rem;font-weight:700;margin-top:1em;margin-bottom:.5em}.markdown-content[data-v-298aef9f] h4{font-size:1.25rem;font-weight:700;margin-top:1em;margin-bottom:.5em}.markdown-content[data-v-298aef9f] h5{font-size:1.125rem;font-weight:700;margin-top:1em;margin-bottom:.5em}.markdown-content[data-v-298aef9f] h6{font-size:1rem;font-weight:700;margin-top:1em;margin-bottom:.5em}.markdown-content[data-v-298aef9f] p{margin-bottom:1em}.markdown-content[data-v-298aef9f] ul,.markdown-content[data-v-298aef9f] ol{margin-left:1.5em;margin-bottom:1em}.markdown-content[data-v-298aef9f] li{margin-bottom:.5em}.markdown-content[data-v-298aef9f] code{background-color:#f5f5f5;padding:.2em .4em;border-radius:3px;font-family:monospace;font-size:.9em}.markdown-content[data-v-298aef9f] pre{background-color:#f5f5f5;padding:1em;border-radius:4px;overflow-x:auto;margin-bottom:1em}.markdown-content[data-v-298aef9f] pre code{background-color:transparent;padding:0}.markdown-content[data-v-298aef9f] blockquote{border-left:4px solid #ddd;padding-left:1em;color:#666;margin:1em 0}.markdown-content[data-v-298aef9f] a{color:#2563eb;text-decoration:underline}.markdown-content[data-v-298aef9f] a:hover{color:#1d4ed8}.markdown-content[data-v-298aef9f] table{border-collapse:collapse;width:100%;margin-bottom:1em}.markdown-content[data-v-298aef9f] th,.markdown-content[data-v-298aef9f] td{border:1px solid #ddd;padding:.5em;text-align:left}.markdown-content[data-v-298aef9f] th{background-color:#f5f5f5;font-weight:700}.markdown-content[data-v-298aef9f] hr{border:none;border-top:1px solid #ddd;margin:1.5em 0}.markdown-content[data-v-298aef9f] .think-block{color:#6b7280;background-color:#f9fafb;border-left:3px solid #d1d5db;padding:.75em 1em;margin:1em 0;border-radius:4px;font-style:italic}.markdown-content[data-v-298aef9f] .think-block p{color:#6b7280}.markdown-content[data-v-298aef9f] .think-block code{background-color:#e5e7eb;color:#4b5563}.text-response-container[data-v-298aef9f]{display:flex;flex-direction:column;height:100%;overflow:hidden}.text-response-content-wrapper[data-v-298aef9f]{flex:1;overflow-y:auto}.text-response-source[data-v-298aef9f]{padding:.5rem;background:#f5f5f5;border-top:1px solid #e0e0e0;font-family:monospace;font-size:.85rem;flex-shrink:0}.text-response-source summary[data-v-298aef9f]{cursor:pointer;-webkit-user-select:none;user-select:none;padding:.5rem;background:#e8e8e8;border-radius:4px;font-weight:500;color:#333}.text-response-source[open] summary[data-v-298aef9f]{margin-bottom:.5rem}.text-response-source summary[data-v-298aef9f]:hover{background:#d8d8d8}.text-response-editor[data-v-298aef9f]{width:100%;height:40vh;padding:1rem;background:#fff;border:1px solid #ccc;border-radius:4px;color:#333;font-family:Courier New,monospace;font-size:.9rem;resize:vertical;margin-bottom:.5rem;line-height:1.5}.text-response-editor[data-v-298aef9f]:focus{outline:none;border-color:#4caf50;box-shadow:0 0 0 2px #4caf501a}.apply-btn[data-v-298aef9f]{padding:.5rem 1rem;background:#4caf50;color:#fff;border:none;border-radius:4px;cursor:pointer;font-size:.9rem;transition:background .2s;font-weight:500}.apply-btn[data-v-298aef9f]:hover{background:#45a049}.apply-btn[data-v-298aef9f]:active{background:#3d8b40}.apply-btn[data-v-298aef9f]:disabled{background:#ccc;color:#666;cursor:not-allowed;opacity:.6}.apply-btn[data-v-298aef9f]:disabled:hover{background:#ccc}
@@ -0,0 +1,8 @@
1
+ import type { ToolResultComplete } from "gui-chat-protocol/vue";
2
+ import type { TextResponseData } from "../core/types";
3
+ type __VLS_Props = {
4
+ result: ToolResultComplete<TextResponseData>;
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;
@@ -0,0 +1,12 @@
1
+ import type { ToolResult, ToolResultComplete } from "gui-chat-protocol/vue";
2
+ import type { TextResponseData } from "../core/types";
3
+ type __VLS_Props = {
4
+ selectedResult: ToolResultComplete<TextResponseData>;
5
+ };
6
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
7
+ updateResult: (result: ToolResult<unknown, unknown>) => any;
8
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
9
+ onUpdateResult?: ((result: ToolResult<unknown, unknown>) => any) | undefined;
10
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
+ declare const _default: typeof __VLS_export;
12
+ export default _default;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Text Response Plugin - Vue Implementation
3
+ */
4
+ import "../style.css";
5
+ import type { ToolPlugin } from "gui-chat-protocol/vue";
6
+ import type { TextResponseData, TextResponseArgs } from "../core/types";
7
+ import View from "./View.vue";
8
+ import Preview from "./Preview.vue";
9
+ export declare const plugin: ToolPlugin<TextResponseData, unknown, TextResponseArgs>;
10
+ export type { TextResponseData, TextResponseArgs } from "../core/types";
11
+ export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT, executeTextResponse, pluginCore, } from "../core/plugin";
12
+ export { samples } from "../core/samples";
13
+ export { View, Preview };
14
+ declare const _default: {
15
+ plugin: ToolPlugin<TextResponseData, unknown, TextResponseData, import("gui-chat-protocol/vue").InputHandler, Record<string, unknown>>;
16
+ };
17
+ export default _default;
package/dist/vue.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const o=require("./index.cjs"),e=require("vue"),v=require("marked"),y={class:"text-response-container"},w={class:"text-response-content-wrapper"},N={class:"p-6"},C={class:"max-w-3xl mx-auto space-y-4"},V={class:"flex justify-between items-start mb-2 text-sm text-gray-500"},O={class:"font-medium text-gray-700"},R={key:0,class:"italic"},S=["innerHTML"],M={class:"text-response-source"},I=["disabled"],L=e.defineComponent({__name:"View",props:{selectedResult:{}},emits:["updateResult"],setup(r,{emit:l}){const t=r,d=l,a=e.computed(()=>t.selectedResult.data?.text??""),c=e.ref(a.value);e.watch(()=>t.selectedResult.data?.text,s=>{s!==void 0&&(c.value=s)});const u=e.computed(()=>t.selectedResult.data?.role??"assistant"),p=e.computed(()=>t.selectedResult.data?.transportKind??""),h=e.computed(()=>{if(!a.value)return"";let s=a.value;const n=s.trim();if(n.startsWith("{")&&n.endsWith("}")||n.startsWith("[")&&n.endsWith("]"))try{JSON.parse(n),s="```json\n"+n+"\n```"}catch{}s=s.replace(/<think>([\s\S]*?)<\/think>/g,(A,T)=>`<div class="think-block">${v.marked(T.trim())}</div>`);const i={breaks:!0,gfm:!0};return v.marked(s,i)}),f=e.computed(()=>{switch(u.value){case"system":return"System";case"user":return"You";default:return"Assistant"}}),b=e.computed(()=>{switch(u.value){case"system":return"bg-blue-50 border-blue-200";case"user":return"bg-green-50 border-green-200";default:return"bg-purple-50 border-purple-200"}}),m=e.computed(()=>c.value!==a.value);function k(){}function E(){if(!m.value)return;const s={...t.selectedResult,data:{...t.selectedResult.data,text:c.value}};d("updateResult",s)}return(s,n)=>(e.openBlock(),e.createElementBlock("div",y,[e.createElementVNode("div",w,[e.createElementVNode("div",N,[e.createElementVNode("div",C,[e.createElementVNode("div",{class:e.normalizeClass(["rounded-lg border border-gray-300 bg-white shadow-sm p-5",b.value])},[e.createElementVNode("div",V,[e.createElementVNode("span",O,e.toDisplayString(f.value),1),p.value?(e.openBlock(),e.createElementBlock("span",R,e.toDisplayString(p.value),1)):e.createCommentVNode("",!0)]),e.createElementVNode("div",{class:"markdown-content prose prose-slate max-w-none leading-relaxed text-gray-900",innerHTML:h.value},null,8,S)],2)])])]),e.createElementVNode("details",M,[n[1]||(n[1]=e.createElementVNode("summary",null,"Edit Text Content",-1)),e.withDirectives(e.createElementVNode("textarea",{"onUpdate:modelValue":n[0]||(n[0]=i=>c.value=i),onInput:k,class:"text-response-editor",spellcheck:"false"},null,544),[[e.vModelText,c.value]]),e.createElementVNode("button",{onClick:E,class:"apply-btn",disabled:!m.value}," Apply Changes ",8,I)])]))}}),P=(r,l)=>{const t=r.__vccOpts||r;for(const[d,a]of l)t[d]=a;return t},_=P(L,[["__scopeId","data-v-298aef9f"]]),B={class:"line-clamp-5 whitespace-pre-wrap"},x=e.defineComponent({__name:"Preview",props:{result:{}},setup(r){const l=r,t=e.computed(()=>l.result.data?.text??""),d=e.computed(()=>l.result.data?.role??"assistant"),a=e.computed(()=>{switch(d.value){case"system":return"text-blue-700";case"user":return"text-green-700 font-medium";default:return"text-gray-700"}});return(c,u)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["text-sm leading-snug",a.value])},[e.createElementVNode("p",B,e.toDisplayString(t.value),1)],2))}}),g={...o.pluginCore,viewComponent:_,previewComponent:x,samples:o.samples},D={plugin:g};exports.SYSTEM_PROMPT=o.SYSTEM_PROMPT;exports.TOOL_DEFINITION=o.TOOL_DEFINITION;exports.TOOL_NAME=o.TOOL_NAME;exports.executeTextResponse=o.executeTextResponse;exports.pluginCore=o.pluginCore;exports.samples=o.samples;exports.Preview=x;exports.View=_;exports.default=D;exports.plugin=g;
package/dist/vue.js ADDED
@@ -0,0 +1,157 @@
1
+ import { samples as R, pluginCore as O } from "./index.js";
2
+ import { SYSTEM_PROMPT as ne, TOOL_DEFINITION as ae, TOOL_NAME as re, executeTextResponse as oe } from "./index.js";
3
+ import { defineComponent as f, computed as a, ref as E, watch as M, createElementBlock as d, openBlock as p, createElementVNode as e, normalizeClass as g, createCommentVNode as N, toDisplayString as m, withDirectives as S, vModelText as I } from "vue";
4
+ import { marked as h } from "marked";
5
+ const L = { class: "text-response-container" }, V = { class: "text-response-content-wrapper" }, P = { class: "p-6" }, W = { class: "max-w-3xl mx-auto space-y-4" }, A = { class: "flex justify-between items-start mb-2 text-sm text-gray-500" }, D = { class: "font-medium text-gray-700" }, H = {
6
+ key: 0,
7
+ class: "italic"
8
+ }, $ = ["innerHTML"], j = { class: "text-response-source" }, B = ["disabled"], K = /* @__PURE__ */ f({
9
+ __name: "View",
10
+ props: {
11
+ selectedResult: {}
12
+ },
13
+ emits: ["updateResult"],
14
+ setup(o, { emit: l }) {
15
+ const t = o, i = l, r = a(() => t.selectedResult.data?.text ?? ""), c = E(r.value);
16
+ M(
17
+ () => t.selectedResult.data?.text,
18
+ (s) => {
19
+ s !== void 0 && (c.value = s);
20
+ }
21
+ );
22
+ const u = a(
23
+ () => t.selectedResult.data?.role ?? "assistant"
24
+ ), v = a(
25
+ () => t.selectedResult.data?.transportKind ?? ""
26
+ ), b = a(() => {
27
+ if (!r.value) return "";
28
+ let s = r.value;
29
+ const n = s.trim();
30
+ if (n.startsWith("{") && n.endsWith("}") || n.startsWith("[") && n.endsWith("]"))
31
+ try {
32
+ JSON.parse(n), s = "```json\n" + n + "\n```";
33
+ } catch {
34
+ }
35
+ return s = s.replace(
36
+ /<think>([\s\S]*?)<\/think>/g,
37
+ (q, C) => `<div class="think-block">${h(C.trim())}</div>`
38
+ ), h(s, {
39
+ breaks: !0,
40
+ // Convert \n to <br>
41
+ gfm: !0
42
+ // GitHub Flavored Markdown
43
+ });
44
+ }), w = a(() => {
45
+ switch (u.value) {
46
+ case "system":
47
+ return "System";
48
+ case "user":
49
+ return "You";
50
+ default:
51
+ return "Assistant";
52
+ }
53
+ }), y = a(() => {
54
+ switch (u.value) {
55
+ case "system":
56
+ return "bg-blue-50 border-blue-200";
57
+ case "user":
58
+ return "bg-green-50 border-green-200";
59
+ default:
60
+ return "bg-purple-50 border-purple-200";
61
+ }
62
+ }), _ = a(() => c.value !== r.value);
63
+ function k() {
64
+ }
65
+ function T() {
66
+ if (!_.value) return;
67
+ const s = {
68
+ ...t.selectedResult,
69
+ data: {
70
+ ...t.selectedResult.data,
71
+ text: c.value
72
+ }
73
+ };
74
+ i("updateResult", s);
75
+ }
76
+ return (s, n) => (p(), d("div", L, [
77
+ e("div", V, [
78
+ e("div", P, [
79
+ e("div", W, [
80
+ e("div", {
81
+ class: g(["rounded-lg border border-gray-300 bg-white shadow-sm p-5", y.value])
82
+ }, [
83
+ e("div", A, [
84
+ e("span", D, m(w.value), 1),
85
+ v.value ? (p(), d("span", H, m(v.value), 1)) : N("", !0)
86
+ ]),
87
+ e("div", {
88
+ class: "markdown-content prose prose-slate max-w-none leading-relaxed text-gray-900",
89
+ innerHTML: b.value
90
+ }, null, 8, $)
91
+ ], 2)
92
+ ])
93
+ ])
94
+ ]),
95
+ e("details", j, [
96
+ n[1] || (n[1] = e("summary", null, "Edit Text Content", -1)),
97
+ S(e("textarea", {
98
+ "onUpdate:modelValue": n[0] || (n[0] = (x) => c.value = x),
99
+ onInput: k,
100
+ class: "text-response-editor",
101
+ spellcheck: "false"
102
+ }, null, 544), [
103
+ [I, c.value]
104
+ ]),
105
+ e("button", {
106
+ onClick: T,
107
+ class: "apply-btn",
108
+ disabled: !_.value
109
+ }, " Apply Changes ", 8, B)
110
+ ])
111
+ ]));
112
+ }
113
+ }), Y = (o, l) => {
114
+ const t = o.__vccOpts || o;
115
+ for (const [i, r] of l)
116
+ t[i] = r;
117
+ return t;
118
+ }, z = /* @__PURE__ */ Y(K, [["__scopeId", "data-v-298aef9f"]]), F = { class: "line-clamp-5 whitespace-pre-wrap" }, J = /* @__PURE__ */ f({
119
+ __name: "Preview",
120
+ props: {
121
+ result: {}
122
+ },
123
+ setup(o) {
124
+ const l = o, t = a(() => l.result.data?.text ?? ""), i = a(() => l.result.data?.role ?? "assistant"), r = a(() => {
125
+ switch (i.value) {
126
+ case "system":
127
+ return "text-blue-700";
128
+ case "user":
129
+ return "text-green-700 font-medium";
130
+ default:
131
+ return "text-gray-700";
132
+ }
133
+ });
134
+ return (c, u) => (p(), d("div", {
135
+ class: g(["text-sm leading-snug", r.value])
136
+ }, [
137
+ e("p", F, m(t.value), 1)
138
+ ], 2));
139
+ }
140
+ }), U = {
141
+ ...O,
142
+ viewComponent: z,
143
+ previewComponent: J,
144
+ samples: R
145
+ }, ee = { plugin: U };
146
+ export {
147
+ J as Preview,
148
+ ne as SYSTEM_PROMPT,
149
+ ae as TOOL_DEFINITION,
150
+ re as TOOL_NAME,
151
+ z as View,
152
+ ee as default,
153
+ oe as executeTextResponse,
154
+ U as plugin,
155
+ O as pluginCore,
156
+ R as samples
157
+ };
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@gui-chat-plugin/text-response",
3
+ "version": "0.1.0",
4
+ "description": "Text Response plugin for GUI Chat - Markdown rendering with role-based styling",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./core": {
16
+ "types": "./dist/core/index.d.ts",
17
+ "import": "./dist/core.js",
18
+ "require": "./dist/core.cjs"
19
+ },
20
+ "./vue": {
21
+ "types": "./dist/vue/index.d.ts",
22
+ "import": "./dist/vue.js",
23
+ "require": "./dist/vue.cjs"
24
+ },
25
+ "./style.css": "./dist/style.css"
26
+ },
27
+ "files": ["dist"],
28
+ "scripts": {
29
+ "dev": "vite",
30
+ "build": "vite build && vue-tsc -p tsconfig.build.json --emitDeclarationOnly",
31
+ "typecheck": "vue-tsc --noEmit",
32
+ "lint": "eslint src demo"
33
+ },
34
+ "peerDependencies": {
35
+ "vue": "^3.5.0"
36
+ },
37
+ "dependencies": {
38
+ "gui-chat-protocol": "^0.0.1",
39
+ "marked": "^15.0.0"
40
+ },
41
+ "devDependencies": {
42
+ "@tailwindcss/vite": "^4.1.18",
43
+ "@typescript-eslint/eslint-plugin": "^8.53.0",
44
+ "@typescript-eslint/parser": "^8.53.0",
45
+ "@vitejs/plugin-vue": "^6.0.3",
46
+ "eslint": "^9.39.2",
47
+ "eslint-plugin-vue": "^10.6.2",
48
+ "globals": "^17.0.0",
49
+ "tailwindcss": "^4.1.18",
50
+ "typescript": "~5.9.3",
51
+ "vite": "^7.3.1",
52
+ "vue": "^3.5.26",
53
+ "vue-eslint-parser": "^10.2.0",
54
+ "vue-tsc": "^3.2.2"
55
+ },
56
+ "keywords": ["guichat", "plugin", "text-response", "markdown"],
57
+ "license": "MIT"
58
+ }