prepia 1.0.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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +312 -0
  3. package/bin/prepia.mjs +119 -0
  4. package/package.json +53 -0
  5. package/skill/SKILL.md +148 -0
  6. package/skill/config.json +29 -0
  7. package/src/analytics/dashboard.mjs +84 -0
  8. package/src/analytics/tracker.mjs +131 -0
  9. package/src/api/middleware.mjs +219 -0
  10. package/src/api/routes.mjs +142 -0
  11. package/src/api/server.mjs +150 -0
  12. package/src/cache/disk-store.mjs +199 -0
  13. package/src/cache/manager.mjs +142 -0
  14. package/src/cache/memory-store.mjs +205 -0
  15. package/src/chain/dag.mjs +209 -0
  16. package/src/chain/executor.mjs +103 -0
  17. package/src/chain/scheduler.mjs +89 -0
  18. package/src/client/adapters.mjs +483 -0
  19. package/src/client/connector.mjs +391 -0
  20. package/src/client/index.mjs +483 -0
  21. package/src/client/websocket.mjs +353 -0
  22. package/src/core/context-packager.mjs +169 -0
  23. package/src/core/engine.mjs +338 -0
  24. package/src/core/event-bus.mjs +84 -0
  25. package/src/core/prepimshot.mjs +120 -0
  26. package/src/core/task-decomposer.mjs +158 -0
  27. package/src/edge/lite.mjs +90 -0
  28. package/src/guard/checker.mjs +123 -0
  29. package/src/guard/fact-checker.mjs +105 -0
  30. package/src/guard/hallucination.mjs +108 -0
  31. package/src/index.mjs +67 -0
  32. package/src/models/local-model.mjs +171 -0
  33. package/src/models/provider.mjs +192 -0
  34. package/src/models/router.mjs +156 -0
  35. package/src/morph/optimizer.mjs +142 -0
  36. package/src/network/p2p.mjs +146 -0
  37. package/src/persona/detector.mjs +118 -0
  38. package/src/plugins/loader.mjs +120 -0
  39. package/src/plugins/registry.mjs +164 -0
  40. package/src/plugins/sandbox.mjs +79 -0
  41. package/src/rate/limiter.mjs +145 -0
  42. package/src/rate/shield.mjs +150 -0
  43. package/src/script/executor.mjs +164 -0
  44. package/src/script/parser.mjs +134 -0
  45. package/src/security/privacy.mjs +108 -0
  46. package/src/security/sanitizer.mjs +133 -0
  47. package/src/shadow/daemon.mjs +128 -0
  48. package/src/stream/handler.mjs +204 -0
  49. package/src/tools/calculator.mjs +312 -0
  50. package/src/tools/file-ops.mjs +138 -0
  51. package/src/tools/http-client.mjs +127 -0
  52. package/src/tools/orchestrator.mjs +205 -0
  53. package/src/tools/web-scraper.mjs +159 -0
  54. package/src/tools/web-search.mjs +129 -0
  55. package/src/vault/knowledge-base.mjs +207 -0
  56. package/src/vault/pattern-learner.mjs +192 -0
  57. package/workflows/analyze.json +32 -0
  58. package/workflows/automate.json +32 -0
  59. package/workflows/research.json +37 -0
  60. package/workflows/summarize.json +32 -0
