@kernel.chat/kbot 3.74.0 → 3.83.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 CHANGED
@@ -16,6 +16,7 @@
16
16
  <a href="https://github.com/isaacsight/kernel/blob/main/LICENSE"><img src="https://img.shields.io/github/license/isaacsight/kernel?color=6B5B95" alt="MIT License"></a>
17
17
  <a href="https://kernel.chat"><img src="https://img.shields.io/badge/web-kernel.chat-6B5B95" alt="kernel.chat"></a>
18
18
  <a href="https://discord.gg/kdMauM9abG"><img src="https://img.shields.io/badge/discord-join-6B5B95?logo=discord&logoColor=white" alt="Discord"></a>
19
+ <a href="https://glama.ai/mcp/servers/isaacsight/kernel"><img src="https://glama.ai/mcp/servers/isaacsight/kernel/badges/score.svg" alt="kbot MCP server"></a>
19
20
  </p>
20
21
 
21
22
  ```bash
@@ -305,6 +306,8 @@ graph TD
305
306
 
306
307
  ## MCP Server
307
308
 
309
+ [![kbot MCP server](https://glama.ai/mcp/servers/isaacsight/kernel/badges/card.svg)](https://glama.ai/mcp/servers/isaacsight/kernel)
310
+
308
311
  Use kbot as a tool provider inside any MCP-compatible IDE:
309
312
 
310
313
  ```json
@@ -317,6 +320,12 @@ Use kbot as a tool provider inside any MCP-compatible IDE:
317
320
  }
