opc-agent 4.0.0 → 4.0.2

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.
Files changed (75) hide show
  1. package/README.md +404 -80
  2. package/README.zh-CN.md +82 -0
  3. package/dist/cli/chat.d.ts +2 -0
  4. package/dist/cli/chat.js +134 -0
  5. package/dist/cli/setup.d.ts +4 -0
  6. package/dist/cli/setup.js +303 -0
  7. package/dist/cli.js +106 -6
  8. package/dist/hub/brain-seed.d.ts +14 -0
  9. package/dist/hub/brain-seed.js +77 -0
  10. package/dist/hub/client.d.ts +25 -0
  11. package/dist/hub/client.js +44 -0
  12. package/dist/index.d.ts +4 -2
  13. package/dist/index.js +12 -3
  14. package/dist/providers/index.d.ts +1 -1
  15. package/dist/providers/index.js +74 -1
  16. package/dist/scheduler/cron-engine.d.ts +41 -0
  17. package/dist/scheduler/cron-engine.js +200 -0
  18. package/dist/scheduler/index.d.ts +3 -0
  19. package/dist/scheduler/index.js +7 -0
  20. package/dist/skills/builtin/index.d.ts +6 -0
  21. package/dist/skills/builtin/index.js +402 -0
  22. package/dist/skills/marketplace.d.ts +30 -0
  23. package/dist/skills/marketplace.js +142 -0
  24. package/dist/skills/types.d.ts +34 -0
  25. package/dist/skills/types.js +16 -0
  26. package/dist/studio/server.d.ts +25 -0
  27. package/dist/studio/server.js +780 -0
  28. package/dist/studio/templates-data.d.ts +21 -0
  29. package/dist/studio/templates-data.js +148 -0
  30. package/dist/studio-ui/index.html +2502 -1073
  31. package/dist/tools/builtin/index.d.ts +1 -0
  32. package/dist/tools/builtin/index.js +7 -2
  33. package/dist/tools/builtin/web-search.d.ts +9 -0
  34. package/dist/tools/builtin/web-search.js +150 -0
  35. package/dist/tools/document-processor.d.ts +39 -0
  36. package/dist/tools/document-processor.js +188 -0
  37. package/dist/tools/image-generator.d.ts +42 -0
  38. package/dist/tools/image-generator.js +136 -0
  39. package/dist/tools/web-scraper.d.ts +20 -0
  40. package/dist/tools/web-scraper.js +148 -0
  41. package/dist/tools/web-search.d.ts +51 -0
  42. package/dist/tools/web-search.js +152 -0
  43. package/install.ps1 +154 -0
  44. package/install.sh +164 -0
  45. package/package.json +63 -52
  46. package/src/cli/chat.ts +99 -0
  47. package/src/cli/setup.ts +314 -0
  48. package/src/cli.ts +108 -6
  49. package/src/hub/brain-seed.ts +54 -0
  50. package/src/hub/client.ts +60 -0
  51. package/src/index.ts +4 -2
  52. package/src/providers/index.ts +80 -1
  53. package/src/scheduler/cron-engine.ts +191 -0
  54. package/src/scheduler/index.ts +2 -0
  55. package/src/skills/builtin/index.ts +408 -0
  56. package/src/skills/marketplace.ts +113 -0
  57. package/src/skills/types.ts +42 -0
  58. package/src/studio/server.ts +1591 -791
  59. package/src/studio/templates-data.ts +178 -0
  60. package/src/studio-ui/index.html +2502 -1073
  61. package/src/tools/builtin/index.ts +37 -35
  62. package/src/tools/builtin/web-search.ts +126 -0
  63. package/src/tools/document-processor.ts +213 -0
  64. package/src/tools/image-generator.ts +150 -0
  65. package/src/tools/web-scraper.ts +179 -0
  66. package/src/tools/web-search.ts +180 -0
  67. package/tests/cron-engine.test.ts +101 -0
  68. package/tests/document-processor.test.ts +69 -0
  69. package/tests/e2e-nocode.test.ts +442 -0
  70. package/tests/image-generator.test.ts +84 -0
  71. package/tests/settings-api.test.ts +148 -0
  72. package/tests/setup.test.ts +73 -0
  73. package/tests/studio.test.ts +402 -229
  74. package/tests/voice-interaction.test.ts +38 -0
  75. package/tests/web-search.test.ts +155 -0