@@ -0,0 +1,483 @@
1
+ /**
2
+ * Prepia Agent Adapters
3
+ * Universal connectors for popular AI agent frameworks
4
+ * Each adapter wraps PrepiClient for framework-specific usage
5
+ */
6
+
7
+ import { PrepiClient, prepiConnect } from './index.mjs';
8
+
9
+ /**
10
+ * Base adapter with common functionality
11
+ */
12
+ class BaseAdapter {
13
+ constructor(config = {}) {
14
+ this.client = typeof config === 'string' ? prepiConnect(config) : new PrepiClient(config);
15
+ this.name = 'base';
16
+ }
17
+
18
+ async init() { await this.client.connect(); }
19
+ async shutdown() { this.client.disconnect(); }
20
+ }
21
+
22
+ // ═══════════════════════════════════════════════════
23
+ // 🔌 OPENCLAW ADAPTER
24
+ // ═══════════════════════════════════════════════════
25
+
26
+ /**
27
+ * OpenClaw Skill Integration
28
+ * Drop this into an OpenClaw skill to use Prepia
29
+ */
30
+ export class OpenClawAdapter extends BaseAdapter {
31
+ constructor(config = {}) {
32
+ super({ ...config, agentType: 'openclaw' });
33
+ this.name = 'openclaw';
34
+ }
35
+
36
+ /**
37
+ * Process a task the OpenClaw way — returns structured result
38
+ * @param {string} task - User's request
39
+ * @param {Object} context - OpenClaw session context
40
+ * @returns {Promise<{ answer: string, sources: Array, tokensSaved: number }>}
41
+ */
42
+ async process(task, context = {}) {
43
+ const result = await this.client.task({
44
+ description: task,
45
+ context: {
46
+ sessionId: context.sessionKey,
47
+ userId: context.userId,
48
+ channel: context.channel,
49
+ },
50
+ mode: this._detectMode(task),
51
+ });
52
+
53
+ return {
54
+ answer: result.data?.answer || result.data?.output || '',
55
+ sources: result.data?.sources || [],
56
+ tokensSaved: result.data?.metrics?.tokensSaved || 0,
57
+ cached: result.data?.cached || false,
58
+ phases: result.data?.phases || [],
59
+ };
60
+ }
61
+
62
+ /**
63
+ * Auto-detect the best processing mode
64
+ * @param {string} task
65
+ * @returns {string}
66
+ */
67
+ _detectMode(task) {
68
+ const lower = task.toLowerCase();
69
+ // Simple factual questions → flash
70
+ if (/^(what|who|when|where|how much|how many|convert|calculate)\b/i.test(lower) && task.length < 100) {
71
+ return 'flash';
72
+ }
73
+ // Complex research → shot with tools
74
+ if (/research|analyze|compare|investigate|find out|look up/i.test(lower)) {
75
+ return 'shot';
76
+ }
77
+ return 'shot';
78
+ }
79
+
80
+ /**
81
+ * Format result for OpenClaw response
82
+ * @param {Object} result
83
+ * @returns {string}
84
+ */
85
+ formatResponse(result) {
86
+ let response = result.answer;
87
+ if (result.cached) response += '\n\n📦 _Served from cache_';
88
+ if (result.tokensSaved > 0) response += `\n⚡ _${result.tokensSaved} tokens saved by Prepia_`;
89
+ return response;
90
+ }
91
+ }
92
+
93
+ // ═══════════════════════════════════════════════════
94
+ // 🤖 AUTO-GPT ADAPTER
95
+ // ═══════════════════════════════════════════════════
96
+
97
+ /**
98
+ * AutoGPT / AgentGPT integration
99
+ */
100
+ export class AutoGPTAdapter extends BaseAdapter {
101
+ constructor(config = {}) {
102
+ super({ ...config, agentType: 'autogpt' });
103
+ this.name = 'autogpt';
104
+ this.goalStack = [];
105
+ }
106
+
107
+ /**
108
+ * Execute a step in the AutoGPT goal loop
109
+ * @param {string} goal - Current goal
110
+ * @param {Object} context - Agent context (thoughts, memories, etc.)
111
+ * @returns {Promise<{ command: string, args: Object, reasoning: string }>}
112
+ */
113
+ async executeStep(goal, context = {}) {
114
+ const result = await this.client.task({
115
+ description: goal,
116
+ mode: 'shot',
117
+ context: {
118
+ previousThoughts: context.thoughts || [],
119
+ memories: context.memories || [],
120
+ constraints: context.constraints || [],
121
+ },
122
+ tools: ['web-search', 'calculator', 'file-ops'],
123
+ });
124
+
125
+ return {
126
+ command: result.data?.suggestedAction || 'respond',
127
+ args: result.data?.actionArgs || {},
128
+ reasoning: result.data?.reasoning || result.data?.answer || '',
129
+ confidence: result.data?.confidence || 0.8,
130
+ };
131
+ }
132
+
133
+ /**
134
+ * Research a topic before acting
135
+ * @param {string} topic
136
+ * @returns {Promise<Object>}
137
+ */
138
+ async research(topic) {
139
+ return this.client.task({
140
+ description: `Research: ${topic}`,
141
+ mode: 'shot',
142
+ tools: ['web-search', 'web-scraper'],
143
+ });
144
+ }
145
+ }
146
+
147
+ // ═══════════════════════════════════════════════════
148
+ // 🚢 CREWAI ADAPTER
149
+ // ═══════════════════════════════════════════════════
150
+
151
+ /**
152
+ * CrewAI integration — Prepia as a crew member
153
+ */
154
+ export class CrewAIAdapter extends BaseAdapter {
155
+ constructor(config = {}) {
156
+ super({ ...config, agentType: 'crewai' });
157
+ this.name = 'crewai';
158
+ }
159
+
160
+ /**
161
+ * Create a Prepia-powered crew agent
162
+ * @param {Object} agentConfig
163
+ * @returns {Object} Agent-like object for CrewAI
164
+ */
165
+ createAgent(agentConfig = {}) {
166
+ const adapter = this;
167
+ return {
168
+ role: agentConfig.role || 'Research Analyst',
169
+ goal: agentConfig.goal || 'Gather and analyze information efficiently',
170
+ backstory: agentConfig.backstory || 'Powered by Prepia middleware for optimized AI tasks',
171
+ tools: agentConfig.tools || ['web-search', 'calculator'],
172
+
173
+ /**
174
+ * CrewAI calls this to execute a task
175
+ */
176
+ async executeTask(taskDescription) {
177
+ const result = await adapter.client.task({
178
+ description: taskDescription,
179
+ mode: 'shot',
180
+ context: { role: agentConfig.role },
181
+ });
182
+ return result.data?.answer || result.data?.output || '';
183
+ },
184
+
185
+ /**
186
+ * CrewAI calls this for delegation
187
+ */
188
+ async delegateTask(taskDescription, targetRole) {
189
+ return adapter.client.task({
190
+ description: taskDescription,
191
+ mode: 'shot',
192
+ context: { delegatedTo: targetRole },
193
+ });
194
+ },
195
+ };
196
+ }
197
+ }
198
+
199
+ // ═══════════════════════════════════════════════════
200
+ // 🔗 LANGCHAIN ADAPTER
201
+ // ═══════════════════════════════════════════════════
202
+
203
+ /**
204
+ * LangChain integration — Prepia as a tool/chain
205
+ */
206
+ export class LangChainAdapter extends BaseAdapter {
207
+ constructor(config = {}) {
208
+ super({ ...config, agentType: 'langchain' });
209
+ this.name = 'langchain';
210
+ }
211
+
212
+ /**
213
+ * Create a LangChain-compatible tool
214
+ * @param {string} name - Tool name
215
+ * @param {string} description - Tool description
216
+ * @returns {Object} LangChain Tool-like object
217
+ */
218
+ createTool(name = 'prepia', description = 'AI-powered research and task execution') {
219
+ const adapter = this;
220
+ return {
221
+ name,
222
+ description,
223
+ schema: {
224
+ type: 'object',
225
+ properties: {
226
+ query: { type: 'string', description: 'The task or question to process' },
227
+ },
228
+ required: ['query'],
229
+ },
230
+ async _call(input) {
231
+ const query = typeof input === 'string' ? input : input.query;
232
+ const result = await adapter.client.task({
233
+ description: query,
234
+ mode: 'shot',
235
+ });
236
+ return result.data?.answer || result.data?.output || JSON.stringify(result.data);
237
+ },
238
+ };
239
+ }
240
+
241
+ /**
242
+ * Create a LangChain-compatible chain
243
+ * @returns {Object} Chain-like object
244
+ */
245
+ createChain() {
246
+ const adapter = this;
247
+ return {
248
+ async invoke(input) {
249
+ const query = typeof input === 'string' ? input : input.input || input.query;
250
+ const result = await adapter.client.task({
251
+ description: query,
252
+ mode: 'shot',
253
+ });
254
+ return { output: result.data?.answer || result.data?.output || '' };
255
+ },
256
+ async batch(inputs) {
257
+ return Promise.all(inputs.map(input => this.invoke(input)));
258
+ },
259
+ };
260
+ }
261
+ }
262
+
263
+ // ═══════════════════════════════════════════════════
264
+ // 🦜 SEMANTIC KERNEL ADAPTER
265
+ // ═══════════════════════════════════════════════════
266
+
267
+ /**
268
+ * Microsoft Semantic Kernel integration
269
+ */
270
+ export class SemanticKernelAdapter extends BaseAdapter {
271
+ constructor(config = {}) {
272
+ super({ ...config, agentType: 'semantic-kernel' });
273
+ this.name = 'semantic-kernel';
274
+ }
275
+
276
+ /**
277
+ * Create a Semantic Kernel function
278
+ * @param {string} functionName
279
+ * @returns {Object}
280
+ */
281
+ createFunction(functionName = 'PrepiaTask') {
282
+ const adapter = this;
283
+ return {
284
+ name: functionName,
285
+ description: 'Execute a task using Prepia middleware',
286
+ parameters: [
287
+ { name: 'task', type: 'string', description: 'Task to execute', required: true },
288
+ { name: 'mode', type: 'string', description: 'Processing mode', required: false },
289
+ ],
290
+ async invoke(args) {
291
+ const result = await adapter.client.task({
292
+ description: args.task,
293
+ mode: args.mode || 'shot',
294
+ });
295
+ return result.data?.answer || result.data?.output || '';
296
+ },
297
+ };
298
+ }
299
+ }
300
+
301
+ // ═══════════════════════════════════════════════════
302
+ // 🐍 PYTHON BRIDGE ADAPTER
303
+ // ═══════════════════════════════════════════════════
304
+
305
+ /**
306
+ * For Python-based agents (AutoGen, CrewAI Python, custom)
307
+ * Generates a Python client that communicates with Prepia via HTTP
308
+ */
309
+ export class PythonBridgeAdapter extends BaseAdapter {
310
+ constructor(config = {}) {
311
+ super({ ...config, agentType: 'python' });
312
+ this.name = 'python-bridge';
313
+ }
314
+
315
+ /**
316
+ * Generate Python client code
317
+ * @returns {string} Python source code for the client
318
+ */
319
+ generatePythonClient() {
320
+ const host = this.client.host;
321
+ const port = this.client.port;
322
+ return `
323
+ """
324
+ PrepiPy - Python client for Prepia middleware
325
+ Auto-generated by Prepia Universal Adapter
326
+ """
327
+ import json
328
+ import urllib.request
329
+ import urllib.error
330
+
331
+ class PrepiClient:
332
+ def __init__(self, host="${host}", port=${port}, api_key=None, timeout=300):
333
+ self.base_url = f"http://{host}:{port}"
334
+ self.api_key = api_key
335
+ self.timeout = timeout
336
+
337
+ def _request(self, method, path, body=None):
338
+ url = f"{self.base_url}{path}"
339
+ headers = {"Content-Type": "application/json", "X-Prepia-Agent-Type": "python"}
340
+ if self.api_key:
341
+ headers["Authorization"] = f"Bearer {self.api_key}"
342
+ data = json.dumps(body).encode() if body else None
343
+ req = urllib.request.Request(url, data=data, headers=headers, method=method)
344
+ try:
345
+ with urllib.request.urlopen(req, timeout=self.timeout) as resp:
346
+ return json.loads(resp.read().decode())
347
+ except urllib.error.HTTPError as e:
348
+ error_data = json.loads(e.read().decode())
349
+ raise Exception(error_data.get("error", f"HTTP {e.code}"))
350
+
351
+ def task(self, description, mode="shot", **kwargs):
352
+ body = {"description": description, "mode": mode, "agentType": "python", **kwargs}
353
+ return self._request("POST", "/api/task", body)
354
+
355
+ def quick(self, query):
356
+ return self.task(query, mode="flash")
357
+
358
+ def health(self):
359
+ return self._request("GET", "/api/health")
360
+
361
+ def analytics(self):
362
+ return self._request("GET", "/api/analytics")
363
+
364
+ # Quick usage:
365
+ # prepi = PrepiClient()
366
+ # result = prepi.task("Research top 5 phones")
367
+ # print(result["data"]["answer"])
368
+ `;
369
+ }
370
+ }
371
+
372
+ // ═══════════════════════════════════════════════════
373
+ // 🌐 GENERIC REST ADAPTER
374
+ // ═══════════════════════════════════════════════════
375
+
376
+ /**
377
+ * For any agent that can make HTTP requests
378
+ * Provides a simple REST-like interface
379
+ */
380
+ export class RestAdapter extends BaseAdapter {
381
+ constructor(config = {}) {
382
+ super({ ...config, agentType: 'rest-client' });
383
+ this.name = 'rest';
384
+ }
385
+
386
+ /**
387
+ * Get OpenAPI-compatible spec for Prepia
388
+ * @returns {Object}
389
+ */
390
+ getOpenAPISpec() {
391
+ return {
392
+ openapi: '3.0.0',
393
+ info: {
394
+ title: 'Prepia API',
395
+ version: '1.0.0',
396
+ description: 'AI middleware that reduces LLM calls by 80-95%',
397
+ },
398
+ servers: [{ url: this.client.baseUrl }],
399
+ paths: {
400
+ '/api/task': {
401
+ post: {
402
+ summary: 'Submit a task',
403
+ requestBody: {
404
+ content: {
405
+ 'application/json': {
406
+ schema: {
407
+ type: 'object',
408
+ properties: {
409
+ description: { type: 'string' },
410
+ mode: { type: 'string', enum: ['flash', 'shot', 'stream'] },
411
+ tools: { type: 'array', items: { type: 'string' } },
412
+ cache: { type: 'boolean' },
413
+ },
414
+ required: ['description'],
415
+ },
416
+ },
417
+ },
418
+ },
419
+ responses: {
420
+ 200: { description: 'Task result' },
421
+ 429: { description: 'Rate limited' },
422
+ 500: { description: 'Server error' },
423
+ },
424
+ },
425
+ },
426
+ '/api/health': {
427
+ get: { summary: 'Health check', responses: { 200: { description: 'OK' } } },
428
+ },
429
+ '/api/analytics': {
430
+ get: { summary: 'Usage analytics', responses: { 200: { description: 'Analytics data' } } },
431
+ },
432
+ },
433
+ };
434
+ }
435
+ }
436
+
437
+ // ═══════════════════════════════════════════════════
438
+ // 🏭 ADAPTER FACTORY
439
+ // ═══════════════════════════════════════════════════
440
+
441
+ const ADAPTERS = {
442
+ openclaw: OpenClawAdapter,
443
+ autogpt: AutoGPTAdapter,
444
+ crewai: CrewAIAdapter,
445
+ langchain: LangChainAdapter,
446
+ 'semantic-kernel': SemanticKernelAdapter,
447
+ python: PythonBridgeAdapter,
448
+ rest: RestAdapter,
449
+ };
450
+
451
+ /**
452
+ * Create an adapter for a specific agent framework
453
+ * @param {string} framework - Framework name
454
+ * @param {Object} config - Connection config
455
+ * @returns {BaseAdapter}
456
+ */
457
+ export function createAdapter(framework, config = {}) {
458
+ const AdapterClass = ADAPTERS[framework.toLowerCase()];
459
+ if (!AdapterClass) {
460
+ throw new Error(`Unknown framework: ${framework}. Available: ${Object.keys(ADAPTERS).join(', ')}`);
461
+ }
462
+ return new AdapterClass(config);
463
+ }
464
+
465
+ /**
466
+ * List all available adapters
467
+ * @returns {string[]}
468
+ */
469
+ export function listAdapters() {
470
+ return Object.keys(ADAPTERS);
471
+ }
472
+
473
+ export default {
474
+ OpenClawAdapter,
475
+ AutoGPTAdapter,
476
+ CrewAIAdapter,
477
+ LangChainAdapter,
478
+ SemanticKernelAdapter,
479
+ PythonBridgeAdapter,
480
+ RestAdapter,
481
+ createAdapter,
482
+ listAdapters,
483
+ };