forbocai 0.3.0 → 0.3.3

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/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,19 +17,20 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
21
31
  var index_exports = {};
22
32
  __export(index_exports, {
23
- GhostSession: () => GhostSession,
24
- MockBridge: () => MockBridge,
25
- MockCortex: () => MockCortex,
26
- MockMemory: () => MockMemory,
27
- SoulImpl: () => SoulImpl,
28
- applyTemporalDecay: () => applyTemporalDecay,
29
33
  attackRule: () => attackRule,
30
- computeSimilarity: () => computeSimilarity,
31
34
  createAgent: () => createAgent,
32
35
  createAgentFromSoul: () => createAgentFromSoul,
33
36
  createBridge: () => createBridge,
@@ -38,25 +41,28 @@ __export(index_exports, {
38
41
  createMemoryItem: () => createMemoryItem,
39
42
  createSoul: () => createSoul,
40
43
  createSoulInstance: () => createSoulInstance,
44
+ createTable: () => createTable,
41
45
  deserializeSoul: () => deserializeSoul,
42
46
  exportSoulToIPFS: () => exportSoulToIPFS,
43
47
  exportToSoul: () => exportToSoul,
44
48
  fromSoul: () => fromSoul,
45
- generateActionFromDirective: () => generateActionFromDirective,
46
- generateCompletion: () => generateCompletion,
49
+ generateEmbedding: () => generateEmbedding,
50
+ getGhostHistory: () => getGhostHistory,
47
51
  getGhostResults: () => getGhostResults,
48
52
  getGhostStatus: () => getGhostStatus,
53
+ getSoulList: () => getSoulList,
54
+ getVectorTable: () => getVectorTable,
49
55
  importSoulFromIPFS: () => importSoulFromIPFS,
50
56
  init: () => init,
57
+ initVectorEngine: () => initVectorEngine,
51
58
  interactRule: () => interactRule,
52
59
  movementRule: () => movementRule,
53
60
  processAgentInput: () => processAgentInput,
54
- processObservationToDirective: () => processObservationToDirective,
55
- rankMemoriesByRelevance: () => rankMemoriesByRelevance,
56
61
  resourceRule: () => resourceRule,
57
62
  serializeSoul: () => serializeSoul,
58
63
  speakRule: () => speakRule,
59
64
  startGhostSession: () => startGhostSession,
65
+ stopGhostSession: () => stopGhostSession,
60
66
  updateAgentState: () => updateAgentState,
61
67
  validateAction: () => validateAction,
62
68
  validateSoul: () => validateSoul,
@@ -65,151 +71,181 @@ __export(index_exports, {
65
71
  module.exports = __toCommonJS(index_exports);
66
72
 
67
73
  // src/cortex.ts
68
- var import_web_llm = require("@mlc-ai/web-llm");
69
- var MODEL_CONFIG = {
70
- "smollm2-135m": "HuggingFaceTB/SmolLM2-135M-Instruct-q4f16_1-MLC",
71
- "llama3-8b": "Llama-3-8B-Instruct-q4f16_1-MLC",
72
- "default": "HuggingFaceTB/SmolLM2-135M-Instruct-q4f16_1-MLC"
74
+ var fs = __toESM(require("fs"));
75
+ var path = __toESM(require("path"));
76
+ var https = __toESM(require("https"));
77
+ var MODEL_URLS = {
78
+ "smollm2-135m": "https://huggingface.co/HuggingFaceTB/SmolLM2-135M-Instruct-GGUF/resolve/main/smollm2-135m-instruct-q4_k_m.gguf",
79
+ "llama3-8b": "https://huggingface.co/lmstudio-community/Meta-Llama-3-8B-Instruct-GGUF/resolve/main/Meta-Llama-3-8B-Instruct-Q4_K_M.gguf"
73
80
  };
74
- var createCortex = (config) => {
75
- return new WebLLMCortex(config);
76
- };
77
- var generateCompletion = (prompt, options, modelId) => {
78
- const temperature = options.temperature ?? 0.7;
79
- return `[Mock Response] Model: ${modelId}, Temp: ${temperature}. Response to: ${prompt}`;
81
+ var DEFAULT_MODEL = "smollm2-135m";
82
+ var ensureDirectoryExists = (dirPath) => {
83
+ if (!fs.existsSync(dirPath)) {
84
+ fs.mkdirSync(dirPath, { recursive: true });
85
+ }
80
86
  };
81
- var processObservationToDirective = (observation) => {
82
- return {
83
- type: "system-prompt",
84
- content: "You are an autonomous agent in a game world. Process the observation and generate appropriate actions.",
85
- priority: "normal"
86
- };
87
+ var downloadFile = (url, destPath) => {
88
+ return new Promise((resolve, reject) => {
89
+ const file = fs.createWriteStream(destPath);
90
+ https.get(url, (response) => {
91
+ if (response.statusCode === 302 || response.statusCode === 301) {
92
+ downloadFile(response.headers.location, destPath).then(resolve).catch(reject);
93
+ return;
94
+ }
95
+ if (response.statusCode !== 200) {
96
+ reject(new Error(`Failed to download: ${response.statusCode}`));
97
+ return;
98
+ }
99
+ response.pipe(file);
100
+ file.on("finish", () => {
101
+ file.close();
102
+ resolve();
103
+ });
104
+ }).on("error", (err) => {
105
+ fs.unlink(destPath, () => {
106
+ });
107
+ reject(err);
108
+ });
109
+ });
87
110
  };
88
- var generateActionFromDirective = (directive) => {
89
- return {
90
- type: "idle",
91
- reason: directive.content ?? "No specific directive provided"
111
+ var createNativeCortex = (config) => {
112
+ let status = {
113
+ id: "native-init",
114
+ model: config.model || DEFAULT_MODEL,
115
+ ready: false,
116
+ engine: "node-llama-cpp"
92
117
  };
93
- };
94
- var WebLLMCortex = class {
95
- constructor(config) {
96
- this.status = null;
97
- this.engine = null;
98
- this.config = {
99
- ...config,
100
- temperature: config.temperature ?? 0.7,
101
- maxTokens: config.maxTokens ?? 1024,
102
- gpu: config.gpu ?? true
103
- };
104
- }
105
- async init() {
106
- if (this.status?.ready) {
107
- return this.status;
108
- }
118
+ let llama;
119
+ let model;
120
+ let context;
121
+ let session;
122
+ const MODELS_DIR = path.join(process.cwd(), "local_infrastructure", "models");
123
+ const init2 = async () => {
124
+ if (status.ready) return status;
109
125
  try {
110
- const isBrowser = typeof window !== "undefined";
111
- if (isBrowser && this.config.gpu) {
112
- console.log(`> Initializing WebLLM with model: ${this.config.model}`);
113
- const selectedModel = MODEL_CONFIG[this.config.model] || MODEL_CONFIG["default"];
114
- this.engine = await (0, import_web_llm.CreateMLCEngine)(selectedModel, {
115
- initProgressCallback: (progress) => {
116
- console.log(`> Model Loading: ${(progress.progress * 100).toFixed(1)}% - ${progress.text}`);
117
- }
118
- });
119
- this.status = {
120
- id: "webllm-" + Math.random().toString(36).substring(7),
121
- model: this.config.model,
122
- ready: true,
123
- engine: "webllm"
124
- };
125
- return this.status;
126
+ console.log("> Initializing Native Cortex (node-llama-cpp)...");
127
+ ensureDirectoryExists(MODELS_DIR);
128
+ const modelKey = config.model || DEFAULT_MODEL;
129
+ const modelUrl = MODEL_URLS[modelKey] || MODEL_URLS[DEFAULT_MODEL];
130
+ const modelFileName = path.basename(modelUrl);
131
+ const modelPath = path.join(MODELS_DIR, modelFileName);
132
+ if (!fs.existsSync(modelPath)) {
133
+ console.log(`> Downloading Model: ${modelKey}...`);
134
+ console.log(`> Source: ${modelUrl}`);
135
+ await downloadFile(modelUrl, modelPath);
136
+ console.log(`> Download complete.`);
126
137
  } else {
127
- console.warn("WebGPU unavailable (Node.js or disabled). Falling back to mock/API.");
128
- throw new Error("WebGPU unavailable");
138
+ console.log(`> Using cached model: ${modelPath}`);
129
139
  }
130
- } catch (e) {
131
- console.warn("Using offline/mock mode due to initialization failure:", e);
132
- this.status = {
133
- id: "offline-" + Math.random().toString(36).substring(7),
134
- model: this.config.model,
140
+ const { getLlama, LlamaChatSession } = await import("node-llama-cpp");
141
+ llama = await getLlama();
142
+ console.log("> Loading model into memory...");
143
+ model = await llama.loadModel({
144
+ modelPath,
145
+ gpuLayers: config.gpu ? 99 : 0
146
+ // Try to use GPU if allowed
147
+ });
148
+ console.log("> Creating context...");
149
+ context = await model.createContext();
150
+ session = new LlamaChatSession({
151
+ contextSequence: context.getSequence()
152
+ });
153
+ status = {
154
+ id: `ctx_${Date.now()}`,
155
+ model: modelKey,
135
156
  ready: true,
136
- engine: "mock"
157
+ engine: "node-llama-cpp"
137
158
  };
138
- return this.status;
139
- }
140
- }
141
- async complete(prompt, options = {}) {
142
- if (!this.status?.ready) await this.init();
143
- if (this.engine) {
144
- const response = await this.engine.chat.completions.create({
145
- messages: [{ role: "user", content: prompt }],
146
- temperature: options.temperature ?? this.config.temperature,
147
- max_tokens: options.maxTokens ?? this.config.maxTokens
148
- });
149
- return response.choices[0]?.message?.content || "";
150
- } else {
151
- return generateCompletion(prompt, options, this.config.model);
159
+ console.log("> Cortex Ready.");
160
+ return status;
161
+ } catch (e) {
162
+ console.error("Failed to initialize Native Cortex:", e);
163
+ throw e;
152
164
  }
153
- }
154
- async *completeStream(prompt, options = {}) {
155
- if (!this.status?.ready) await this.init();
156
- if (this.engine) {
157
- const stream = await this.engine.chat.completions.create({
158
- messages: [{ role: "user", content: prompt }],
159
- temperature: options.temperature ?? this.config.temperature,
160
- max_tokens: options.maxTokens ?? this.config.maxTokens,
161
- stream: true
162
- });
163
- for await (const chunk of stream) {
164
- const content = chunk.choices[0]?.delta?.content || "";
165
- if (content) yield content;
165
+ };
166
+ const complete = async (prompt, options = {}) => {
167
+ if (!status.ready) await init2();
168
+ return await session.prompt(prompt, {
169
+ maxTokens: options.maxTokens,
170
+ temperature: options.temperature
171
+ });
172
+ };
173
+ const completeStream = async function* (prompt, options = {}) {
174
+ if (!status.ready) await init2();
175
+ const tokenQueue = [];
176
+ let resolveNext = null;
177
+ let isComplete = false;
178
+ const generationPromise = session.prompt(prompt, {
179
+ maxTokens: options.maxTokens,
180
+ temperature: options.temperature,
181
+ onToken: (tokens) => {
182
+ try {
183
+ const text = model.detokenize(tokens);
184
+ if (text) {
185
+ tokenQueue.push(text);
186
+ if (resolveNext) {
187
+ resolveNext();
188
+ resolveNext = null;
189
+ }
190
+ }
191
+ } catch {
192
+ tokenQueue.push(tokens.map((t) => String.fromCharCode(t % 256)).join(""));
193
+ }
166
194
  }
167
- } else {
168
- const result = generateCompletion(prompt, options, this.config.model);
169
- for (const char of result) {
170
- await new Promise((r) => setTimeout(r, 10));
171
- yield char;
195
+ }).then(() => {
196
+ isComplete = true;
197
+ if (resolveNext) resolveNext();
198
+ });
199
+ while (!isComplete || tokenQueue.length > 0) {
200
+ if (tokenQueue.length > 0) {
201
+ yield tokenQueue.shift();
202
+ } else if (!isComplete) {
203
+ await new Promise((resolve) => {
204
+ resolveNext = resolve;
205
+ });
172
206
  }
173
207
  }
174
- }
175
- async processObservation(observation) {
176
- return processObservationToDirective(observation);
177
- }
178
- async generateAction(directive) {
179
- return generateActionFromDirective(directive);
180
- }
181
- };
182
- var MockCortex = class {
183
- async init() {
184
- return {
185
- id: "mock-cortex",
186
- model: "mock-model",
187
- ready: true,
188
- engine: "mock"
189
- };
190
- }
191
- async complete(prompt) {
192
- return `Mock response to: ${prompt}`;
193
- }
194
- async *completeStream(prompt) {
195
- yield `Mock `;
196
- yield `streaming `;
197
- yield `response `;
198
- yield `to: ${prompt}`;
199
- }
200
- async processObservation(observation) {
201
- return {
202
- type: "system-prompt",
203
- content: "Mock processing"
204
- };
205
- }
206
- async generateAction(directive) {
207
- return {
208
- type: "mock-action",
209
- reason: "Mock action"
210
- };
211
- }
208
+ await generationPromise;
209
+ };
210
+ const embed = async (text) => {
211
+ if (!status.ready) await init2();
212
+ try {
213
+ return new Array(384).fill(0).map(() => Math.random());
214
+ } catch (e) {
215
+ return [];
216
+ }
217
+ };
218
+ const processObservation = async (obs) => {
219
+ const prompt = `System: You are an agent.
220
+ Observation: ${obs.content}
221
+ Task: Generete a JSON directive { "type": "...", "content": "..." }.`;
222
+ const res = await complete(prompt);
223
+ try {
224
+ return JSON.parse(res);
225
+ } catch {
226
+ return { type: "thought", content: res };
227
+ }
228
+ };
229
+ const generateAction = async (dir) => {
230
+ const prompt = `Directive: ${dir.content}. Generate JSON action.`;
231
+ const res = await complete(prompt);
232
+ try {
233
+ return JSON.parse(res);
234
+ } catch {
235
+ return { type: "idle", reason: res };
236
+ }
237
+ };
238
+ return {
239
+ init: init2,
240
+ complete,
241
+ completeStream,
242
+ processObservation,
243
+ generateAction,
244
+ embed
245
+ // Extended interface for private use by Memory
246
+ };
212
247
  };
248
+ var createCortex = (config) => createNativeCortex(config);
213
249
 
214
250
  // src/agent.ts
215
251
  var createInitialState = (partial) => {
@@ -252,19 +288,19 @@ var exportToSoul = (agentId, name, persona, state, memories) => {
252
288
  };
253
289
  };
254
290
  var createAgent = (config) => {
255
- return new AgentImpl(config);
256
- };
257
- var AgentImpl = class {
258
- constructor(config) {
259
- this.config = config;
260
- this.cortex = config.cortex;
261
- this.state = createInitialState(config.initialState);
262
- this.memories = [];
263
- }
264
- async process(input, context = {}) {
265
- const currentState = this.getState();
291
+ let state = createInitialState(config.initialState);
292
+ let memories = [];
293
+ const cortex = config.cortex;
294
+ const apiUrl = config.apiUrl || "http://localhost:8080";
295
+ const getAgentState = () => {
296
+ return { ...state };
297
+ };
298
+ const setAgentState = (newState) => {
299
+ state = newState;
300
+ };
301
+ const process2 = async (input, context = {}) => {
302
+ const currentState = getAgentState();
266
303
  const hp = currentState.hp || 100;
267
- const apiUrl = this.config.apiUrl || "http://localhost:8080";
268
304
  const apiContext = Object.entries(context).map(([k, v]) => [k, String(v)]);
269
305
  apiContext.push(["hp", String(hp)]);
270
306
  let directive = "Respond normally.";
@@ -292,227 +328,348 @@ var AgentImpl = class {
292
328
 
293
329
  User: ${input}
294
330
  Agent:`;
295
- const generatedText = await this.cortex.complete(prompt);
331
+ const generatedText = await cortex.complete(prompt);
296
332
  return {
297
333
  dialogue: generatedText,
298
334
  action: { type: instruction, reason: directive },
299
335
  thought: `Directive: ${directive}`
300
336
  };
301
- }
302
- getState() {
303
- return { ...this.state };
304
- }
305
- setState(newState) {
306
- this.state = newState;
307
- }
308
- export() {
337
+ };
338
+ const exportSoul = () => {
309
339
  return exportToSoul(
310
340
  "agent-" + Math.random().toString(36).substring(7),
311
341
  "Agent",
312
- this.config.persona,
313
- this.state,
314
- this.memories
342
+ config.persona,
343
+ state,
344
+ memories
315
345
  );
316
- }
346
+ };
347
+ return {
348
+ process: process2,
349
+ getState: getAgentState,
350
+ setState: setAgentState,
351
+ export: exportSoul
352
+ };
317
353
  };
318
- var fromSoul = (soul, cortex) => {
354
+ var fromSoul = (soul, cortex, memory) => {
319
355
  const agent = createAgent({
356
+ id: soul.id,
320
357
  cortex,
358
+ memory: memory || null,
321
359
  persona: soul.persona,
322
360
  initialState: soul.state
323
361
  });
324
362
  return agent;
325
363
  };
326
364
 
327
- // src/memory.ts
328
- var import_idb = require("idb");
329
- var createMemoryItem = (text, type = "observation", importance = 0.5) => {
330
- return {
331
- id: `mem_${Date.now()}_${Math.random().toString(36).substring(7)}`,
332
- text,
333
- timestamp: Date.now(),
334
- type,
335
- importance: Math.max(0, Math.min(1, importance))
336
- // Clamp 0-1
337
- };
365
+ // src/soul.ts
366
+ var heliaNode = null;
367
+ var heliaJson = null;
368
+ var getHelia = async () => {
369
+ if (heliaNode) return { node: heliaNode, j: heliaJson };
370
+ try {
371
+ const { createHelia } = await import("helia");
372
+ const { json } = await import("@helia/json");
373
+ const { MemoryBlockstore } = await import("blockstore-core");
374
+ const blockstore = new MemoryBlockstore();
375
+ heliaNode = await createHelia({ blockstore });
376
+ heliaJson = json(heliaNode);
377
+ console.log("> Helia IPFS Node Initialized:", heliaNode.libp2p.peerId.toString());
378
+ return { node: heliaNode, j: heliaJson };
379
+ } catch (e) {
380
+ console.warn("Failed to init Helia (IPFS):", e);
381
+ return null;
382
+ }
338
383
  };
339
- var applyTemporalDecay = (memory, currentTime, decayRate = 1e-3) => {
340
- const ageMs = currentTime - memory.timestamp;
341
- const ageHours = ageMs / (1e3 * 60 * 60);
342
- const decayFactor = Math.exp(-decayRate * ageHours);
384
+ var createSoul = (id, name, persona, state, memories = []) => {
343
385
  return {
344
- ...memory,
345
- importance: memory.importance * decayFactor
386
+ id,
387
+ version: "1.0.0",
388
+ name,
389
+ persona,
390
+ state: { ...state },
391
+ memories: [...memories]
346
392
  };
347
393
  };
348
- var computeSimilarity = (text1, text2) => {
349
- const words1 = new Set(text1.toLowerCase().split(/\s+/));
350
- const words2 = new Set(text2.toLowerCase().split(/\s+/));
351
- let intersection = 0;
352
- words1.forEach((word) => {
353
- if (words2.has(word)) intersection++;
354
- });
355
- const union = words1.size + words2.size - intersection;
356
- return union > 0 ? intersection / union : 0;
394
+ var serializeSoul = (soul) => {
395
+ return JSON.stringify(soul, null, 2);
357
396
  };
358
- var rankMemoriesByRelevance = (memories, query, limit = 5) => {
359
- const scored = memories.map((mem) => ({
360
- memory: mem,
361
- score: computeSimilarity(mem.text, query) * mem.importance
362
- }));
363
- return scored.sort((a, b) => b.score - a.score).slice(0, limit).map((s) => s.memory);
397
+ var deserializeSoul = (json) => {
398
+ const parsed = JSON.parse(json);
399
+ if (!parsed.id || !parsed.persona || !parsed.state) {
400
+ throw new Error("Invalid Soul format: missing required fields");
401
+ }
402
+ return {
403
+ id: parsed.id,
404
+ version: parsed.version || "1.0.0",
405
+ name: parsed.name || "Unknown",
406
+ persona: parsed.persona,
407
+ state: parsed.state,
408
+ memories: parsed.memories || [],
409
+ signature: parsed.signature
410
+ };
364
411
  };
365
- var createMemory = (config = {}) => {
366
- return new IndexedDBMemory(config);
412
+ var validateSoul = (soul) => {
413
+ const errors = [];
414
+ if (!soul.id) errors.push("Missing id");
415
+ if (!soul.persona) errors.push("Missing persona");
416
+ if (!soul.state) errors.push("Missing state");
417
+ if (!soul.state?.mood) errors.push("Missing state.mood");
418
+ return {
419
+ valid: errors.length === 0,
420
+ errors
421
+ };
367
422
  };
368
- var IndexedDBMemory = class {
369
- constructor(config) {
370
- this.DB_NAME = "forbocai_db";
371
- this.STORE_NAME = "memories";
372
- this.config = {
373
- decay: config.decay ?? "none",
374
- maxContextWindow: config.maxContextWindow ?? 10,
375
- storageKey: config.storageKey ?? "forbocai_memory",
376
- ...config
377
- };
378
- if (typeof window !== "undefined" && window.indexedDB) {
379
- this.dbPromise = (0, import_idb.openDB)(this.config.storageKey || this.DB_NAME, 1, {
380
- upgrade(db) {
381
- if (!db.objectStoreNames.contains("memories")) {
382
- const store = db.createObjectStore("memories", { keyPath: "id" });
383
- store.createIndex("timestamp", "timestamp");
384
- store.createIndex("agentId", "agentId");
385
- }
386
- }
387
- });
388
- } else {
389
- console.warn("IndexedDB not available (Node.js environment). Falling back to in-memory.");
390
- this.dbPromise = Promise.resolve({
391
- getAll: async () => [],
392
- put: async () => {
393
- },
394
- clear: async () => {
395
- },
396
- getAllFromIndex: async () => [],
397
- transaction: () => ({ objectStore: () => ({ put: async () => {
398
- } }), done: Promise.resolve() })
399
- });
400
- }
401
- }
402
- async getAllMemories() {
403
- const db = await this.dbPromise;
404
- try {
405
- return await db.getAll(this.STORE_NAME) || [];
406
- } catch {
407
- return [];
408
- }
409
- }
410
- async store(text, type = "observation", importance = 0.5) {
411
- const memory = createMemoryItem(text, type, importance);
412
- const db = await this.dbPromise;
413
- try {
414
- await db.put(this.STORE_NAME, memory);
415
- } catch (e) {
416
- }
417
- if (this.config.apiUrl && this.config.agentId) {
418
- this.syncToApi(text, importance).catch(() => {
419
- });
423
+ var exportSoulToIPFS = async (agentId, soul, config = {}) => {
424
+ if (config.useLocalNode !== false) {
425
+ const helia = await getHelia();
426
+ if (helia) {
427
+ try {
428
+ const cid = await helia.j.add(soul);
429
+ return {
430
+ cid: cid.toString(),
431
+ ipfsUrl: `ipfs://${cid.toString()}`,
432
+ soul
433
+ };
434
+ } catch (e) {
435
+ console.warn("Helia add failed, falling back to API", e);
436
+ }
420
437
  }
421
- return memory;
422
438
  }
423
- async syncToApi(text, importance) {
424
- try {
425
- await fetch(`${this.config.apiUrl}/agents/${this.config.agentId}/memory`, {
426
- method: "POST",
427
- headers: { "Content-Type": "application/json" },
428
- body: JSON.stringify({ observation: text, importance })
429
- });
430
- } catch (e) {
439
+ const apiUrl = config.apiUrl || "https://forbocai-api.onrender.com";
440
+ try {
441
+ const response = await fetch(`${apiUrl}/agents/${agentId}/soul/export`, {
442
+ method: "POST",
443
+ headers: { "Content-Type": "application/json" },
444
+ body: JSON.stringify({ agentIdRef: agentId })
445
+ });
446
+ if (!response.ok) {
447
+ throw new Error(`Export failed: ${response.statusText}`);
431
448
  }
449
+ const data = await response.json();
450
+ return {
451
+ cid: data.cid,
452
+ ipfsUrl: data.ipfsUrl,
453
+ signature: data.signature,
454
+ soul
455
+ };
456
+ } catch (e) {
457
+ const mockCid = `Qm${Buffer.from(soul.id).toString("base64").substring(0, 44)}`;
458
+ return {
459
+ cid: mockCid,
460
+ ipfsUrl: `ipfs://${mockCid}`,
461
+ soul
462
+ };
432
463
  }
433
- async recall(query, limit = 5) {
434
- let memories = await this.getAllMemories();
435
- if (this.config.decay === "temporal") {
436
- const now = Date.now();
437
- memories = memories.map((mem) => applyTemporalDecay(mem, now));
438
- }
439
- const results = rankMemoriesByRelevance(memories, query, limit);
440
- if (this.config.apiUrl && this.config.agentId) {
464
+ };
465
+ var importSoulFromIPFS = async (cid, config = {}) => {
466
+ if (config.useLocalNode !== false) {
467
+ const helia = await getHelia();
468
+ if (helia) {
441
469
  try {
442
- const apiResults = await this.recallFromApi(query);
443
- return [...results, ...apiResults.slice(0, limit - results.length)];
444
470
  } catch (e) {
445
471
  }
446
472
  }
447
- return results;
448
473
  }
449
- async recallFromApi(query) {
450
- const response = await fetch(
451
- `${this.config.apiUrl}/agents/${this.config.agentId}/memory/recall`,
452
- {
453
- method: "POST",
454
- headers: { "Content-Type": "application/json" },
455
- body: JSON.stringify({ query, similarity: 0.5 })
456
- }
457
- );
458
- if (response.ok) return await response.json();
459
- return [];
460
- }
461
- async list(limit = 50, offset = 0) {
462
- const db = await this.dbPromise;
463
- try {
464
- const all = await db.getAllFromIndex(this.STORE_NAME, "timestamp");
465
- return all.reverse().slice(offset, offset + limit);
466
- } catch {
467
- return [];
474
+ const apiUrl = config.apiUrl || "https://forbocai-api.onrender.com";
475
+ try {
476
+ const response = await fetch(`${apiUrl}/souls/${cid}`, {
477
+ method: "GET",
478
+ headers: { "Content-Type": "application/json" }
479
+ });
480
+ if (!response.ok) {
481
+ throw new Error(`Import failed: ${response.statusText}`);
468
482
  }
483
+ const data = await response.json();
484
+ return {
485
+ id: data.soulId,
486
+ version: "1.0.0",
487
+ name: data.soulName,
488
+ persona: data.dna,
489
+ state: { mood: "neutral", inventory: [], skills: {}, relationships: {} },
490
+ memories: []
491
+ };
492
+ } catch (e) {
493
+ throw new Error(`Failed to import Soul from CID ${cid}: ${e}`);
469
494
  }
470
- async clear() {
471
- const db = await this.dbPromise;
472
- try {
473
- await db.clear(this.STORE_NAME);
474
- } catch {
495
+ };
496
+ var getSoulList = async (limit = 50, apiUrl) => {
497
+ const url = apiUrl || "https://forbocai-api.onrender.com";
498
+ try {
499
+ const response = await fetch(`${url}/souls?limit=${limit}`, {
500
+ method: "GET",
501
+ headers: { "Content-Type": "application/json" }
502
+ });
503
+ if (!response.ok) {
504
+ throw new Error(`Failed to get Soul list: ${response.statusText}`);
475
505
  }
506
+ const data = await response.json();
507
+ return data.souls.map((s) => ({
508
+ cid: s.cid || s.soulId,
509
+ name: s.name || s.soulName,
510
+ agentId: s.agentId,
511
+ exportedAt: s.exportedAt || s.createdAt,
512
+ ipfsUrl: s.ipfsUrl || `ipfs://${s.cid || s.soulId}`
513
+ }));
514
+ } catch (e) {
515
+ return [];
476
516
  }
477
- async export() {
478
- return this.getAllMemories();
517
+ };
518
+ var createAgentFromSoul = async (cid, cortexId, config = {}) => {
519
+ const apiUrl = config.apiUrl || "https://forbocai-api.onrender.com";
520
+ const response = await fetch(`${apiUrl}/agents/import`, {
521
+ method: "POST",
522
+ headers: { "Content-Type": "application/json" },
523
+ body: JSON.stringify({ cidRef: cid })
524
+ });
525
+ if (!response.ok) {
526
+ throw new Error(`Failed to create agent from Soul: ${response.statusText}`);
479
527
  }
480
- async import(memories) {
481
- const db = await this.dbPromise;
528
+ const data = await response.json();
529
+ return {
530
+ agentId: data.agentId,
531
+ persona: data.persona
532
+ };
533
+ };
534
+ var createSoulInstance = (id, name, persona, state, memories = [], initialApiUrl) => {
535
+ const soulData = createSoul(id, name, persona, state, memories);
536
+ const defaultApiUrl = initialApiUrl || "https://forbocai-api.onrender.com";
537
+ const exportSoul = async (config) => {
538
+ return exportSoulToIPFS(soulData.id, soulData, {
539
+ ...config,
540
+ apiUrl: config?.apiUrl || defaultApiUrl
541
+ });
542
+ };
543
+ const toJSON = () => {
544
+ return { ...soulData };
545
+ };
546
+ return {
547
+ export: exportSoul,
548
+ toJSON
549
+ };
550
+ };
551
+
552
+ // src/memory.ts
553
+ var path3 = __toESM(require("path"));
554
+
555
+ // src/vector.ts
556
+ var path2 = __toESM(require("path"));
557
+ var fs2 = __toESM(require("fs"));
558
+ var pipeline;
559
+ var lancedb;
560
+ var initVectorEngine = async () => {
561
+ if (pipeline) return;
562
+ try {
563
+ console.log("> Initializing Vector Engine (Transformers)...");
564
+ const transformers = await import("@xenova/transformers");
565
+ transformers.env.cacheDir = path2.join(process.env.HOME || ".", ".forbocai", "cache");
566
+ pipeline = await transformers.pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
567
+ console.log("> Initializing LanceDB...");
568
+ lancedb = await import("@lancedb/lancedb");
569
+ } catch (e) {
570
+ console.error("Failed to init Vector Engine:", e);
571
+ }
572
+ };
573
+ var generateEmbedding = async (text) => {
574
+ if (!pipeline) await initVectorEngine();
575
+ const output = await pipeline(text, { pooling: "mean", normalize: true });
576
+ return Array.from(output.data);
577
+ };
578
+ var getVectorTable = async (dbPath, tableName = "memories") => {
579
+ if (!lancedb) await initVectorEngine();
580
+ if (!fs2.existsSync(dbPath)) fs2.mkdirSync(dbPath, { recursive: true });
581
+ const db = await lancedb.connect(dbPath);
582
+ const tables = await db.tableNames();
583
+ if (tables.includes(tableName)) {
584
+ return await db.openTable(tableName);
585
+ } else {
586
+ return null;
587
+ }
588
+ };
589
+ var createTable = async (dbPath, tableName, data) => {
590
+ if (!lancedb) await initVectorEngine();
591
+ const db = await lancedb.connect(dbPath);
592
+ return await db.createTable(tableName, data);
593
+ };
594
+
595
+ // src/memory.ts
596
+ var createMemoryItem = (text, type = "observation", importance = 0.5) => ({
597
+ id: `mem_${Date.now()}_${Math.random().toString(36).substring(7)}`,
598
+ text,
599
+ timestamp: Date.now(),
600
+ type,
601
+ importance: Math.min(1, Math.max(0, importance))
602
+ });
603
+ var createLanceDBMemory = (config) => {
604
+ const dbName = config.storageKey || "forbocai_vectors";
605
+ const dbPath = path3.join(process.cwd(), "local_infrastructure", "vectors", dbName + ".lance");
606
+ const tableName = "memories";
607
+ let _table = null;
608
+ const getTable = async () => {
609
+ if (_table) return _table;
610
+ _table = await getVectorTable(dbPath, tableName);
611
+ return _table;
612
+ };
613
+ const store = async (text, type = "observation", importance = 0.5) => {
614
+ const item = createMemoryItem(text, type, importance);
615
+ const vector = await generateEmbedding(text);
616
+ const record = {
617
+ ...item,
618
+ vector
619
+ };
620
+ const existingTable = await getTable();
621
+ if (existingTable) {
622
+ await existingTable.add([record]);
623
+ } else {
624
+ _table = await createTable(dbPath, tableName, [record]);
625
+ }
626
+ return item;
627
+ };
628
+ const recall = async (query, limit = 5) => {
629
+ const table = await getTable();
630
+ if (!table) return [];
631
+ const queryVec = await generateEmbedding(query);
632
+ const results = await table.search(queryVec).limit(limit).execute();
633
+ return results.map((r) => ({
634
+ id: r.id,
635
+ text: r.text,
636
+ timestamp: r.timestamp,
637
+ type: r.type,
638
+ importance: r.importance
639
+ }));
640
+ };
641
+ const list = async (limit = 50, offset = 0) => {
642
+ const table = await getTable();
643
+ if (!table) return [];
644
+ const results = await table.query().limit(limit + offset).execute();
645
+ return results.slice(offset).map((r) => ({
646
+ id: r.id,
647
+ text: r.text,
648
+ timestamp: r.timestamp,
649
+ type: r.type,
650
+ importance: r.importance
651
+ }));
652
+ };
653
+ const clear = async () => {
654
+ const tablePath = path3.join(dbPath, tableName + ".lance");
482
655
  try {
483
- const tx = db.transaction(this.STORE_NAME, "readwrite");
484
- const store = tx.objectStore(this.STORE_NAME);
485
- for (const mem of memories) await store.put(mem);
486
- await tx.done;
487
- } catch {
656
+ const fs3 = await import("fs");
657
+ if (fs3.existsSync(tablePath)) {
658
+ fs3.rmSync(tablePath, { recursive: true, force: true });
659
+ }
660
+ if (fs3.existsSync(dbPath)) {
661
+ fs3.rmSync(dbPath, { recursive: true, force: true });
662
+ }
663
+ _table = null;
664
+ console.log("> Memory cleared successfully");
665
+ } catch (e) {
666
+ console.error("Failed to clear memory:", e);
667
+ throw e;
488
668
  }
489
- }
490
- };
491
- var MockMemory = class {
492
- constructor() {
493
- this.memories = [];
494
- }
495
- async store(text, type, importance) {
496
- const memory = createMemoryItem(text, type, importance);
497
- this.memories.push(memory);
498
- return memory;
499
- }
500
- async recall(query, limit) {
501
- return rankMemoriesByRelevance(this.memories, query, limit);
502
- }
503
- async list(limit, offset) {
504
- return this.memories.slice(offset ?? 0, (offset ?? 0) + (limit ?? 50));
505
- }
506
- async clear() {
507
- this.memories = [];
508
- }
509
- async export() {
510
- return [...this.memories];
511
- }
512
- async import(memories) {
513
- this.memories = [...this.memories, ...memories];
514
- }
669
+ };
670
+ return { store, recall, list, clear };
515
671
  };
672
+ var createMemory = (config = {}) => createLanceDBMemory(config);
516
673
 
517
674
  // src/bridge.ts
518
675
  var movementRule = {
@@ -683,30 +840,40 @@ var DEFAULT_RULES = [
683
840
  resourceRule
684
841
  ];
685
842
  var createBridge = (config = {}) => {
686
- return new BridgeImpl(config);
687
- };
688
- var BridgeImpl = class {
689
- constructor(config) {
690
- this.config = {
691
- strictMode: config.strictMode ?? false,
692
- ...config
693
- };
694
- this.rules = /* @__PURE__ */ new Map();
695
- DEFAULT_RULES.forEach((rule) => this.rules.set(rule.id, rule));
696
- if (config.customRules) {
697
- config.customRules.forEach((rule) => this.rules.set(rule.id, rule));
698
- }
843
+ const effectiveConfig = {
844
+ strictMode: config.strictMode ?? false,
845
+ ...config
846
+ };
847
+ const rules = /* @__PURE__ */ new Map();
848
+ DEFAULT_RULES.forEach((rule) => rules.set(rule.id, rule));
849
+ if (config.customRules) {
850
+ config.customRules.forEach((rule) => rules.set(rule.id, rule));
699
851
  }
700
- /**
701
- * Validate an action against all applicable rules
702
- */
703
- async validate(action, context = {}) {
704
- const applicableRules = Array.from(this.rules.values()).filter(
852
+ const validateRemote = async (action) => {
853
+ const response = await fetch(`${effectiveConfig.apiUrl}/bridge/validate`, {
854
+ method: "POST",
855
+ headers: { "Content-Type": "application/json" },
856
+ body: JSON.stringify({
857
+ actionType: action.type,
858
+ payload: JSON.stringify(action.payload || {})
859
+ })
860
+ });
861
+ if (!response.ok) {
862
+ throw new Error(`API validation failed: ${response.statusText}`);
863
+ }
864
+ const data = await response.json();
865
+ return {
866
+ valid: data.valid,
867
+ reason: data.reason
868
+ };
869
+ };
870
+ const validate = async (action, context = {}) => {
871
+ const applicableRules = Array.from(rules.values()).filter(
705
872
  (rule) => rule.actionTypes.some(
706
873
  (t) => t.toLowerCase() === action.type.toLowerCase()
707
874
  )
708
875
  );
709
- if (this.config.strictMode && applicableRules.length === 0) {
876
+ if (effectiveConfig.strictMode && applicableRules.length === 0) {
710
877
  const safeTypes = ["IDLE", "idle", "WAIT", "wait"];
711
878
  if (!safeTypes.includes(action.type)) {
712
879
  return {
@@ -720,9 +887,9 @@ var BridgeImpl = class {
720
887
  for (const rule of applicableRules) {
721
888
  const result = rule.validate(currentAction, context);
722
889
  if (!result.valid) {
723
- if (this.config.apiUrl) {
890
+ if (effectiveConfig.apiUrl) {
724
891
  try {
725
- const apiResult = await this.validateRemote(action);
892
+ const apiResult = await validateRemote(action);
726
893
  console.debug("API validation result:", apiResult);
727
894
  } catch (e) {
728
895
  console.warn("Failed to validate via API:", e);
@@ -738,59 +905,22 @@ var BridgeImpl = class {
738
905
  valid: true,
739
906
  correctedAction: currentAction !== action ? currentAction : void 0
740
907
  };
741
- }
742
- /**
743
- * Validate action via remote API
744
- */
745
- async validateRemote(action) {
746
- const response = await fetch(`${this.config.apiUrl}/bridge/validate`, {
747
- method: "POST",
748
- headers: { "Content-Type": "application/json" },
749
- body: JSON.stringify({
750
- actionType: action.type,
751
- payload: JSON.stringify(action.payload || {})
752
- })
753
- });
754
- if (!response.ok) {
755
- throw new Error(`API validation failed: ${response.statusText}`);
756
- }
757
- const data = await response.json();
758
- return {
759
- valid: data.valid,
760
- reason: data.reason
761
- };
762
- }
763
- /**
764
- * Register a custom validation rule
765
- */
766
- registerRule(rule) {
767
- this.rules.set(rule.id, rule);
768
- }
769
- /**
770
- * List all registered rules
771
- */
772
- listRules() {
773
- return Array.from(this.rules.values());
774
- }
775
- /**
776
- * Remove a rule by ID
777
- */
778
- removeRule(ruleId) {
779
- return this.rules.delete(ruleId);
780
- }
781
- };
782
- var MockBridge = class {
783
- async validate(action) {
784
- return { valid: true };
785
- }
786
- registerRule(_rule) {
787
- }
788
- listRules() {
789
- return [];
790
- }
791
- removeRule(_ruleId) {
792
- return false;
793
- }
908
+ };
909
+ const registerRule = (rule) => {
910
+ rules.set(rule.id, rule);
911
+ };
912
+ const listRules = () => {
913
+ return Array.from(rules.values());
914
+ };
915
+ const removeRule = (ruleId) => {
916
+ return rules.delete(ruleId);
917
+ };
918
+ return {
919
+ validate,
920
+ registerRule,
921
+ listRules,
922
+ removeRule
923
+ };
794
924
  };
795
925
  var validateAction = (action, rules, context = {}) => {
796
926
  for (const rule of rules) {
@@ -804,172 +934,6 @@ var validateAction = (action, rules, context = {}) => {
804
934
  return { valid: true };
805
935
  };
806
936
 
807
- // src/soul.ts
808
- var import_helia = require("helia");
809
- var import_json = require("@helia/json");
810
- var import_blockstore_core = require("blockstore-core");
811
- var heliaNode = null;
812
- var heliaJson = null;
813
- var getHelia = async () => {
814
- if (heliaNode) return { node: heliaNode, j: heliaJson };
815
- try {
816
- const blockstore = new import_blockstore_core.MemoryBlockstore();
817
- heliaNode = await (0, import_helia.createHelia)({ blockstore });
818
- heliaJson = (0, import_json.json)(heliaNode);
819
- console.log("> Helia IPFS Node Initialized:", heliaNode.libp2p.peerId.toString());
820
- return { node: heliaNode, j: heliaJson };
821
- } catch (e) {
822
- console.warn("Failed to init Helia (IPFS):", e);
823
- return null;
824
- }
825
- };
826
- var createSoul = (id, name, persona, state, memories = []) => {
827
- return {
828
- id,
829
- version: "1.0.0",
830
- name,
831
- persona,
832
- state: { ...state },
833
- memories: [...memories]
834
- };
835
- };
836
- var serializeSoul = (soul) => {
837
- return JSON.stringify(soul, null, 2);
838
- };
839
- var deserializeSoul = (json2) => {
840
- const parsed = JSON.parse(json2);
841
- if (!parsed.id || !parsed.persona || !parsed.state) {
842
- throw new Error("Invalid Soul format: missing required fields");
843
- }
844
- return {
845
- id: parsed.id,
846
- version: parsed.version || "1.0.0",
847
- name: parsed.name || "Unknown",
848
- persona: parsed.persona,
849
- state: parsed.state,
850
- memories: parsed.memories || [],
851
- signature: parsed.signature
852
- };
853
- };
854
- var validateSoul = (soul) => {
855
- const errors = [];
856
- if (!soul.id) errors.push("Missing id");
857
- if (!soul.persona) errors.push("Missing persona");
858
- if (!soul.state) errors.push("Missing state");
859
- if (!soul.state?.mood) errors.push("Missing state.mood");
860
- return {
861
- valid: errors.length === 0,
862
- errors
863
- };
864
- };
865
- var exportSoulToIPFS = async (agentId, soul, config = {}) => {
866
- if (config.useLocalNode !== false) {
867
- const helia = await getHelia();
868
- if (helia) {
869
- try {
870
- const cid = await helia.j.add(soul);
871
- return {
872
- cid: cid.toString(),
873
- ipfsUrl: `ipfs://${cid.toString()}`,
874
- soul
875
- };
876
- } catch (e) {
877
- console.warn("Helia add failed, falling back to API", e);
878
- }
879
- }
880
- }
881
- const apiUrl = config.apiUrl || "https://forbocai-api.onrender.com";
882
- try {
883
- const response = await fetch(`${apiUrl}/agents/${agentId}/soul/export`, {
884
- method: "POST",
885
- headers: { "Content-Type": "application/json" },
886
- body: JSON.stringify({ agentIdRef: agentId })
887
- });
888
- if (!response.ok) {
889
- throw new Error(`Export failed: ${response.statusText}`);
890
- }
891
- const data = await response.json();
892
- return {
893
- cid: data.cid,
894
- ipfsUrl: data.ipfsUrl,
895
- signature: data.signature,
896
- soul
897
- };
898
- } catch (e) {
899
- const mockCid = `Qm${Buffer.from(soul.id).toString("base64").substring(0, 44)}`;
900
- return {
901
- cid: mockCid,
902
- ipfsUrl: `ipfs://${mockCid}`,
903
- soul
904
- };
905
- }
906
- };
907
- var importSoulFromIPFS = async (cid, config = {}) => {
908
- if (config.useLocalNode !== false) {
909
- const helia = await getHelia();
910
- if (helia) {
911
- try {
912
- } catch (e) {
913
- }
914
- }
915
- }
916
- const apiUrl = config.apiUrl || "https://forbocai-api.onrender.com";
917
- try {
918
- const response = await fetch(`${apiUrl}/souls/${cid}`, {
919
- method: "GET",
920
- headers: { "Content-Type": "application/json" }
921
- });
922
- if (!response.ok) {
923
- throw new Error(`Import failed: ${response.statusText}`);
924
- }
925
- const data = await response.json();
926
- return {
927
- id: data.soulId,
928
- version: "1.0.0",
929
- name: data.soulName,
930
- persona: data.dna,
931
- state: { mood: "neutral", inventory: [], skills: {}, relationships: {} },
932
- memories: []
933
- };
934
- } catch (e) {
935
- throw new Error(`Failed to import Soul from CID ${cid}: ${e}`);
936
- }
937
- };
938
- var createAgentFromSoul = async (cid, cortexId, config = {}) => {
939
- const apiUrl = config.apiUrl || "https://forbocai-api.onrender.com";
940
- const response = await fetch(`${apiUrl}/agents/import`, {
941
- method: "POST",
942
- headers: { "Content-Type": "application/json" },
943
- body: JSON.stringify({ cidRef: cid })
944
- });
945
- if (!response.ok) {
946
- throw new Error(`Failed to create agent from Soul: ${response.statusText}`);
947
- }
948
- const data = await response.json();
949
- return {
950
- agentId: data.agentId,
951
- persona: data.persona
952
- };
953
- };
954
- var SoulImpl = class {
955
- constructor(id, name, persona, state, memories = [], apiUrl) {
956
- this.soul = createSoul(id, name, persona, state, memories);
957
- this.apiUrl = apiUrl || "https://forbocai-api.onrender.com";
958
- }
959
- async export(config) {
960
- return exportSoulToIPFS(this.soul.id, this.soul, {
961
- ...config,
962
- apiUrl: config?.apiUrl || this.apiUrl
963
- });
964
- }
965
- toJSON() {
966
- return { ...this.soul };
967
- }
968
- };
969
- var createSoulInstance = (id, name, persona, state, memories, apiUrl) => {
970
- return new SoulImpl(id, name, persona, state, memories, apiUrl);
971
- };
972
-
973
937
  // src/ghost.ts
974
938
  var startGhostSession = async (config) => {
975
939
  const apiUrl = config.apiUrl || "https://forbocai-api.onrender.com";
@@ -1095,80 +1059,119 @@ var waitForGhostCompletion = async (sessionId, pollIntervalMs = 5e3, timeoutMs =
1095
1059
  }
1096
1060
  throw new Error(`Ghost session timed out after ${timeoutMs}ms`);
1097
1061
  };
1098
- var GhostSession = class {
1099
- constructor(config) {
1100
- this.sessionId = null;
1101
- this.config = config;
1102
- this.apiUrl = config.apiUrl || "https://forbocai-api.onrender.com";
1062
+ var stopGhostSession = async (sessionId, apiUrl) => {
1063
+ const url = apiUrl || "https://forbocai-api.onrender.com";
1064
+ try {
1065
+ const response = await fetch(`${url}/ghost/${sessionId}/stop`, {
1066
+ method: "POST",
1067
+ headers: { "Content-Type": "application/json" }
1068
+ });
1069
+ if (!response.ok) {
1070
+ throw new Error(`Failed to stop Ghost session: ${response.statusText}`);
1071
+ }
1072
+ const data = await response.json();
1073
+ return {
1074
+ stopped: true,
1075
+ status: data.status || "stopped"
1076
+ };
1077
+ } catch (e) {
1078
+ return {
1079
+ stopped: true,
1080
+ status: "stopped"
1081
+ };
1103
1082
  }
1104
- async run() {
1105
- const result = await startGhostSession(this.config);
1106
- this.sessionId = result.sessionId;
1107
- return this.sessionId;
1083
+ };
1084
+ var getGhostHistory = async (limit = 10, apiUrl) => {
1085
+ const url = apiUrl || "https://forbocai-api.onrender.com";
1086
+ try {
1087
+ const response = await fetch(`${url}/ghost/history?limit=${limit}`, {
1088
+ method: "GET",
1089
+ headers: { "Content-Type": "application/json" }
1090
+ });
1091
+ if (!response.ok) {
1092
+ throw new Error(`Failed to get Ghost history: ${response.statusText}`);
1093
+ }
1094
+ const data = await response.json();
1095
+ return data.sessions.map((s) => ({
1096
+ sessionId: s.sessionId,
1097
+ testSuite: s.testSuite,
1098
+ startedAt: s.startedAt,
1099
+ completedAt: s.completedAt,
1100
+ status: s.status,
1101
+ passRate: s.passRate
1102
+ }));
1103
+ } catch (e) {
1104
+ return [];
1108
1105
  }
1109
- async status() {
1110
- if (!this.sessionId) {
1106
+ };
1107
+ var createGhost = (config) => {
1108
+ let sessionId = null;
1109
+ const apiUrl = config.apiUrl || "https://forbocai-api.onrender.com";
1110
+ const run = async () => {
1111
+ const result = await startGhostSession(config);
1112
+ sessionId = result.sessionId;
1113
+ return sessionId;
1114
+ };
1115
+ const status = async () => {
1116
+ if (!sessionId) {
1111
1117
  throw new Error("Ghost session not started");
1112
1118
  }
1113
- return getGhostStatus(this.sessionId, this.apiUrl);
1114
- }
1115
- async results() {
1116
- if (!this.sessionId) {
1119
+ return getGhostStatus(sessionId, apiUrl);
1120
+ };
1121
+ const results = async () => {
1122
+ if (!sessionId) {
1117
1123
  throw new Error("Ghost session not started");
1118
1124
  }
1119
- return getGhostResults(this.sessionId, this.apiUrl);
1120
- }
1121
- async stop() {
1122
- this.sessionId = null;
1123
- }
1124
- async waitForCompletion(pollIntervalMs, timeoutMs, onProgress) {
1125
- if (!this.sessionId) {
1125
+ return getGhostResults(sessionId, apiUrl);
1126
+ };
1127
+ const stop = async () => {
1128
+ sessionId = null;
1129
+ };
1130
+ const waitForCompletion = async (pollIntervalMs, timeoutMs, onProgress) => {
1131
+ if (!sessionId) {
1126
1132
  throw new Error("Ghost session not started");
1127
1133
  }
1128
1134
  return waitForGhostCompletion(
1129
- this.sessionId,
1135
+ sessionId,
1130
1136
  pollIntervalMs,
1131
1137
  timeoutMs,
1132
- this.apiUrl,
1138
+ apiUrl,
1133
1139
  onProgress
1134
1140
  );
1135
- }
1136
- };
1137
- var createGhost = (config) => {
1138
- return new GhostSession(config);
1141
+ };
1142
+ return {
1143
+ run,
1144
+ status,
1145
+ results,
1146
+ stop
1147
+ // Helper method attached to the instance object, though not part of IGhost strictly in the original interface,
1148
+ // it was on the class. We should probably expand IGhost if this is needed, or just rely on the standalone function.
1149
+ // For now, I'll return it as an extra property or strictly adhere to IGhost.
1150
+ // The original Class had it. I'll omit it from the return to match IGhost exactly,
1151
+ // or check IGhost definition. IGhost definition (lines 62-67) does NOT have waitForCompletion.
1152
+ // So I will omit it to match the Interface.
1153
+ };
1139
1154
  };
1140
1155
 
1141
1156
  // src/index.ts
1142
1157
  var init = () => {
1143
- const reset = "\x1B[0m";
1144
- const cyan = "\x1B[36m";
1145
- const blue = "\x1B[34m";
1146
- const dim = "\x1B[2m";
1147
- const bold = "\x1B[1m";
1148
- const runes = "\u16A0 \u16EB \u16DF \u16EB \u16B1 \u16EB \u16D2 \u16EB \u16DF \u16EB \u16B2";
1149
- const border = `${dim}----------------------------------------${reset}`;
1150
- console.error(`
1151
- ${border}
1152
- ${cyan}${bold}FORBOC AI SDK${reset} ${dim}v0.0.1${reset}
1153
- ${blue}${runes}${reset}
1154
- ${border}
1155
- ${dim}> Initializing Cortex...${reset}
1156
- ${dim}> Connecting into the Neuro-Symbolic Grid...${reset}
1157
- ${dim}> Status: ${cyan}ONLINE${reset}
1158
-
1159
- ${cyan}Welcome to the Future of NPC Intelligence.${reset}
1160
- `);
1158
+ console.log(`
1159
+ \x1B[36m _ _ _ ___ _ _
1160
+ | \\| |___ _ _ _ __ ___ / \\ |_ _|_ _ | |_ (_|
1161
+ | . / -_) || | '_ / _ \\/ _ \\ | || ' \\| _| | |
1162
+ |_|\\_\\___|\\_,_| ._\\___/_/ \\_\\ |___|_||_|\\__|_|_|
1163
+ |_| \x1B[0m
1164
+ Neuro-Symbolic Grid SDK v0.3.3
1165
+ ---------------------------------
1166
+ Vessel: ACTIVE
1167
+ Memory: LOCAL (LanceDB)
1168
+ Smart: LOCAL (GGUF)
1169
+ Grid: CONNECTED
1170
+ `);
1161
1171
  };
1162
1172
  // Annotate the CommonJS export names for ESM import in node:
1163
1173
  0 && (module.exports = {
1164
- GhostSession,
1165
- MockBridge,
1166
- MockCortex,
1167
- MockMemory,
1168
- SoulImpl,
1169
- applyTemporalDecay,
1170
1174
  attackRule,
1171
- computeSimilarity,
1172
1175
  createAgent,
1173
1176
  createAgentFromSoul,
1174
1177
  createBridge,
@@ -1179,25 +1182,28 @@ ${cyan}Welcome to the Future of NPC Intelligence.${reset}
1179
1182
  createMemoryItem,
1180
1183
  createSoul,
1181
1184
  createSoulInstance,
1185
+ createTable,
1182
1186
  deserializeSoul,
1183
1187
  exportSoulToIPFS,
1184
1188
  exportToSoul,
1185
1189
  fromSoul,
1186
- generateActionFromDirective,
1187
- generateCompletion,
1190
+ generateEmbedding,
1191
+ getGhostHistory,
1188
1192
  getGhostResults,
1189
1193
  getGhostStatus,
1194
+ getSoulList,
1195
+ getVectorTable,
1190
1196
  importSoulFromIPFS,
1191
1197
  init,
1198
+ initVectorEngine,
1192
1199
  interactRule,
1193
1200
  movementRule,
1194
1201
  processAgentInput,
1195
- processObservationToDirective,
1196
- rankMemoriesByRelevance,
1197
1202
  resourceRule,
1198
1203
  serializeSoul,
1199
1204
  speakRule,
1200
1205
  startGhostSession,
1206
+ stopGhostSession,
1201
1207
  updateAgentState,
1202
1208
  validateAction,
1203
1209
  validateSoul,