@@ -9,6 +9,7 @@ export { fileTool, webTool, shellTool, datetimeTool, browserTools, BrowserManage
9
9
  export { visionTools, visionAnalyzeTool, visionExtractTextTool, visionCompareTool };
10
10
  export { rlTools } from './rl-tools';
11
11
  export { homeAssistantTools, configureHomeAssistant } from './home-assistant';
12
+ export { webSearchTools, webSearchTool, webReadTool } from './web-search';
12
13
  /**
13
14
  * Get all built-in tools.
14
15
  */
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.configureHomeAssistant = exports.homeAssistantTools = exports.rlTools = exports.visionCompareTool = exports.visionExtractTextTool = exports.visionAnalyzeTool = exports.visionTools = exports.browserManager = exports.BrowserManager = exports.browserTools = exports.datetimeTool = exports.shellTool = exports.webTool = exports.fileTool = void 0;
3
+ exports.webReadTool = exports.webSearchTool = exports.webSearchTools = exports.configureHomeAssistant = exports.homeAssistantTools = exports.rlTools = exports.visionCompareTool = exports.visionExtractTextTool = exports.visionAnalyzeTool = exports.visionTools = exports.browserManager = exports.BrowserManager = exports.browserTools = exports.datetimeTool = exports.shellTool = exports.webTool = exports.fileTool = void 0;
4
4
  exports.getBuiltinTools = getBuiltinTools;
5
5
  exports.getBuiltinToolsByName = getBuiltinToolsByName;
6
6
  const file_1 = require("./file");
@@ -22,12 +22,17 @@ Object.defineProperty(exports, "visionExtractTextTool", { enumerable: true, get:
22
22
  Object.defineProperty(exports, "visionCompareTool", { enumerable: true, get: function () { return vision_1.visionCompareTool; } });
23
23
  const rl_tools_1 = require("./rl-tools");
24
24
  const home_assistant_1 = require("./home-assistant");
25
+ const web_search_1 = require("./web-search");
25
26
  var rl_tools_2 = require("./rl-tools");
26
27
  Object.defineProperty(exports, "rlTools", { enumerable: true, get: function () { return rl_tools_2.rlTools; } });
27
28
  var home_assistant_2 = require("./home-assistant");
28
29
  Object.defineProperty(exports, "homeAssistantTools", { enumerable: true, get: function () { return home_assistant_2.homeAssistantTools; } });
29
30
  Object.defineProperty(exports, "configureHomeAssistant", { enumerable: true, get: function () { return home_assistant_2.configureHomeAssistant; } });
30
- const ALL_BUILTIN_TOOLS = [file_1.fileTool, web_1.webTool, shell_1.shellTool, datetime_1.datetimeTool, ...browser_1.browserTools, ...vision_1.visionTools, ...rl_tools_1.rlTools, ...home_assistant_1.homeAssistantTools];
31
+ var web_search_2 = require("./web-search");
32
+ Object.defineProperty(exports, "webSearchTools", { enumerable: true, get: function () { return web_search_2.webSearchTools; } });
33
+ Object.defineProperty(exports, "webSearchTool", { enumerable: true, get: function () { return web_search_2.webSearchTool; } });
34
+ Object.defineProperty(exports, "webReadTool", { enumerable: true, get: function () { return web_search_2.webReadTool; } });
35
+ const ALL_BUILTIN_TOOLS = [file_1.fileTool, web_1.webTool, shell_1.shellTool, datetime_1.datetimeTool, ...browser_1.browserTools, ...vision_1.visionTools, ...rl_tools_1.rlTools, ...home_assistant_1.homeAssistantTools, ...web_search_1.webSearchTools];
31
36
  const BUILTIN_MAP = new Map(ALL_BUILTIN_TOOLS.map(t => [t.name, t]));
32
37
  /**
33
38
  * Get all built-in tools.
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Web Search & Read Built-in Tools - v0.10.0
3
+ * Registers web_search and web_read as agent-callable tools.
4
+ */
5
+ import type { MCPTool } from '../mcp';
6
+ export declare const webSearchTool: MCPTool;
7
+ export declare const webReadTool: MCPTool;
8
+ export declare const webSearchTools: MCPTool[];
9
+ //# sourceMappingURL=web-search.d.ts.map
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ /**
3
+ * Web Search & Read Built-in Tools - v0.10.0
4
+ * Registers web_search and web_read as agent-callable tools.
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.webSearchTools = exports.webReadTool = exports.webSearchTool = void 0;
41
+ const web_search_1 = require("../web-search");
42
+ const web_scraper_1 = require("../web-scraper");
43
+ const fs_1 = require("fs");
44
+ const path_1 = require("path");
45
+ const os = __importStar(require("os"));
46
+ function loadSearchConfig() {
47
+ try {
48
+ const cfgPath = (0, path_1.join)(os.homedir(), '.opc', 'config.json');
49
+ if ((0, fs_1.existsSync)(cfgPath)) {
50
+ const cfg = JSON.parse((0, fs_1.readFileSync)(cfgPath, 'utf-8'));
51
+ if (cfg.webSearch) {
52
+ return { ...web_search_1.DEFAULT_SEARCH_CONFIG, ...cfg.webSearch };
53
+ }
54
+ }
55
+ }
56
+ catch { /* ignore */ }
57
+ return web_search_1.DEFAULT_SEARCH_CONFIG;
58
+ }
59
+ exports.webSearchTool = {
60
+ name: 'web_search',
61
+ description: 'Search the internet for information. Returns titles, URLs, and snippets from search results. Use when you need current information or facts you\'re unsure about.',
62
+ inputSchema: {
63
+ type: 'object',
64
+ properties: {
65
+ query: {
66
+ type: 'string',
67
+ description: 'Search query string',
68
+ },
69
+ maxResults: {
70
+ type: 'number',
71
+ description: 'Maximum number of results to return (default: 5)',
72
+ },
73
+ engine: {
74
+ type: 'string',
75
+ enum: ['duckduckgo', 'brave', 'searxng', 'google'],
76
+ description: 'Search engine to use (default: configured engine)',
77
+ },
78
+ },
79
+ required: ['query'],
80
+ },
81
+ async execute(input) {
82
+ const query = String(input.query ?? '');
83
+ if (!query.trim()) {
84
+ return { content: 'Error: empty search query', isError: true };
85
+ }
86
+ const config = loadSearchConfig();
87
+ if (!config.enabled) {
88
+ return { content: 'Web search is disabled in settings.', isError: true };
89
+ }
90
+ try {
91
+ const results = await (0, web_search_1.webSearch)(query, config, {
92
+ maxResults: input.maxResults || 5,
93
+ engine: input.engine,
94
+ });
95
+ if (results.length === 0) {
96
+ return { content: `No results found for: ${query}` };
97
+ }
98
+ const formatted = results.map((r, i) => `${i + 1}. **${r.title}**\n ${r.url}\n ${r.snippet}`).join('\n\n');
99
+ return {
100
+ content: `Search results for "${query}":\n\n${formatted}`,
101
+ metadata: { resultCount: results.length, query },
102
+ };
103
+ }
104
+ catch (err) {
105
+ return {
106
+ content: `Search error: ${err instanceof Error ? err.message : String(err)}`,
107
+ isError: true,
108
+ };
109
+ }
110
+ },
111
+ };
112
+ exports.webReadTool = {
113
+ name: 'web_read',
114
+ description: 'Read and extract the main content from a web page URL. Returns clean markdown text. Use to get detailed information from a specific page.',
115
+ inputSchema: {
116
+ type: 'object',
117
+ properties: {
118
+ url: {
119
+ type: 'string',
120
+ description: 'URL of the web page to read',
121
+ },
122
+ maxLength: {
123
+ type: 'number',
124
+ description: 'Maximum content length in characters (default: 5000)',
125
+ },
126
+ },
127
+ required: ['url'],
128
+ },
129
+ async execute(input) {
130
+ const url = String(input.url ?? '');
131
+ if (!url.trim()) {
132
+ return { content: 'Error: empty URL', isError: true };
133
+ }
134
+ try {
135
+ const result = await (0, web_scraper_1.scrapeUrl)(url, input.maxLength || 5000);
136
+ return {
137
+ content: `# ${result.title}\n\nSource: ${result.url}\nWords: ${result.wordCount}\n\n---\n\n${result.content}`,
138
+ metadata: { title: result.title, url: result.url, wordCount: result.wordCount },
139
+ };
140
+ }
141
+ catch (err) {
142
+ return {
143
+ content: `Scrape error: ${err instanceof Error ? err.message : String(err)}`,
144
+ isError: true,
145
+ };
146
+ }
147
+ },
148
+ };
149
+ exports.webSearchTools = [exports.webSearchTool, exports.webReadTool];
150
+ //# sourceMappingURL=web-search.js.map
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Document Processor - Parse and chunk documents for knowledge learning
3
+ * Supports: PDF, TXT, MD, DOCX, CSV, JSON
4
+ */
5
+ export interface DocumentChunk {
6
+ title: string;
7
+ content: string;
8
+ metadata: {
9
+ source: string;
10
+ format: string;
11
+ chunkIndex: number;
12
+ totalChunks?: number;
13
+ page?: number;
14
+ };
15
+ }
16
+ export interface ProcessedDocument {
17
+ id: string;
18
+ filename: string;
19
+ format: string;
20
+ size: number;
21
+ chunks: DocumentChunk[];
22
+ processedAt: string;
23
+ }
24
+ export declare class DocumentProcessor {
25
+ /**
26
+ * Process a file buffer into chunks
27
+ */
28
+ process(buffer: Buffer, filename: string): Promise<ProcessedDocument>;
29
+ private parsePDF;
30
+ private parseDOCX;
31
+ private parseCSV;
32
+ private parseCSVLine;
33
+ private parseJSON;
34
+ /**
35
+ * Smart chunking: split by headings/paragraphs, respecting size limits
36
+ */
37
+ private chunkText;
38
+ }
39
+ //# sourceMappingURL=document-processor.d.ts.map
@@ -0,0 +1,188 @@
1
+ "use strict";
2
+ /**
3
+ * Document Processor - Parse and chunk documents for knowledge learning
4
+ * Supports: PDF, TXT, MD, DOCX, CSV, JSON
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.DocumentProcessor = void 0;
8
+ const MAX_FILE_SIZE = 50 * 1024 * 1024; // 50MB
9
+ const CHUNK_TARGET_CHARS = 2000; // ~500 tokens
10
+ const CHUNK_MAX_CHARS = 4000; // ~1000 tokens
11
+ class DocumentProcessor {
12
+ /**
13
+ * Process a file buffer into chunks
14
+ */
15
+ async process(buffer, filename) {
16
+ if (buffer.length > MAX_FILE_SIZE) {
17
+ throw new Error(`File too large: ${(buffer.length / 1024 / 1024).toFixed(1)}MB (max 50MB)`);
18
+ }
19
+ const ext = filename.split('.').pop()?.toLowerCase() || '';
20
+ let rawText;
21
+ switch (ext) {
22
+ case 'pdf':
23
+ rawText = await this.parsePDF(buffer);
24
+ break;
25
+ case 'docx':
26
+ rawText = await this.parseDOCX(buffer);
27
+ break;
28
+ case 'csv':
29
+ rawText = this.parseCSV(buffer.toString('utf-8'));
30
+ break;
31
+ case 'json':
32
+ rawText = this.parseJSON(buffer.toString('utf-8'));
33
+ break;
34
+ case 'txt':
35
+ case 'md':
36
+ case 'markdown':
37
+ rawText = buffer.toString('utf-8');
38
+ break;
39
+ default:
40
+ // Try as plain text
41
+ rawText = buffer.toString('utf-8');
42
+ }
43
+ const chunks = this.chunkText(rawText, filename, ext);
44
+ return {
45
+ id: `doc-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
46
+ filename,
47
+ format: ext,
48
+ size: buffer.length,
49
+ chunks,
50
+ processedAt: new Date().toISOString(),
51
+ };
52
+ }
53
+ async parsePDF(buffer) {
54
+ try {
55
+ const pdfParse = require('pdf-parse');
56
+ const data = await pdfParse(buffer);
57
+ return data.text || '';
58
+ }
59
+ catch (e) {
60
+ throw new Error(`PDF parse failed: ${e.message}`);
61
+ }
62
+ }
63
+ async parseDOCX(buffer) {
64
+ try {
65
+ const mammoth = require('mammoth');
66
+ const result = await mammoth.extractRawText({ buffer });
67
+ return result.value || '';
68
+ }
69
+ catch (e) {
70
+ throw new Error(`DOCX parse failed: ${e.message}`);
71
+ }
72
+ }
73
+ parseCSV(text) {
74
+ const lines = text.split('\n').filter(l => l.trim());
75
+ if (lines.length === 0)
76
+ return '';
77
+ const headers = lines[0].split(',').map(h => h.trim().replace(/^"|"$/g, ''));
78
+ const rows = lines.slice(1);
79
+ // Convert CSV to readable text
80
+ return rows.map((row, i) => {
81
+ const values = this.parseCSVLine(row);
82
+ const pairs = headers.map((h, j) => `${h}: ${values[j] || ''}`);
83
+ return `Record ${i + 1}:\n${pairs.join('\n')}`;
84
+ }).join('\n\n');
85
+ }
86
+ parseCSVLine(line) {
87
+ const result = [];
88
+ let current = '';
89
+ let inQuotes = false;
90
+ for (const ch of line) {
91
+ if (ch === '"') {
92
+ inQuotes = !inQuotes;
93
+ }
94
+ else if (ch === ',' && !inQuotes) {
95
+ result.push(current.trim());
96
+ current = '';
97
+ }
98
+ else {
99
+ current += ch;
100
+ }
101
+ }
102
+ result.push(current.trim());
103
+ return result;
104
+ }
105
+ parseJSON(text) {
106
+ try {
107
+ const data = JSON.parse(text);
108
+ if (Array.isArray(data)) {
109
+ return data.map((item, i) => `Item ${i + 1}:\n${JSON.stringify(item, null, 2)}`).join('\n\n');
110
+ }
111
+ return JSON.stringify(data, null, 2);
112
+ }
113
+ catch {
114
+ return text;
115
+ }
116
+ }
117
+ /**
118
+ * Smart chunking: split by headings/paragraphs, respecting size limits
119
+ */
120
+ chunkText(text, filename, format) {
121
+ if (!text.trim())
122
+ return [];
123
+ // Split by markdown headings or double newlines
124
+ const sections = text.split(/\n(?=#{1,3}\s)|(?:\n\s*\n)/).filter(s => s.trim());
125
+ const chunks = [];
126
+ let currentChunk = '';
127
+ let currentTitle = filename;
128
+ for (const section of sections) {
129
+ const headingMatch = section.match(/^(#{1,3})\s+(.+)/);
130
+ if (headingMatch) {
131
+ currentTitle = headingMatch[2].trim();
132
+ }
133
+ if (currentChunk.length + section.length > CHUNK_MAX_CHARS && currentChunk.length > 0) {
134
+ chunks.push({
135
+ title: currentTitle,
136
+ content: currentChunk.trim(),
137
+ metadata: { source: filename, format, chunkIndex: chunks.length },
138
+ });
139
+ currentChunk = '';
140
+ }
141
+ currentChunk += section + '\n\n';
142
+ if (currentChunk.length >= CHUNK_TARGET_CHARS) {
143
+ chunks.push({
144
+ title: currentTitle,
145
+ content: currentChunk.trim(),
146
+ metadata: { source: filename, format, chunkIndex: chunks.length },
147
+ });
148
+ currentChunk = '';
149
+ }
150
+ }
151
+ if (currentChunk.trim()) {
152
+ chunks.push({
153
+ title: currentTitle,
154
+ content: currentChunk.trim(),
155
+ metadata: { source: filename, format, chunkIndex: chunks.length },
156
+ });
157
+ }
158
+ // If we got no chunks from section splitting (e.g. dense text), force-split
159
+ if (chunks.length === 0 && text.trim()) {
160
+ const words = text.split(/\s+/);
161
+ let buf = '';
162
+ for (const w of words) {
163
+ if (buf.length + w.length + 1 > CHUNK_MAX_CHARS && buf) {
164
+ chunks.push({
165
+ title: filename,
166
+ content: buf.trim(),
167
+ metadata: { source: filename, format, chunkIndex: chunks.length },
168
+ });
169
+ buf = '';
170
+ }
171
+ buf += w + ' ';
172
+ }
173
+ if (buf.trim()) {
174
+ chunks.push({
175
+ title: filename,
176
+ content: buf.trim(),
177
+ metadata: { source: filename, format, chunkIndex: chunks.length },
178
+ });
179
+ }
180
+ }
181
+ // Set totalChunks
182
+ for (const c of chunks)
183
+ c.metadata.totalChunks = chunks.length;
184
+ return chunks;
185
+ }
186
+ }
187
+ exports.DocumentProcessor = DocumentProcessor;
188
+ //# sourceMappingURL=document-processor.js.map
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Image Generator — multi-backend image generation tool.
3
+ * Supports DALL·E (OpenAI), Stable Diffusion (local), and Replicate.
4
+ */
5
+ export interface ImageGenConfig {
6
+ provider?: 'dalle' | 'stable-diffusion' | 'replicate';
7
+ openaiApiKey?: string;
8
+ replicateApiKey?: string;
9
+ sdApiUrl?: string;
10
+ defaultModel?: string;
11
+ defaultSize?: string;
12
+ }
13
+ export interface ImageGenResult {
14
+ success: boolean;
15
+ url?: string;
16
+ base64?: string;
17
+ error?: string;
18
+ provider: string;
19
+ }
20
+ export declare class ImageGenerator {
21
+ private config;
22
+ constructor(config?: ImageGenConfig);
23
+ /** Auto-detect best available provider */
24
+ detectProvider(): string | null;
25
+ /** Get configuration status for the settings UI */
26
+ getStatus(): {
27
+ configured: boolean;
28
+ providers: {
29
+ name: string;
30
+ configured: boolean;
31
+ }[];
32
+ };
33
+ generate(prompt: string, options?: {
34
+ provider?: string;
35
+ size?: string;
36
+ model?: string;
37
+ }): Promise<ImageGenResult>;
38
+ private generateDalle;
39
+ private generateSD;
40
+ private generateReplicate;
41
+ }
42
+ //# sourceMappingURL=image-generator.d.ts.map
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ /**
3
+ * Image Generator — multi-backend image generation tool.
4
+ * Supports DALL·E (OpenAI), Stable Diffusion (local), and Replicate.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ImageGenerator = void 0;
8
+ class ImageGenerator {
9
+ config;
10
+ constructor(config) {
11
+ this.config = {
12
+ provider: config?.provider,
13
+ openaiApiKey: config?.openaiApiKey || process.env.OPENAI_API_KEY,
14
+ replicateApiKey: config?.replicateApiKey || process.env.REPLICATE_API_TOKEN,
15
+ sdApiUrl: config?.sdApiUrl || process.env.SD_API_URL,
16
+ defaultModel: config?.defaultModel || 'dall-e-3',
17
+ defaultSize: config?.defaultSize || '1024x1024',
18
+ };
19
+ }
20
+ /** Auto-detect best available provider */
21
+ detectProvider() {
22
+ if (this.config.openaiApiKey)
23
+ return 'dalle';
24
+ if (this.config.sdApiUrl)
25
+ return 'stable-diffusion';
26
+ if (this.config.replicateApiKey)
27
+ return 'replicate';
28
+ return null;
29
+ }
30
+ /** Get configuration status for the settings UI */
31
+ getStatus() {
32
+ return {
33
+ configured: !!this.detectProvider(),
34
+ providers: [
35
+ { name: 'dalle', configured: !!this.config.openaiApiKey },
36
+ { name: 'stable-diffusion', configured: !!this.config.sdApiUrl },
37
+ { name: 'replicate', configured: !!this.config.replicateApiKey },
38
+ ],
39
+ };
40
+ }
41
+ async generate(prompt, options) {
42
+ const provider = options?.provider || this.config.provider || this.detectProvider();
43
+ if (!provider) {
44
+ return { success: false, error: 'No image generation provider configured. Please set OPENAI_API_KEY, SD_API_URL, or REPLICATE_API_TOKEN.', provider: 'none' };
45
+ }
46
+ switch (provider) {
47
+ case 'dalle': return this.generateDalle(prompt, options);
48
+ case 'stable-diffusion': return this.generateSD(prompt, options);
49
+ case 'replicate': return this.generateReplicate(prompt, options);
50
+ default: return { success: false, error: `Unknown provider: ${provider}`, provider };
51
+ }
52
+ }
53
+ async generateDalle(prompt, options) {
54
+ const apiKey = this.config.openaiApiKey;
55
+ if (!apiKey)
56
+ return { success: false, error: 'OPENAI_API_KEY not configured', provider: 'dalle' };
57
+ try {
58
+ const res = await fetch('https://api.openai.com/v1/images/generations', {
59
+ method: 'POST',
60
+ headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
61
+ body: JSON.stringify({
62
+ model: options?.model || this.config.defaultModel || 'dall-e-3',
63
+ prompt,
64
+ size: options?.size || this.config.defaultSize || '1024x1024',
65
+ n: 1,
66
+ }),
67
+ });
68
+ const data = await res.json();
69
+ if (data.error)
70
+ return { success: false, error: data.error.message, provider: 'dalle' };
71
+ const url = data.data?.[0]?.url;
72
+ return url ? { success: true, url, provider: 'dalle' } : { success: false, error: 'No image returned', provider: 'dalle' };
73
+ }
74
+ catch (err) {
75
+ return { success: false, error: err.message, provider: 'dalle' };
76
+ }
77
+ }
78
+ async generateSD(prompt, options) {
79
+ const apiUrl = this.config.sdApiUrl;
80
+ if (!apiUrl)
81
+ return { success: false, error: 'SD_API_URL not configured', provider: 'stable-diffusion' };
82
+ try {
83
+ const [w, h] = (options?.size || '1024x1024').split('x').map(Number);
84
+ const res = await fetch(`${apiUrl}/sdapi/v1/txt2img`, {
85
+ method: 'POST',
86
+ headers: { 'Content-Type': 'application/json' },
87
+ body: JSON.stringify({ prompt, width: w || 1024, height: h || 1024 }),
88
+ });
89
+ const data = await res.json();
90
+ if (data.images?.length) {
91
+ return { success: true, base64: data.images[0], provider: 'stable-diffusion' };
92
+ }
93
+ return { success: false, error: 'No image generated', provider: 'stable-diffusion' };
94
+ }
95
+ catch (err) {
96
+ return { success: false, error: err.message, provider: 'stable-diffusion' };
97
+ }
98
+ }
99
+ async generateReplicate(prompt, _options) {
100
+ const apiKey = this.config.replicateApiKey;
101
+ if (!apiKey)
102
+ return { success: false, error: 'REPLICATE_API_TOKEN not configured', provider: 'replicate' };
103
+ try {
104
+ const res = await fetch('https://api.replicate.com/v1/predictions', {
105
+ method: 'POST',
106
+ headers: { 'Authorization': `Token ${apiKey}`, 'Content-Type': 'application/json' },
107
+ body: JSON.stringify({
108
+ version: 'stability-ai/sdxl:39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b',
109
+ input: { prompt },
110
+ }),
111
+ });
112
+ const prediction = await res.json();
113
+ if (prediction.error)
114
+ return { success: false, error: prediction.error, provider: 'replicate' };
115
+ // Poll for completion (max 60s)
116
+ const getUrl = prediction.urls?.get || `https://api.replicate.com/v1/predictions/${prediction.id}`;
117
+ for (let i = 0; i < 30; i++) {
118
+ await new Promise(r => setTimeout(r, 2000));
119
+ const poll = await fetch(getUrl, { headers: { 'Authorization': `Token ${apiKey}` } });
120
+ const result = await poll.json();
121
+ if (result.status === 'succeeded' && result.output?.length) {
122
+ return { success: true, url: result.output[0], provider: 'replicate' };
123
+ }
124
+ if (result.status === 'failed') {
125
+ return { success: false, error: result.error || 'Generation failed', provider: 'replicate' };
126
+ }
127
+ }
128
+ return { success: false, error: 'Timeout waiting for image generation', provider: 'replicate' };
129
+ }
130
+ catch (err) {
131
+ return { success: false, error: err.message, provider: 'replicate' };
132
+ }
133
+ }
134
+ }
135
+ exports.ImageGenerator = ImageGenerator;
136
+ //# sourceMappingURL=image-generator.js.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Web Scraper - v0.10.0
3
+ * Fetch URL content and extract readable text in markdown format.
4
+ * Uses a simple readability-style extraction (no external dependencies).
5
+ */
6
+ export interface ScrapedContent {
7
+ title: string;
8
+ content: string;
9
+ url: string;
10
+ wordCount: number;
11
+ }
12
+ /**
13
+ * Fetch a URL and extract readable content as markdown.
14
+ */
15
+ export declare function scrapeUrl(url: string, maxLength?: number): Promise<ScrapedContent>;
16
+ /**
17
+ * Extract readable content from HTML using simple heuristics.
18
+ */
19
+ export declare function extractReadableContent(html: string, url: string, maxLength?: number): ScrapedContent;
20
+ //# sourceMappingURL=web-scraper.d.ts.map