318
321
  ```
319
322
 
323
+ Or run the MCP server via Docker:
324
+
325
+ ```bash
326
+ docker run -i --rm kernelchat/kbot ide mcp
327
+ ```
328
+
320
329
  Works with Claude Code, Cursor, VS Code, Windsurf, Zed, Neovim.
321
330
 
322
331
  ## Commands
package/dist/cli.js CHANGED
@@ -1960,6 +1960,40 @@ async function main() {
1960
1960
  printInfo(`Or pull all: ${missing.map(m => `ollama pull ${m.name}`).join(' && ')}`);
1961
1961
  }
1962
1962
  });
1963
+ program
1964
+ .command('stream [action]')
1965
+ .description('Multi-platform livestream to Twitch, Rumble, and Kick simultaneously')
1966
+ .option('-p, --platforms <list>', 'Comma-separated: twitch,rumble,kick or "all"', 'all')
1967
+ .option('-s, --source <src>', 'Video source: screen, webcam, test, or file path', 'screen')
1968
+ .option('-r, --resolution <res>', 'Output resolution', '1920x1080')
1969
+ .option('-b, --bitrate <kbps>', 'Video bitrate in kbps', '4500')
1970
+ .action(async (action, opts) => {
1971
+ const { ensureLazyToolsLoaded, executeTool: execTool } = await import('./tools/index.js');
1972
+ await ensureLazyToolsLoaded();
1973
+ const cmd = (action || 'status').toLowerCase();
1974
+ if (cmd === 'start' || cmd === 'go' || cmd === 'live') {
1975
+ const result = await execTool({
1976
+ id: `stream_${Date.now()}`, name: 'stream_start',
1977
+ arguments: { platforms: opts?.platforms, source: opts?.source, resolution: opts?.resolution, bitrate: opts?.bitrate },
1978
+ });
1979
+ process.stderr.write(result.result + '\n');
1980
+ }
1981
+ else if (cmd === 'stop' || cmd === 'end') {
1982
+ const result = await execTool({ id: `stream_${Date.now()}`, name: 'stream_stop', arguments: {} });
1983
+ process.stderr.write(result.result + '\n');
1984
+ }
1985
+ else if (cmd === 'status') {
1986
+ const result = await execTool({ id: `stream_${Date.now()}`, name: 'stream_status', arguments: {} });
1987
+ process.stderr.write(result.result + '\n');
1988
+ }
1989
+ else if (cmd === 'setup') {
1990
+ const result = await execTool({ id: `stream_${Date.now()}`, name: 'stream_setup', arguments: { platform: 'all' } });
1991
+ process.stderr.write(result.result + '\n');
1992
+ }
1993
+ else {
1994
+ process.stderr.write(`Unknown stream action: ${cmd}\nUsage: kbot stream [start|stop|status|setup]\n`);
1995
+ }
1996
+ });
1963
1997
  program
1964
1998
  .command('serve')
1965
1999
  .description('Start HTTP/HTTPS server — expose all tools for kernel.chat, Claude Cowork, or any client')
@@ -16,6 +16,21 @@ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSche
16
16
  import { initBridge, chat, executeCommand, getTools, getStatus, getAgents, getMemory, getSessions, getContext, getFileDiagnostics, remember, setAgent, } from './bridge.js';
17
17
  import { ResponseStream } from '../streaming.js';
18
18
  import { formatDiagnostics } from './lsp-bridge.js';
19
+ import { createRequire } from 'node:module';
20
+ const __require = createRequire(import.meta.url);
21
+ const PKG_VERSION = __require('../../package.json').version;
22
+ /** Sanitize error messages to prevent leaking internal paths, keys, or URLs */
23
+ function sanitizeError(err) {
24
+ if (err instanceof Error) {
25
+ return err.message
26
+ .replace(/Bearer\s+\S+/gi, 'Bearer [REDACTED]')
27
+ .replace(/apikey\s+\S+/gi, 'apikey [REDACTED]')
28
+ .replace(/https?:\/\/[^\s]+/g, '[URL]')
29
+ .replace(/\/Users\/[^\s]+/g, '[PATH]')
30
+ .replace(/\/home\/[^\s]+/g, '[PATH]');
31
+ }
32
+ return 'An unexpected error occurred';
33
+ }
19
34
  /**
20
35
  * Start the MCP server on stdio.
21
36
  * This is the entry point called by `kbot ide mcp`.
@@ -25,7 +40,7 @@ export async function startMcpServer(config = {}) {
25
40
  await initBridge(config);
26
41
  const server = new Server({
27
42
  name: 'kbot',
28
- version: '2.0.0',
43
+ version: PKG_VERSION,
29
44
  }, {
30
45
  capabilities: {
31
46
  tools: {},
@@ -39,90 +54,90 @@ export async function startMcpServer(config = {}) {
39
54
  const staticTools = [
40
55
  {
41
56
  name: 'kbot_chat',
42
- description: 'Send a message to kbot and get an agent response. Supports 22 specialist agents with automatic routing.',
57
+ description: 'Send a natural language message to kbot and receive a specialist agent response. kbot automatically routes to the best-fit agent (coder, researcher, writer, analyst, guardian, or 30 others) based on message intent, or you can force a specific agent via the agent parameter. Use this tool when you need AI-powered assistance for coding, research, writing, analysis, security review, or any general task. Do not use this for direct file operations (use kbot_read_file, kbot_edit_file, kbot_write_file instead) or shell commands (use kbot_bash instead). Each call is stateless -- conversation history is not preserved between calls. Returns the agent response text, plus optional thinking traces and tool-use results if the agent invoked sub-tools.',
43
58
  inputSchema: {
44
59
  type: 'object',
45
60
  properties: {
46
- message: { type: 'string', description: 'The message to send to kbot' },
47
- agent: { type: 'string', description: 'Force a specific agent (kernel, researcher, coder, writer, analyst, etc.). Defaults to auto-routing.' },
61
+ message: { type: 'string', description: 'The natural language message or task description for kbot. Must be a non-empty string. Be specific about what you need -- e.g., "refactor this function to use async/await" rather than "fix this".' },
62
+ agent: { type: 'string', description: 'Force a specific specialist agent by ID. Available agents: "coder" (programming), "researcher" (research and fact-finding), "writer" (content creation), "analyst" (strategy and evaluation), "guardian" (security), "quant" (data analysis), "aesthete" (design), "infrastructure" (DevOps), and 27 more. Omit to let kbot auto-route based on message content.' },
48
63
  },
49
64
  required: ['message'],
50
65
  },
51
66
  },
52
67
  {
53
68
  name: 'kbot_edit_file',
54
- description: 'Edit a file using search/replace. Finds old_string and replaces with new_string.',
69
+ description: 'Edit an existing file by finding and replacing a specific text occurrence. Locates the first exact match of old_string in the file and replaces it with new_string. Use this tool for targeted, surgical edits to existing files -- prefer this over kbot_write_file when you only need to change part of a file. Do not use this for creating new files (use kbot_write_file instead). Always call kbot_read_file first to verify the exact text you want to replace. Side effects: modifies the file on disk. Fails with an error if old_string is not found or the file does not exist.',
55
70
  inputSchema: {
56
71
  type: 'object',
57
72
  properties: {
58
- path: { type: 'string', description: 'File path to edit' },
59
- old_string: { type: 'string', description: 'Text to find' },
60
- new_string: { type: 'string', description: 'Replacement text' },
73
+ path: { type: 'string', description: 'Absolute or relative file path to edit. The file must already exist.' },
74
+ old_string: { type: 'string', description: 'Exact text to find in the file. Must match precisely including all whitespace and indentation. Copy the text from kbot_read_file output to ensure accuracy.' },
75
+ new_string: { type: 'string', description: 'Replacement text to insert where old_string was found. Can be an empty string to delete the matched text.' },
61
76
  },
62
77
  required: ['path', 'old_string', 'new_string'],
63
78
  },
64
79
  },
65
80
  {
66
81
  name: 'kbot_write_file',
67
- description: 'Create or overwrite a file with content.',
82
+ description: 'Create a new file or completely overwrite an existing file with the provided content. Creates parent directories automatically if they do not exist. Use this tool when creating new files from scratch. Do not use this for partial edits to existing files (use kbot_edit_file instead, which preserves the rest of the file). If the target file already exists, call kbot_read_file first to avoid unintentional data loss. Side effects: writes to disk, may create directories.',
68
83
  inputSchema: {
69
84
  type: 'object',
70
85
  properties: {
71
- path: { type: 'string', description: 'File path' },
72
- content: { type: 'string', description: 'File content' },
86
+ path: { type: 'string', description: 'Absolute or relative file path to write. Parent directories are created automatically if missing.' },
87
+ content: { type: 'string', description: 'Complete file content to write. This replaces the entire file -- include all content, not just changes.' },
73
88
  },
74
89
  required: ['path', 'content'],
75
90
  },
76
91
  },
77
92
  {
78
93
  name: 'kbot_read_file',
79
- description: 'Read the contents of a file.',
94
+ description: 'Read and return the full text contents of a file from the local filesystem. Use this tool to inspect source code, configuration files, documentation, or data files before making edits. Always call this before kbot_edit_file to verify the exact text you want to replace. Do not use this for binary files (images, compiled artifacts). Read-only operation with no side effects. Returns an error message if the file does not exist or is not readable.',
80
95
  inputSchema: {
81
96
  type: 'object',
82
97
  properties: {
83
- path: { type: 'string', description: 'File path to read' },
98
+ path: { type: 'string', description: 'Absolute or relative file path to read. Supports any text-based file format.' },
84
99
  },
85
100
  required: ['path'],
86
101
  },
87
102
  },
88
103
  {
89
104
  name: 'kbot_bash',
90
- description: 'Run a shell command and return the output.',
105
+ description: 'Execute a shell command in the project working directory and return combined stdout and stderr output. Use this tool for build commands (npm run build), git operations (git status, git diff), package management (npm install), running tests (npm test), and system checks (which, ls, cat). Do not use this for file reading (use kbot_read_file) or file writing (use kbot_write_file) -- those tools are safer and more reliable. Destructive commands (rm -rf, git reset --hard) require user confirmation when --safe mode is enabled. Side effects: depends on the command executed. Commands exceeding the timeout are terminated with SIGTERM.',
91
106
  inputSchema: {
92
107
  type: 'object',
93
108
  properties: {
94
- command: { type: 'string', description: 'Shell command to execute' },
95
- timeout: { type: 'number', description: 'Timeout in milliseconds (default: 30000)' },
109
+ command: { type: 'string', description: 'Shell command to execute. Avoid commands requiring interactive input (like vim, nano, or prompts). Pipe-friendly commands work best.' },
110
+ timeout: { type: 'number', description: 'Maximum execution time in milliseconds before the command is killed. Default: 30000 (30 seconds). Maximum: 300000 (5 minutes). Increase for long-running builds or tests.' },
96
111
  },
97
112
  required: ['command'],
98
113
  },
99
114
  },
100
115
  {
101
116
  name: 'kbot_search',
102
- description: 'Search the web for information.',
117
+ description: 'Search the web for current information and return summarized results. Use this tool when you need real-time data, recent events, up-to-date documentation, or answers not available in local files. Do not use this for searching the local project codebase (use kbot_grep or kbot_glob instead) or for GitHub-specific searches (use kbot_github instead). Read-only operation with no side effects. Requires a search provider to be configured via kbot auth.',
103
118
  inputSchema: {
104
119
  type: 'object',
105
120
  properties: {
106
- query: { type: 'string', description: 'Search query' },
121
+ query: { type: 'string', description: 'Web search query string. Be specific and include relevant keywords for better results -- e.g., "React 19 useActionState migration guide" rather than "React hooks".' },
107
122
  },
108
123
  required: ['query'],
109
124
  },
110
125
  },
111
126
  {
112
127
  name: 'kbot_github',
113
- description: 'Search GitHub repositories and code.',
128
+ description: 'Search GitHub for repositories, code snippets, or issues/PRs matching a query. Use this tool to find libraries, reference implementations, open issues, or code examples across public GitHub repositories. Do not use this for web searches (use kbot_search instead) or local file searches (use kbot_grep instead). Read-only operation with no side effects. Returns structured results with repository names, descriptions, star counts, and URLs.',
114
129
  inputSchema: {
115
130
  type: 'object',
116
131
  properties: {
117
- query: { type: 'string', description: 'GitHub search query' },
118
- type: { type: 'string', description: 'Search type: repositories, code, issues' },
132
+ query: { type: 'string', description: 'GitHub search query. Supports GitHub search qualifiers like "language:typescript", "stars:>100", "topic:mcp-server". Example: "mcp server language:typescript stars:>50".' },
133
+ type: { type: 'string', description: 'What to search for. "repositories" searches repo names and descriptions. "code" searches file contents across repos. "issues" searches issue and PR titles and bodies. Default: "repositories".' },
119
134
  },
120
135
  required: ['query'],
121
136
  },
122
137
  },
123
138
  {
124
139
  name: 'kbot_status',
125
- description: 'Get kbot status including agent info, learning stats, and session count.',
140
+ description: 'Retrieve kbot runtime status as a JSON object. Returns the active specialist agent, learning engine statistics (patterns, solutions, knowledge entries, total messages processed), session count, and registered tool count. Use this tool to verify kbot is properly configured, check which agent is active, or monitor learning progress. Do not use this for project-specific status (use kbot_bash with "git status" instead). Read-only operation with no side effects.',
126
141
  inputSchema: {
127
142
  type: 'object',
128
143
  properties: {},
@@ -130,68 +145,68 @@ export async function startMcpServer(config = {}) {
130
145
  },
131
146
  {
132
147
  name: 'kbot_agent',
133
- description: 'Switch the active kbot agent or list available agents.',
148
+ description: 'Switch the active specialist agent for subsequent kbot_chat calls, or list all available agents when called without arguments. Use this tool to optimize responses by selecting the right specialist -- e.g., switch to "guardian" before a security review, or "researcher" before a deep-dive investigation. Do not use this if you only need to route a single message (pass the agent parameter to kbot_chat instead). Side effects: when agent ID is provided, changes the active agent for all future kbot_chat calls in this session.',
134
149
  inputSchema: {
135
150
  type: 'object',
136
151
  properties: {
137
- agent: { type: 'string', description: 'Agent ID to switch to. Omit to list available agents.' },
152
+ agent: { type: 'string', description: 'Agent ID to activate. Examples: "coder", "researcher", "writer", "analyst", "guardian", "quant", "infrastructure", "aesthete". Omit this parameter entirely to list all 35 available agents with descriptions.' },
138
153
  },
139
154
  },
140
155
  },
141
156
  {
142
157
  name: 'kbot_remember',
143
- description: 'Teach kbot a fact that persists across sessions.',
158
+ description: 'Store a fact in kbot persistent memory that persists across sessions and restarts. Use this tool to teach kbot project-specific conventions (e.g., "This project uses pnpm, not npm"), user preferences (e.g., "User prefers functional React components"), or domain knowledge that should inform future agent responses. Do not use this for temporary notes or session-specific context. Side effects: writes to the learning database on disk at ~/.kbot/. Facts are automatically surfaced to agents as context in future sessions.',
144
159
  inputSchema: {
145
160
  type: 'object',
146
161
  properties: {
147
- fact: { type: 'string', description: 'The fact to remember' },
162
+ fact: { type: 'string', description: 'The fact, convention, or knowledge to persist. Be specific and declarative -- e.g., "This project uses Vitest for testing, not Jest" rather than "testing stuff".' },
148
163
  },
149
164
  required: ['fact'],
150
165
  },
151
166
  },
152
167
  {
153
168
  name: 'kbot_diagnostics',
154
- description: 'Get LSP diagnostics (type errors, warnings) for a file.',
169
+ description: 'Retrieve TypeScript/JavaScript diagnostics (type errors, warnings, lint issues) for a specific source file via the kbot LSP bridge. Use this tool to check for type errors before committing changes, to verify that a fix resolved a type issue, or to understand compilation errors. Do not use this for runtime errors (use kbot_bash to run the code instead) or for non-TypeScript files. Read-only operation with no side effects. Returns formatted diagnostic messages with file path, line number, column, severity level, and error message.',
155
170
  inputSchema: {
156
171
  type: 'object',
157
172
  properties: {
158
- path: { type: 'string', description: 'File path to check' },
173
+ path: { type: 'string', description: 'Absolute or relative path to the TypeScript or JavaScript file to check for diagnostics.' },
159
174
  },
160
175
  required: ['path'],
161
176
  },
162
177
  },
163
178
  {
164
179
  name: 'kbot_plan',
165
- description: 'Generate and execute an autonomous plan for a complex task.',
180
+ description: 'Generate and optionally execute an autonomous multi-step plan for a complex task. The planner analyzes the task, breaks it into ordered subtasks, selects appropriate tools for each step, executes them sequentially, and self-corrects on failures with retries. Use this tool for complex multi-file refactors, full-stack feature implementations, research-then-implement workflows, or any task requiring coordination of multiple tools. Do not use this for simple single-step operations (use the specific tool directly). Side effects: depends on plan steps -- may read/write files, run shell commands, make API calls. Set auto_approve=false to review the generated plan before any execution begins.',
166
181
  inputSchema: {
167
182
  type: 'object',
168
183
  properties: {
169
- task: { type: 'string', description: 'The complex task to plan and execute' },
170
- auto_approve: { type: 'boolean', description: 'Auto-approve (default: false)' },
184
+ task: { type: 'string', description: 'Detailed description of the complex task to plan and execute. More context leads to better plans -- include relevant file paths, expected outcomes, and constraints.' },
185
+ auto_approve: { type: 'boolean', description: 'Controls whether plan steps execute automatically. false (default): generates the plan and returns it for review without executing. true: generates and immediately executes all steps without confirmation.' },
171
186
  },
172
187
  required: ['task'],
173
188
  },
174
189
  },
175
190
  {
176
191
  name: 'kbot_glob',
177
- description: 'Find files matching a glob pattern.',
192
+ description: 'Find files matching a glob pattern in the project directory tree. Use this tool to discover files by name pattern before reading or editing them -- e.g., find all test files, all TypeScript files in a directory, or locate a specific config file. Do not use this for searching file contents (use kbot_grep instead). Read-only operation with no side effects. Returns a list of matching absolute file paths sorted by most recently modified first.',
178
193
  inputSchema: {
179
194
  type: 'object',
180
195
  properties: {
181
- pattern: { type: 'string', description: 'Glob pattern (e.g., "**/*.ts")' },
182
- path: { type: 'string', description: 'Base directory (default: cwd)' },
196
+ pattern: { type: 'string', description: 'Glob pattern to match against file paths. Supports ** for recursive directory matching, * for single-level wildcards, and {a,b} for alternatives. Examples: "**/*.ts" (all TypeScript files), "src/**/*.test.tsx" (all test files in src), "*.json" (JSON files in current directory).' },
197
+ path: { type: 'string', description: 'Base directory to start searching from. Default: current working directory. Use an absolute path for predictable results.' },
183
198
  },
184
199
  required: ['pattern'],
185
200
  },
186
201
  },
187
202
  {
188
203
  name: 'kbot_grep',
189
- description: 'Search file contents with regex.',
204
+ description: 'Search file contents for lines matching a regular expression pattern. Use this tool to find function definitions, string references, import statements, TODO comments, or any text pattern across the project codebase. Do not use this for finding files by name (use kbot_glob instead) or for web searches (use kbot_search instead). Read-only operation with no side effects. Returns matching lines with file path, line number, and the matched line content.',
190
205
  inputSchema: {
191
206
  type: 'object',
192
207
  properties: {
193
- pattern: { type: 'string', description: 'Regex pattern' },
194
- path: { type: 'string', description: 'File or directory to search' },
208
+ pattern: { type: 'string', description: 'Regular expression pattern to search for in file contents. Supports full regex syntax. Examples: "function\\s+\\w+" (function declarations), "TODO|FIXME|HACK" (code annotations), "import.*from \'react\'" (React imports).' },
209
+ path: { type: 'string', description: 'File or directory to search in. When a directory is given, searches recursively through all text files. Default: current working directory.' },
195
210
  },
196
211
  required: ['pattern'],
197
212
  },
@@ -372,7 +387,7 @@ export async function startMcpServer(config = {}) {
372
387
  return {
373
388
  content: [{
374
389
  type: 'text',
375
- text: `Error: ${err instanceof Error ? err.message : String(err)}`,
390
+ text: `Error: ${sanitizeError(err)}`,
376
391
  }],
377
392
  isError: true,
378
393
  };
@@ -452,11 +467,11 @@ export async function startMcpServer(config = {}) {
452
467
  server.setRequestHandler(ListPromptsRequestSchema, async () => {
453
468
  return {
454
469
  prompts: [
455
- { name: 'explain_code', description: 'Explain what code does', arguments: [{ name: 'code', required: true, description: 'Code to explain' }] },
456
- { name: 'review_code', description: 'Review code for bugs and improvements', arguments: [{ name: 'code', required: true, description: 'Code to review' }] },
457
- { name: 'fix_error', description: 'Fix a code error', arguments: [{ name: 'error', required: true, description: 'Error message' }, { name: 'code', required: false, description: 'Relevant code' }] },
458
- { name: 'generate_tests', description: 'Generate tests for code', arguments: [{ name: 'code', required: true, description: 'Code to test' }] },
459
- { name: 'refactor', description: 'Suggest refactoring improvements', arguments: [{ name: 'code', required: true, description: 'Code to refactor' }] },
470
+ { name: 'explain_code', description: 'Generate a detailed explanation of what a code snippet does, including its purpose, control flow, key operations, and return values. Use this when you need to understand unfamiliar code.', arguments: [{ name: 'code', required: true, description: 'The source code snippet to explain. Can be any programming language.' }] },
471
+ { name: 'review_code', description: 'Perform a code review identifying bugs, security vulnerabilities, performance issues, and improvement opportunities. Returns categorized findings with severity levels and suggested fixes.', arguments: [{ name: 'code', required: true, description: 'The source code to review. Include enough surrounding context for accurate analysis.' }] },
472
+ { name: 'fix_error', description: 'Diagnose and fix a code error given an error message and optionally the relevant source code. Returns the corrected code with an explanation of what caused the error and how the fix resolves it.', arguments: [{ name: 'error', required: true, description: 'The full error message, stack trace, or diagnostic output.' }, { name: 'code', required: false, description: 'The source code that produced the error. Include the function or block containing the error for best results.' }] },
473
+ { name: 'generate_tests', description: 'Generate comprehensive test cases for a code snippet, covering happy paths, edge cases, error conditions, and boundary values. Outputs test code in the appropriate testing framework for the language.', arguments: [{ name: 'code', required: true, description: 'The source code to generate tests for. Include type signatures and function documentation for better test coverage.' }] },
474
+ { name: 'refactor', description: 'Analyze code and suggest refactoring improvements for readability, maintainability, performance, and adherence to best practices. Returns the refactored code with explanations for each change.', arguments: [{ name: 'code', required: true, description: 'The source code to refactor. Include the complete function or module for context-aware suggestions.' }] },
460
475
  ],
461
476
  };
462
477
  });
@@ -314,6 +314,9 @@ const LAZY_MODULE_IMPORTS = [
314
314
  { path: './mobile-automation.js', registerFn: 'registerMobileAutomationTools' },
315
315
  { path: './iphone.js', registerFn: 'registerIPhoneTools' },
316
316
  { path: './ghost.js', registerFn: 'registerGhostTools' },
317
+ { path: './streaming.js', registerFn: 'registerStreamingTools' },
318
+ { path: './stream-character.js', registerFn: 'registerStreamCharacterTools' },
319
+ { path: './stream-renderer.js', registerFn: 'registerStreamRendererTools' },
317
320
  ];
318
321
  /** Track whether lazy tools have been registered */
319
322
  let lazyToolsRegistered = false;
@@ -0,0 +1,158 @@
1
+ import type { CanvasRenderingContext2D } from 'canvas';
2
+ export interface Light {
3
+ x: number;
4
+ y: number;
5
+ radius: number;
6
+ color: string;
7
+ intensity: number;
8
+ flicker?: boolean;
9
+ }
10
+ /**
11
+ * Render dynamic lighting over the scene.
12
+ * First draws a dark ambient overlay, then additively blends each light source.
13
+ */
14
+ export declare function renderLighting(ctx: CanvasRenderingContext2D, lights: Light[], width: number, height: number, ambientLight: number): void;
15
+ /**
16
+ * Get ambient light level for a given time of day.
17
+ */
18
+ export declare function getAmbientForTime(timeOfDay: string): number;
19
+ /**
20
+ * Build default light sources for the kbot stream character.
21
+ */
22
+ export declare function buildCharacterLights(robotX: number, robotY: number, scale: number, moodColor: string, frame: number, hasLightning: boolean, worldItems?: Array<{
23
+ x: number;
24
+ y: number;
25
+ emoji: string;
26
+ name: string;
27
+ }>): Light[];
28
+ export interface BloomSpot {
29
+ x: number;
30
+ y: number;
31
+ radius: number;
32
+ color: string;
33
+ }
34
+ /**
35
+ * Render soft glowing halos around bright elements.
36
+ */
37
+ export declare function renderBloom(ctx: CanvasRenderingContext2D, brightSpots: BloomSpot[]): void;
38
+ /**
39
+ * Build default bloom spots for the kbot character.
40
+ */
41
+ export declare function buildCharacterBloom(robotX: number, robotY: number, scale: number, moodColor: string, frame: number): BloomSpot[];
42
+ export interface Particle {
43
+ x: number;
44
+ y: number;
45
+ vx: number;
46
+ vy: number;
47
+ life: number;
48
+ maxLife: number;
49
+ size: number;
50
+ color: string;
51
+ type: 'spark' | 'fire' | 'magic' | 'electricity' | 'trail' | 'smoke' | 'aura';
52
+ trail?: Array<{
53
+ x: number;
54
+ y: number;
55
+ }>;
56
+ gravity?: number;
57
+ cx?: number;
58
+ cy?: number;
59
+ orbitRadius?: number;
60
+ orbitPhase?: number;
61
+ startX?: number;
62
+ startY?: number;
63
+ endX?: number;
64
+ endY?: number;
65
+ midpoints?: Array<{
66
+ x: number;
67
+ y: number;
68
+ }>;
69
+ lastMidpointFrame?: number;
70
+ pulsePhase?: number;
71
+ }
72
+ /**
73
+ * Create particles of a given type at a position.
74
+ */
75
+ export declare function createParticleEmitter(type: Particle['type'], x: number, y: number, count: number): Particle[];
76
+ /**
77
+ * Tick all particles: apply physics, age, return survivors.
78
+ */
79
+ export declare function tickParticles(particles: Particle[]): Particle[];
80
+ /**
81
+ * Render all particles to the canvas.
82
+ */
83
+ export declare function renderParticles(ctx: CanvasRenderingContext2D, particles: Particle[]): void;
84
+ /**
85
+ * Render a full procedural sky based on time of day, weather, and frame.
86
+ */
87
+ export declare function renderSky(ctx: CanvasRenderingContext2D, width: number, height: number, timeOfDay: string, weather: string, frame: number, dividerX?: number): void;
88
+ export interface ParallaxLayer {
89
+ type: 'far' | 'mid' | 'near';
90
+ factor: number;
91
+ draw: (ctx: CanvasRenderingContext2D, offsetX: number, frame: number) => void;
92
+ }
93
+ /**
94
+ * Build parallax layers for a given biome.
95
+ */
96
+ export declare function buildParallaxLayers(biome: string, dividerX: number): ParallaxLayer[];
97
+ /**
98
+ * Render parallax layers relative to robot position.
99
+ */
100
+ export declare function renderParallaxLayers(ctx: CanvasRenderingContext2D, layers: ParallaxLayer[], robotX: number, frame: number): void;
101
+ export interface GrowingPlant {
102
+ x: number;
103
+ y: number;
104
+ type: 'tree' | 'flower' | 'mushroom' | 'crystal';
105
+ growthStage: number;
106
+ maxHeight: number;
107
+ color: string;
108
+ }
109
+ /**
110
+ * Tick and render growing vegetation.
111
+ */
112
+ export declare function tickGrowingPlants(plants: GrowingPlant[]): void;
113
+ export declare function renderGrowingPlants(ctx: CanvasRenderingContext2D, plants: GrowingPlant[]): void;
114
+ /**
115
+ * Render animated water with multiple sine waves, reflections, and foam.
116
+ */
117
+ export declare function renderAnimatedWater(ctx: CanvasRenderingContext2D, dividerX: number, frame: number): void;
118
+ /**
119
+ * Render lava with organic flow patterns and popping bubbles.
120
+ */
121
+ export declare function renderLavaFlow(ctx: CanvasRenderingContext2D, dividerX: number, frame: number): void;
122
+ /**
123
+ * Draw AAA character effects: eye glow bleed, power-up aura, walk trail, etc.
124
+ */
125
+ export declare function drawCharacterEffects(ctx: CanvasRenderingContext2D, x: number, y: number, scale: number, mood: string, frame: number, isExecutingTool: boolean, walkSpeed: number, moodColor: string): void;
126
+ /**
127
+ * Track mood changes and return chromatic aberration offset if transitioning.
128
+ * Returns {active, framesLeft} — caller draws character 3x with RGB offsets.
129
+ */
130
+ export declare function checkMoodTransition(mood: string, moodColor: string): {
131
+ active: boolean;
132
+ framesLeft: number;
133
+ };
134
+ /**
135
+ * Trigger a white damage flash for 2 frames.
136
+ */
137
+ export declare function triggerDamageFlash(): void;
138
+ /**
139
+ * Render damage flash overlay on the character.
140
+ * Returns true if flash is active (caller should skip normal character rendering logic).
141
+ */
142
+ export declare function renderDamageFlash(ctx: CanvasRenderingContext2D, x: number, y: number, scale: number): boolean;
143
+ export interface PostProcessOptions {
144
+ bloom: boolean;
145
+ filmGrain: boolean;
146
+ vignette: boolean;
147
+ scanlines: boolean;
148
+ focusPulse?: {
149
+ x: number;
150
+ y: number;
151
+ radius: number;
152
+ };
153
+ }
154
+ /**
155
+ * Apply screen-space post-processing effects.
156
+ */
157
+ export declare function renderPostProcessing(ctx: CanvasRenderingContext2D, width: number, height: number, frame: number, options: PostProcessOptions): void;
158
+ //# sourceMappingURL=render-engine.d.ts.map