Feedback Package
Provides tools for human-in-the-loop interactions in AI workflows, allowing agents to pause execution, present information to users, and collect feedback through chat-based questioning and browser-based reviews.
Package Reference
Package Name: @tokenring-ai/feedback
Version: 0.2.0
License: MIT
Overview
The feedback package enables AI agents to interact with humans during execution through three primary mechanisms:
- Interactive Chat Questioning: Ask multiple questions via chat with support for text responses or multiple-choice options using structured form inputs
- Browser-Based File Review: Display file contents (text, Markdown, HTML, JSON) in browser UIs for approval/rejection with optional comments
- React Component Preview: Bundle and preview React components in browsers for visual feedback and approval
This package is designed for task uncertainty resolution, approval workflows, and interactive content review scenarios where human input is needed before proceeding.
Installation
bun add @tokenring-ai/feedback
Package Structure
pkg/feedback/
├── index.ts # Main entry point (currently empty)
├── plugin.ts # Plugin registration
├── tools.ts # Tool exports aggregator
├── tools/ # Core tool implementations
│ ├── askQuestions.ts # Interactive questioning tool
│ ├── getFileFeedback.ts # File content review tool
│ └── react-feedback.ts # React component preview tool
├── package.json # Package metadata and dependencies
├── vitest.config.ts # Testing configuration
├── BRAINSTORM.md # Feature brainstorming document
└── README.md # Package documentation
Core Tools
1. Feedback/askQuestions
Interactive questioning tool that presents form-based questions to users with optional multiple-choice options and freeform text responses.
Tool Name: ask_questions
Tool Display: Feedback/askQuestions
Description: Use this tool when human feedback is needed or when you're uncertain about the proper path to complete a task. It provides a strong guarantee that decisions align with user intent. You can ask one or more questions, and you can also provide choices for the user to choose from for each one. The user will either pick one of these choices, or respond with their own answer if none of the options are aligned with their intent.
Input Schema (Zod):
z.object({
message: z.string().describe("A free-form, paragraph sized message, explaining the problem you are facing, or the uncertainty you have about the task."),
questions: z.array(z.object({
question: z.string().describe("A question to ask the human, such as something to clarify, or to get additional information on."),
choices: z.array(z.string()).describe("Suggested choices for the human to select from. The human can choose from any of these options or provide their own response.")
}))
})
Input Parameters:
- message (string): Required - Free-form paragraph explaining the problem or uncertainty
- questions (array): Required - Array of question objects
- question (string): Required - The specific question to ask
- choices (string[]): Required - Suggested choices for the user to select from (can be empty for freeform responses)
Browser Response Format:
The tool uses the agent's askQuestion API with a form-based interface. Users can:
- Select from provided choices (treeSelect)
- Provide freeform text responses (text input)
- Choose "Other" to provide custom answers for multiple-choice questions
Example Usage:
import askQuestions from "@tokenring-ai/feedback/tools/askQuestions";
// Single question with choices
const result = await askQuestions.execute({
message: "I'm unsure about the best approach for this feature.",
questions: [
{
question: "Which implementation method do you prefer?",
choices: ["Method A", "Method B", "Method C"]
}
]
}, agent);
// Ask multiple questions
const result = await askQuestions.execute({
message: "I need information to complete this task properly.",
questions: [
{
question: "What is the priority level?",
choices: ["High", "Medium", "Low"]
},
{
question: "What is the deadline?",
choices: ["Urgent", "Within week", "Flexible"]
}
]
}, agent);
// Ask a question without choices (freeform response)
const result = await askQuestions.execute({
message: "I need additional information about the requirements.",
questions: [
{
question: "What specific details do you need to provide?",
choices: [] // Empty choices array allows freeform input
}
]
}, agent);
Response Format:
Returns a formatted string with the user's responses:
The user has provided the following responses:
Question 1
Answer 1
Question 2
Answer 2
Implementation Details:
- Form-based questions using agent's
askQuestionAPI - Supports both
treeSelect(for choices) andtext(for freeform) input types - Users can select from choices or choose "Other (Will open a text box for a freeform answer)" for freeform input
- Empty choices array creates text input for freeform responses
- Questions are collected iteratively until all are answered
- If a user doesn't provide an answer, returns "The user did not provide an answer, use your own judgement"
- If user doesn't respond at all, throws error: "The user did not respond to the question prompt. Stop what you are doing. Do not call any more tools until the user gives you further instructions."
- Question items are dynamically transformed: choices → treeSelect, no choices → text
Behavior:
- If choices are provided, users can select one option or choose "Other" for freeform input
- If no choices are provided, users can type freeform responses
- The tool continues asking questions until all are answered
- If a user doesn't provide an answer, the agent uses its own judgment
- Uses agent's
askQuestionAPI with form-based questions and treeSelect/text fields
Error Handling:
- Throws error if user doesn't respond to question prompt at all
- Returns default message if user doesn't provide answer to specific question
- Validates that at least one question is provided
2. Feedback/getFileFeedback
Browser-based file content review tool that displays file contents (text, Markdown, HTML, JSON) in an interactive UI for user approval/rejection with optional comments.
Tool Name: feedback_getFileFeedback
Tool Display: Feedback/getFileFeedback
Description: This tool allows you to present the content of a file to the user, solicit feedback (accept/reject with comments), and optionally write the content to a specified file path if accepted. If the contentType is text/markdown or text/x-markdown, the content will be rendered as HTML for review. Creates a browser-based UI the user can review and leave comments on.
Input Schema (Zod):
z.object({
filePath: z.string().describe("The path where the file content should be saved if accepted."),
content: z.string().describe("The actual text content to be reviewed."),
contentType: z.string()
.describe("Optional. The MIME type of the content (e.g., 'text/plain', 'text/html', 'application/json', 'text/markdown', 'text/x-markdown'). Defaults to 'text/plain'. If 'text/markdown' or 'text/x-markdown', content is rendered as HTML for review. Used for browser rendering.")
.default("text/plain")
}).strict()
Input Parameters:
- filePath (string): Required - Path where content should be saved if accepted
- content (string): Required - The actual text content to be reviewed
- contentType (string, optional): MIME type for content rendering. Defaults to
text/plain. Options:text/plain: Plain text with HTML escapingtext/markdown,text/x-markdown: Markdown rendered to HTML using marked.jstext/html: Raw HTML content rendered in iframe (saved to separate file)application/json: JSON formatted with syntax highlighting
Supported Content Types:
text/plain: Plain text display with HTML escapingtext/markdown,text/x-markdown: Markdown rendering using marked.js librarytext/html: Raw HTML content rendered in iframe (content saved touser_content.html)application/json: JSON formatted with HTML escaping in pre tag
Browser Response Format:
{
type: "json",
data: {
status: "accepted" | "rejected",
comment?: string, // User's comment if provided
filePath?: string, // Path where content was saved (if accepted)
rejectedFilePath?: string // Original filePath (if rejected)
}
}
Example Usage:
import getFileFeedback from "@tokenring-ai/feedback/tools/getFileFeedback";
// Review Markdown content
const result = await getFileFeedback.execute({
filePath: "docs/sample.md",
content: "# Sample Markdown\nThis is **bold** text.",
contentType: "text/markdown"
}, agent);
// Review JSON content
const result = await getFileFeedback.execute({
filePath: "config/settings.json",
content: JSON.stringify({ theme: "dark", language: "en" }, null, 2),
contentType: "application/json"
}, agent);
// Review HTML content
const result = await getFileFeedback.execute({
filePath: "templates/page.html",
content: "<h1>Welcome</h1><p>This is HTML content.</p>",
contentType: "text/html"
}, agent);
// Review plain text
const result = await getFileFeedback.execute({
filePath: "README.txt",
content: "This is plain text content.",
contentType: "text/plain"
}, agent);
Response Handling:
if (result.data.status === "accepted") {
// Content successfully saved to filePath
console.log("Content accepted:", result.data.filePath);
if (result.data.comment) {
console.log("User comment:", result.data.comment);
}
} else {
// Content saved with rejected suffix
console.log("Content rejected:", result.data.rejectedFilePath);
if (result.data.comment) {
console.log("User comment:", result.data.comment);
}
}
Implementation Details:
- Temporary Directory: Creates temp directory with prefix
file-feedback- - HTML Content Handling: For
text/htmlcontent type, writes content touser_content.htmlin temp directory - Review UI Generation: Generates HTML review page with:
- Accept/Reject buttons at top of page
- Comment textarea for user feedback
- Content display area with appropriate rendering
- Express Server: Starts HTTP server to serve the review UI
- Browser Launch: Automatically launches browser using
openpackage - Content Rendering:
- Markdown: Uses
marked.jslibrary for HTML conversion with CSS styling - HTML: Renders in iframe referencing
user_content.htmlfor proper isolation - JSON: Pre-formatted display with HTML escaping
- Plain text: Safe HTML escaping for display
- Markdown: Uses
- File Operations:
- If accepted: Saves content to specified
filePathusing FileSystemService - If rejected: Saves content with
.rejectedyyyyMMdd-HHmmsssuffix (e.g.,file.rejected20240115-143022.txt)
- If accepted: Saves content to specified
- Cleanup: Automatically removes temporary directory and stops server
- Error Handling: Throws error if required parameters are missing; cleanup errors are logged but don't stop execution
Error Handling:
- Throws error if
filePathorcontentparameters are missing - Cleanup errors are caught and logged but don't stop execution
- Server startup errors are logged with fallback URL reporting
3. Feedback/react-feedback
React component preview tool that bundles and renders React components in a browser for visual review and user feedback.
Tool Name: feedback_react-feedback
Tool Display: Feedback/react-feedback
Description: This tool lets you solicit feedback from the user, by opening a browser window, where you can show them an HTML document (formatted in JSX, to be rendered via React), and then allows them to accept or reject the document, and optionally add comments, which are then returned to you as a result. Bundles React components and renders them in the browser for visual review.
Input Schema (Zod):
z.object({
code: z.string().describe("The complete source code of the React component to be previewed. This should be valid JSX/TSX that can be bundled and rendered in the browser."),
file: z.string().optional().describe("The filename/path of the React component to be previewed")
}).strict()
Input Parameters:
- code (string): Required - Complete source code of React component to preview (valid JSX/TSX)
- file (string, optional): Filename/path of the React component. Defaults to auto-generated timestamped name:
React-Component-Preview-{ISO timestamp}.tsx
Browser Response Format:
// Accepted response
{
type: "json",
data: {
status: "accept",
comment?: string
}
}
// Rejected response
{
type: "json",
data: {
status: "reject" | "rejected",
comment?: string
}
}
Example Usage:
import reactFeedback from "@tokenring-ai/feedback/tools/react-feedback";
const jsxCode = `
import React from 'react';
export default function MyComponent() {
return (
<div style={{ padding: '20px', border: '1px solid #ccc' }}>
<h1>Hello, Feedback!</h1>
<p>This component can be reviewed and accepted or rejected.</p>
</div>
);
}
`;
const result = await reactFeedback.execute({
code: jsxCode,
file: "src/components/MyComponent.tsx"
}, agent);
Response Handling:
if (result.data.status === "accept") {
// Component saved to configured location
console.log("Component accepted");
if (result.data.comment) {
console.log("User comment:", result.data.comment);
}
} else {
// Component saved with rejected suffix
console.log("Component rejected");
if (result.data.comment) {
console.log("User comment:", result.data.comment);
}
}
Implementation Details:
- Temporary Directory: Creates temp directory with prefix
react-preview- - File Creation: Writes component code to temp directory with specified filename or timestamped name
- Component Bundling: Uses esbuild to bundle React component:
- Entry point: Component file in temp directory
- Output:
bundle.tsin temp directory - JSX transformation: Automatic mode
- Platform: Browser
- External dependencies:
react,react-dom,react/jsx-runtime - Global name:
window.App - Plugin:
esbuild-plugin-external-globalfor external globals
- HTML Wrapper: Generates HTML page that:
- Loads React 18 development builds from CDN (
https://unpkg.com/react@18/umd/react.development.ts) - Loads React DOM 18 from CDN (
https://unpkg.com/react-dom@18/umd/react-dom.development.ts) - Defines
window.JSXwithReact.createElementfor JSX runtime - Loads bundled component
- Renders component using
ReactDOM.createRoot - Includes styled overlay with Accept/Reject buttons and comment textarea
- Loads React 18 development builds from CDN (
- Review UI Features:
- Fixed overlay at top with Accept/Reject buttons
- Comment textarea (5 rows height)
- Styled with yellow theme for submit button
- Alert notification on submission
- Express Server: Starts HTTP server to serve the preview
- Browser Launch: Automatically opens browser to preview page
- File Operations:
- If accepted: Saves component code to specified
filepath using FileSystemService - If rejected: Saves component with
.rejectedyyyyMMdd-HH:mmsuffix (e.g.,component.rejected20240115-14:30.tsx)
- If accepted: Saves component code to specified
- Cleanup: Removes temporary directory and stops server
- Error Handling: Throws error if
codeparameter is missing
Bundling Configuration:
await esbuild.build({
entryPoints: [jsxPath],
outfile: bundlePath,
bundle: true,
jsx: "automatic",
platform: "browser",
external: ["react", "react-dom", "react/jsx-runtime"],
globalName: "window.App",
plugins: [
externalGlobalPlugin({
react: "window.React",
"react-dom": "window.ReactDOM",
"react/jsx-runtime": "window.JSX",
jQuery: "$"
})
]
});
CDN Resources:
- React 18 development:
https://unpkg.com/react@18/umd/react.development.ts - React DOM 18 development:
https://unpkg.com/react-dom@18/umd/react-dom.development.ts - JSX runtime:
window.JSX = { "jsx": React.createElement, "jsxs": React.createElement }
Error Handling:
- Throws error if
codeparameter is missing - Cleanup errors are not explicitly caught (temporary directory is removed after file operations)
Plugin Configuration
The package uses a minimal configuration schema that accepts no custom configuration options.
Plugin Registration:
import {TokenRingPlugin} from "@tokenring-ai/app";
import {ChatService} from "@tokenring-ai/chat";
import {z} from "zod";
import packageJSON from './package.json' with {type: 'json'};
import tools from "./tools.ts";
const packageConfigSchema = z.object({});
export default {
name: packageJSON.name,
version: packageJSON.version,
description: packageJSON.description,
install(app, config) {
app.waitForService(ChatService, chatService =>
chatService.addTools(tools)
);
},
config: packageConfigSchema
} satisfies TokenRingPlugin<typeof packageConfigSchema>;
Configuration Schema
const packageConfigSchema = z.object({});
// No configuration options available
Required Services
The package requires the following services to be registered:
- ChatService: Required for tool registration
- FileSystemService: Required by getFileFeedback and reactFeedback for file operations
- Agent: Required for logging and service access
Key Features
Human-in-the-Loop Workflows
- Uncertainty Resolution: Ask questions when unsure about task approach or requirements
- Approval Systems: Get user approval for code, content, or configurations
- Feedback Collection: Gather freeform or structured user feedback
Multiple Question Types
- Form-based Questions: Structured questions with treeSelect for multiple-choice options
- Freeform Responses: Unstructured text inputs for open-ended questions
- Multi-question Workflows: Collect multiple questions in single interaction
- Iterative Questioning: Clear previously asked questions as they're answered
Rich Content Review
- Multiple Content Types: Support for plain text, Markdown, HTML, and JSON
- Smart Rendering: Appropriate rendering for each content type
- Interactive UI: Browser-based review interface with Accept/Reject buttons
- Comment System: Optional user comments with final feedback
- Visual Preview: React component preview with proper bundling and rendering
Automatic Operations
- Browser Launch: Automatically opens browser for review
- Temporary Files: Creates and cleans up temporary directories
- Server Management: Runs and stops preview servers as needed
- File Operations: Saves accepted or rejected content automatically
- Error Logging: Graceful error handling with agent logging
Integration Pattern
- Tool-based Integration: Simple tool registration via ChatService
- Auto-registration: Tools automatically registered when plugin installs
- Service Access: Uses agent's service requirement pattern
- Logging Integration: Message logging with tool name prefixes
- Type Safety: Full TypeScript support with Zod schema validation
Tools Export
Tool Registration
Tools are registered via the plugin system when the package is installed:
app.waitForService(ChatService, chatService =>
chatService.addTools(tools)
);
Where tools is exported from tools.ts:
import askQuestions from "./tools/askQuestions.ts";
import getFileFeedback from "./tools/getFileFeedback.js";
import reactFeedback from "./tools/react-feedback.js";
export default {
askQuestions,
getFileFeedback,
reactFeedback,
};
Each tool follows the TokenRingToolDefinition pattern with:
- name: Internal tool name
- displayName: Formatted as "Category/ToolName"
- description: Detailed explanation of functionality
- inputSchema: Zod schema for validation
- execute: Async function that performs the tool's action
Tool Interface
All tools export the following structure:
export default {
name: "tool_name",
displayName: "Category/ToolName",
description: "Tool description",
inputSchema: z.object({ ... }),
execute: async (params, agent) => { ... }
} satisfies TokenRingToolDefinition<typeof inputSchema>;
RPC Endpoints
This package does not define any RPC endpoints.
Chat Commands
This package does not define any chat commands.
Agent Configuration
The feedback package integrates with the Token Ring agent system through its tools. The tools expect an Agent instance to access services, logging, and human interaction capabilities.
Required Services
The following services must be available for the tools to function:
- ChatService: Required for tool registration (handled by plugin)
- FileSystemService: Required by getFileFeedback and reactFeedback for file operations
- Agent: Required for logging, service access, and human interaction via
askQuestionAPI
Service Access Pattern
import Agent from "@tokenring-ai/agent/Agent";
import { FileSystemService } from "@tokenring-ai/filesystem";
async function execute(params: unknown, agent: Agent) {
// Access required services
const fileSystem = agent.requireServiceByType(FileSystemService);
// Use agent logging
agent.infoMessage(`[tool-name] Operation started`);
agent.infoMessage(`[tool-name] File review server running at ${url}`);
agent.errorMessage(`[tool-name] Operation failed:`, error);
// Use agent question API
const response = await agent.askQuestion({...});
}
Dependencies
Runtime Dependencies
@tokenring-ai/app@0.2.0- Base application framework@tokenring-ai/chat@0.2.0- Chat service@tokenring-ai/agent@0.2.0- Agent system and question schema@tokenring-ai/filesystem@0.2.0- File system servicezod@^4.3.6- Schema validationesbuild@^0.27.4- React component bundlingesbuild-plugin-external-global@^1.0.1- External global plugin for esbuildexpress@^5.2.1- Web server for previewmarked@^17.0.4- Markdown renderingdate-fns@^4.1.0- Date formattingdate-fns-tz@^3.2.0- Time zone supportopen@^11.0.0- Browser launcherreact@^19.2.4- React library (package dependency, but uses React 18 from CDN for browser previews)react-dom@^19.2.4- React DOM library (package dependency, but uses React DOM 18 from CDN for browser previews)
Development Dependencies
typescript@^5.9.3- TypeScript compiler@types/express@^5.0.6- Express type definitionsvitest@^4.1.0- Testing framework
Error Handling
All tools follow consistent error handling patterns:
Parameter Validation
// askQuestions: Validates that at least one question is provided
if (questionItems.size === 0) {
return "You did not provide any questions, please provide at least one question to ask the user.";
}
// getFileFeedback: Validates filePath and content are provided
if (!filePath || !content) {
throw new Error(
`[feedback_getFileFeedback] filePath and content are required parameters for getFileFeedback.`
);
}
// reactFeedback: Validates code is provided
if (!code) {
throw new Error(`[feedback_react-feedback] code is required parameter for react-feedback.`);
}
Graceful Failure
- Invalid input parameters: Throws errors with descriptive messages
- File system operations: Handle errors with logging without crashing
- Server startup: Log errors and fall back to URL reporting
- Cleanup operations:
getFileFeedback: Caught errors are logged but don't stop executionreact-feedback: Cleanup errors are not explicitly caught
Error Types
- Validation Errors: Missing required parameters or invalid input types
- File System Errors: File I/O operations, permissions, path validation
- Network Errors: Server startup, browser launch, HTTP requests
- Build Errors: React component bundling failures (esbuild errors)
- Agent Errors: Service integration issues
Integration Patterns
Service Access
// Access required services
const fileSystem = agent.requireServiceByType(FileSystemService);
// Use agent logging for tool execution
agent.infoMessage(`[tool-name] Operation started`);
agent.infoMessage(`[tool-name] File review server running at ${url}`);
agent.errorMessage(`[tool-name] Operation failed:`, error);
Tool Registration
Tools are registered via the plugin system:
app.waitForService(ChatService, chatService =>
chatService.addTools(tools)
);
Where tools exports individual tool definitions with the proper structure:
export default {
name: "tool_name",
displayName: "Category/name",
description: "Tool description",
inputSchema: z.object({ ... }),
execute: async (params, agent) => { ... }
};
Usage Examples
Basic Question Prompting
import askQuestions from "@tokenring-ai/feedback/tools/askQuestions";
// When uncertain about approach
const result = await askQuestions.execute({
message: "I'm uncertain about which implementation strategy to use for the data processing pipeline.",
questions: [
{
question: "What is your priority concern?",
choices: ["Performance efficiency", "Code simplicity", "Maintainability", "Scalability"]
}
]
}, agent);
console.log(result);
// Returns: "The user has provided the following responses:\nQuestion 1\nPerformance efficiency"
Requirement Gathering
const requirements = await askQuestions.execute({
message: "I need to understand the requirements for the new feature before implementation.",
questions: [
{
question: "Who are the primary users of this feature?",
choices: ["Internal team", "External customers", "Partners", "Multiple groups"]
},
{
question: "What are the required performance characteristics?",
choices: ["Fast iteration", "High throughput", "Low latency", "Scalable"]
},
{
question: "What level of customization is needed?",
choices: [] // Freeform
}
]
}, agent);
File Approval Workflow
import getFileFeedback from "@tokenring-ai/feedback/tools/getFileFeedback";
// Before committing documentation
const result = await getFileFeedback.execute({
filePath: "docs/api-endpoint-v2.md",
content: "# API Endpoints\n\n## User\n\nGET /api/v2/users...",
contentType: "text/markdown"
}, agent);
if (result.data.status === "accepted") {
// Commit approved documentation
await gitCommit(`docs/api-endpoint-v2.md`);
}
React Component Review
import reactFeedback from "@tokenring-ai/feedback/tools/react-feedback";
// Before integrating new UI component
const componentCode = `
export default function NewSidebar() {
return (
<nav style={{
width: '250px',
height: '100vh',
backgroundColor: '#f5f5f5',
padding: '20px'
}}>
<h3>Sidebar</h3>
</nav>
);
}
`;
const result = await reactFeedback.execute({
code: componentCode,
file: "src/components/NewSidebar.tsx"
}, agent);
// Handle acceptance
if (result.data.status === "accept") {
console.log("Component approved for integration");
}
Multi-step Human Approval
// Step 1: Get requirements
const requirements = await askQuestions.execute({
message: "I need specifications for the new feature.",
questions: [{
question: "What is the main purpose of this feature?",
choices: [] // More complex questions
}]
}, agent);
// Step 2: Approve implementation plan
const planResult = await getFileFeedback.execute({
filePath: "docs/implementation-plan.md",
content: generateImplementationPlan(requirements),
contentType: "text/markdown"
}, agent);
// Step 3: Approve code implementation
const codeResult = await reactFeedback.execute({
code: implementationCode,
file: "src/components/Feature.tsx"
}, agent);
// Continue only if all approvals are received
if (planResult.data.status === "accepted" && codeResult.data.status === "accept") {
// Proceed with implementation
}
Best Practices
When to Use askQuestions
✅ Use when:
- Uncertainty exists about task direction or requirements
- You're worried about making incorrect decisions
- You need clarification from stakeholders
- Multiple options exist and you need user input
- Complex requirements need breaking down
❌ Don't use when:
- Clear requirements are already established
- Automatic execution without human approval is acceptable
- You want exact implementation details without guidance
Validation Strategies
Always validate input parameters before tool execution:
// Example parameter validation
const { message, questions } = params;
if (!message || typeof message !== "string") {
throw new Error("[ask_questions] message is required and must be a string");
}
if (!questions || !Array.isArray(questions)) {
throw new Error("[ask_questions] questions is required and must be an array");
}
questions.forEach(q => {
if (!q.question || typeof q.question !== "string") {
throw new Error("[ask_questions] Each question must have a question field");
}
});
Error Handling
Implement comprehensive error handling:
try {
const result = await execute(params, agent);
agent.infoMessage(`[tool-name] Success:`, result);
return result;
} catch (error) {
agent.errorMessage(`[tool-name] Execution failed:`, error);
throw error; // Re-throw for caller handling
}
Feedback Workflows
Design workflows with clear user expectations:
- Clarify Uncertainty: Use askQuestions to gather requirements
- Get Approval: Use getFileFeedback or reactFeedback for content review
- Log Results: Document user feedback using agent logging
- Decide Next Action: Based on user input, proceed or iteratively improve
Component Review Best Practices
- Provide clear context in the code explaining purpose and usage
- Include proper TypeScript types and interfaces
- Test components in various display scenarios
- Consider accessibility when designing review UIs
- Keep component code focused and reusable
Content Review Best Practices
- Format JSON with proper indentation and syntax highlighting
- Use appropriate MIME types for content types
- Document expected format and structure
- Include examples where possible
- Handle edge cases and error scenarios
Testing
Tool Testing Strategy
import {describe, it, expect} from "vitest";
import askQuestionsTool from "./tools/askQuestions.ts";
describe("Feedback Tools", () => {
describe("askQuestions", () => {
it("should throw error if message is missing", async () => {
await expect(
askQuestionsTool.execute(
{message: "", questions: []},
mockAgent
)
).rejects.toThrow();
});
it("should process single choice question", async () => {
const result = await askQuestionsTool.execute(
{
message: "Select option",
questions: [{ question: "Choose", choices: ["A", "B"] }]
},
mockAgent
);
expect(result).toBeDefined();
});
});
describe("getFileFeedback", () => {
it("should throw error if file path is missing", async () => {
await expect(
getFileFeedbackTool.execute(
{content: "", filePath: ""},
mockAgent
)
).rejects.toThrow();
});
});
describe("reactFeedback", () => {
it("should throw error if code is missing", async () => {
await expect(
reactFeedbackTool.execute(
{code: "", file: "test.tsx"},
mockAgent
)
).rejects.toThrow();
});
});
});
Integration Testing
Test service integration and flow coordination:
describe("Feedback Integration Tests", () => {
it("should coordinate multi-step feedback workflow", async () => {
// Step 1: Ask questions
const questions = await askQuestions.execute({...}, agent);
// Step 2: Get file feedback
const file = await getFileFeedback.execute({...}, agent);
// Step 3: Get component feedback
const component = await reactFeedback.execute({...}, agent);
expect(questions).toBeDefined();
expect(file).toBeDefined();
expect(component).toBeDefined();
});
});
Testing Structure
- Uses vitest for testing
- Tests are located in
**/*.test.tsfiles - Node environment for test execution
- Isolated test runs with globals enabled
Test Configuration
The package uses the following vitest configuration:
import {defineConfig} from "vitest/config";
export default defineConfig({
test: {
include: ["**/*.test.ts"],
environment: "node",
globals: true,
isolate: true,
},
});
Development
Building
# Build the package TypeScript files (no Emit)
bun run build
Testing
# Run tests
bun run test
# Run tests in watch mode
bun run test:watch
# Run tests with coverage
bun run test:coverage
Related Components
Dependent Packages
@tokenring-ai/chat: Required for ChatService integration@tokenring-ai/app: Required for TokenRingPlugin abstraction@tokenring-ai/agent: Required for Agent, askQuestion API, question schemas@tokenring-ai/filesystem: Required for file operations in feedback tools
Related Tools
- Chat Service Tools: Other tools available through ChatService integration
- Code Review Tools: Complementary tools for code validation
Documentation Standards
Follows the general plugin documentation pattern:
- Tool-focused descriptions with clear input/output schemas
- Browser-based workflow documentation
- Implementation details for internal architectural patterns
- Service integration examples
- Error handling patterns
License
MIT License - see LICENSE file for details.