@forbocai/core 0.4.4

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 ADDED
@@ -0,0 +1,960 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
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
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ RemoteCortex: () => RemoteCortex,
34
+ SDK_VERSION: () => SDK_VERSION,
35
+ createAgent: () => createAgent,
36
+ createBridge: () => createBridge,
37
+ createGhost: () => createGhost,
38
+ createInitialState: () => createInitialState,
39
+ createSoul: () => createSoul,
40
+ createSoulInstance: () => createSoulInstance,
41
+ deserializeSoul: () => deserializeSoul,
42
+ exportSoul: () => exportSoul,
43
+ exportToSoul: () => exportToSoul,
44
+ fromSoul: () => fromSoul,
45
+ getGhostHistory: () => getGhostHistory,
46
+ getGhostResults: () => getGhostResults,
47
+ getGhostStatus: () => getGhostStatus,
48
+ getSoulList: () => getSoulList,
49
+ importSoulFromArweave: () => importSoulFromArweave,
50
+ presets: () => presets_exports,
51
+ processAgentInput: () => processAgentInput,
52
+ serializeSoul: () => serializeSoul,
53
+ startGhostSession: () => startGhostSession,
54
+ stopGhostSession: () => stopGhostSession,
55
+ updateAgentState: () => updateAgentState,
56
+ uploadToArweave: () => uploadToArweave,
57
+ validateAction: () => validateAction,
58
+ validateSoul: () => validateSoul,
59
+ waitForGhostCompletion: () => waitForGhostCompletion
60
+ });
61
+ module.exports = __toCommonJS(index_exports);
62
+
63
+ // src/agent.ts
64
+ var createInitialState = (partial) => {
65
+ return { ...partial };
66
+ };
67
+ var updateAgentState = (currentState, updates) => {
68
+ return {
69
+ ...currentState,
70
+ ...updates
71
+ };
72
+ };
73
+ var processAgentInput = (currentState, input, context = {}) => {
74
+ const stateKeys = Object.keys(currentState);
75
+ const stateSummary = stateKeys.length > 0 ? stateKeys.map((k) => `${k}=${JSON.stringify(currentState[k])}`).join(", ") : "empty";
76
+ return {
77
+ dialogue: `Processing: "${input}" (State: ${stateSummary})`,
78
+ action: {
79
+ type: "respond",
80
+ reason: "Default processing"
81
+ }
82
+ };
83
+ };
84
+ var exportToSoul = (agentId, name, persona, state, memories) => {
85
+ return {
86
+ id: agentId,
87
+ version: "1.0.0",
88
+ name,
89
+ persona,
90
+ memories: [...memories],
91
+ // Copy array for immutability
92
+ state: { ...state }
93
+ // Copy state for immutability
94
+ };
95
+ };
96
+ var createAgent = (config) => {
97
+ let state = createInitialState(config.initialState);
98
+ let memories = [];
99
+ const cortex = config.cortex;
100
+ const apiUrl = config.apiUrl || "http://localhost:8080";
101
+ const agentId = config.id || "agent-" + Math.random().toString(36).substring(7);
102
+ const getAgentState = () => {
103
+ return { ...state };
104
+ };
105
+ const setAgentState = (newState) => {
106
+ state = newState;
107
+ };
108
+ const process = async (input, context = {}) => {
109
+ const currentState = getAgentState();
110
+ const apiContext = Object.entries(context).map(([k, v]) => [k, String(v)]);
111
+ const timestamp = Date.now();
112
+ apiContext.push(["timestamp", String(timestamp)]);
113
+ let relevantMemories = [];
114
+ if (config.memory && typeof config.memory.recall === "function") {
115
+ try {
116
+ relevantMemories = await config.memory.recall(input, 5);
117
+ } catch {
118
+ }
119
+ }
120
+ let directive = "Respond normally.";
121
+ let instruction = "IDLE";
122
+ let target;
123
+ try {
124
+ const dirRes = await fetch(`${apiUrl}/agents/${agentId}/directive`, {
125
+ method: "POST",
126
+ headers: {
127
+ "Content-Type": "application/json",
128
+ "X-Request-Timestamp": String(timestamp)
129
+ },
130
+ body: JSON.stringify({
131
+ dirContext: apiContext,
132
+ dirState: currentState,
133
+ dirMemories: relevantMemories.map((m) => ({ text: m.text, type: m.type, importance: m.importance }))
134
+ })
135
+ });
136
+ if (dirRes.ok) {
137
+ const data = await dirRes.json();
138
+ directive = data.dirReason;
139
+ instruction = data.dirInstruction;
140
+ target = data.dirTarget;
141
+ } else {
142
+ throw new Error(`API Error: ${dirRes.status}`);
143
+ }
144
+ } catch (e) {
145
+ throw new Error(`API Directive Failed: ${e instanceof Error ? e.message : String(e)}`);
146
+ }
147
+ const memoryContext = relevantMemories.length > 0 ? `
148
+ Memories:
149
+ ${relevantMemories.map((m) => `- [${m.type}] ${m.text}`).join("\n")}
150
+ ` : "";
151
+ const prompt = `System: You are ${config.persona}.
152
+ Directive: ${instruction} (${directive}).
153
+ Target: ${target || "None"}${memoryContext}
154
+ User: ${input}
155
+ Agent:`;
156
+ const generatedText = await cortex.complete(prompt);
157
+ const verRes = await fetch(`${apiUrl}/agents/${agentId}/verdict`, {
158
+ method: "POST",
159
+ headers: { "Content-Type": "application/json" },
160
+ body: JSON.stringify({
161
+ verDirective: {
162
+ dirInstruction: instruction,
163
+ dirTarget: target || "",
164
+ dirReason: directive
165
+ },
166
+ verAction: {
167
+ gaType: instruction,
168
+ // Map to generic action type
169
+ actionReason: directive,
170
+ actionTarget: target || ""
171
+ },
172
+ verThought: generatedText
173
+ })
174
+ });
175
+ if (!verRes.ok) {
176
+ throw new Error(`API Verdict Error: ${verRes.status}`);
177
+ }
178
+ const vData = await verRes.json();
179
+ const isValid = vData.verValid;
180
+ const signature = vData.verSignature;
181
+ if (!isValid) {
182
+ return {
183
+ dialogue: "... [Action Blocked by Protocol]",
184
+ action: { type: "BLOCKED", reason: "API Validation Failed" }
185
+ };
186
+ }
187
+ if (config.memory && typeof config.memory.store === "function") {
188
+ config.memory.store(`Input: "${input}" \u2192 Action: ${instruction}`, "experience", 0.5).catch(() => {
189
+ });
190
+ }
191
+ return {
192
+ dialogue: generatedText,
193
+ action: {
194
+ type: instruction,
195
+ reason: directive,
196
+ target,
197
+ signature
198
+ },
199
+ thought: `Directive: ${directive}`
200
+ };
201
+ };
202
+ const exportSoul2 = async () => {
203
+ let exportedMemories = [...memories];
204
+ if (config.memory && typeof config.memory.export === "function") {
205
+ try {
206
+ exportedMemories = await config.memory.export();
207
+ } catch {
208
+ }
209
+ }
210
+ return exportToSoul(agentId, "Agent", config.persona, state, exportedMemories);
211
+ };
212
+ return {
213
+ process,
214
+ getState: getAgentState,
215
+ setState: setAgentState,
216
+ export: exportSoul2
217
+ };
218
+ };
219
+ var fromSoul = async (soul, cortex, memory) => {
220
+ const agent = createAgent({
221
+ id: soul.id,
222
+ cortex,
223
+ memory: memory || null,
224
+ persona: soul.persona,
225
+ initialState: soul.state
226
+ });
227
+ if (memory && soul.memories && soul.memories.length > 0 && typeof memory.import === "function") {
228
+ try {
229
+ await memory.import(soul.memories);
230
+ } catch (e) {
231
+ console.warn("Failed to import memories into module:", e);
232
+ }
233
+ }
234
+ return agent;
235
+ };
236
+
237
+ // src/bridge.ts
238
+ var createBridge = (config = {}) => {
239
+ const effectiveConfig = {
240
+ strictMode: config.strictMode ?? false,
241
+ ...config
242
+ };
243
+ const rules = /* @__PURE__ */ new Map();
244
+ if (config.customRules) {
245
+ config.customRules.forEach((rule) => rules.set(rule.id, rule));
246
+ }
247
+ const validateRemote = async (action) => {
248
+ const response = await fetch(`${effectiveConfig.apiUrl}/bridge/validate`, {
249
+ method: "POST",
250
+ headers: { "Content-Type": "application/json" },
251
+ body: JSON.stringify({
252
+ actionType: action.type,
253
+ payload: JSON.stringify(action.payload || {})
254
+ })
255
+ });
256
+ if (!response.ok) {
257
+ throw new Error(`API validation failed: ${response.statusText}`);
258
+ }
259
+ const data = await response.json();
260
+ return {
261
+ valid: data.valid,
262
+ reason: data.reason
263
+ };
264
+ };
265
+ const validate = async (action, context = {}) => {
266
+ const applicableRules = Array.from(rules.values()).filter(
267
+ (rule) => rule.actionTypes.some(
268
+ (t) => t.toLowerCase() === action.type.toLowerCase()
269
+ )
270
+ );
271
+ if (effectiveConfig.strictMode && applicableRules.length === 0) {
272
+ const safeTypes = ["IDLE", "idle", "WAIT", "wait"];
273
+ if (!safeTypes.includes(action.type)) {
274
+ return {
275
+ valid: false,
276
+ reason: `Unknown action type '${action.type}' in strict mode`,
277
+ correctedAction: { ...action, type: "IDLE", reason: "Unknown action type" }
278
+ };
279
+ }
280
+ }
281
+ let currentAction = action;
282
+ for (const rule of applicableRules) {
283
+ const result = rule.validate(currentAction, context);
284
+ if (!result.valid) {
285
+ if (effectiveConfig.apiUrl) {
286
+ const apiResult = await validateRemote(action);
287
+ console.debug("API validation result:", apiResult);
288
+ }
289
+ return result;
290
+ }
291
+ if (result.correctedAction) {
292
+ currentAction = result.correctedAction;
293
+ }
294
+ }
295
+ return {
296
+ valid: true,
297
+ correctedAction: currentAction !== action ? currentAction : void 0
298
+ };
299
+ };
300
+ const registerRule = (rule) => {
301
+ rules.set(rule.id, rule);
302
+ if (effectiveConfig.apiUrl) {
303
+ }
304
+ };
305
+ const listRules = () => {
306
+ return Array.from(rules.values());
307
+ };
308
+ const removeRule = (ruleId) => {
309
+ return rules.delete(ruleId);
310
+ };
311
+ return {
312
+ validate,
313
+ registerRule,
314
+ listRules,
315
+ removeRule
316
+ };
317
+ };
318
+ var validateAction = (action, rules, context = {}) => {
319
+ for (const rule of rules) {
320
+ if (rule.actionTypes.some((t) => t.toLowerCase() === action.type.toLowerCase())) {
321
+ const result = rule.validate(action, context);
322
+ if (!result.valid) {
323
+ return result;
324
+ }
325
+ }
326
+ }
327
+ return { valid: true };
328
+ };
329
+
330
+ // src/soul.ts
331
+ var import_sdk = __toESM(require("@irys/sdk"));
332
+ var createSoul = (id, name, persona, state, memories = []) => {
333
+ return {
334
+ id,
335
+ version: "1.0.0",
336
+ name,
337
+ persona,
338
+ state: { ...state },
339
+ memories: [...memories]
340
+ };
341
+ };
342
+ var serializeSoul = (soul) => {
343
+ return JSON.stringify(soul, null, 2);
344
+ };
345
+ var deserializeSoul = (json) => {
346
+ const parsed = JSON.parse(json);
347
+ if (!parsed.id || !parsed.persona || !parsed.state) {
348
+ throw new Error("Invalid Soul format: missing required fields");
349
+ }
350
+ return {
351
+ id: parsed.id,
352
+ version: parsed.version || "1.0.0",
353
+ name: parsed.name || "Unknown",
354
+ persona: parsed.persona,
355
+ state: parsed.state,
356
+ memories: parsed.memories || [],
357
+ signature: parsed.signature
358
+ };
359
+ };
360
+ var uploadToArweave = async (soul, config) => {
361
+ if (!config.privateKey) {
362
+ throw new Error("Private key required for direct Arweave upload");
363
+ }
364
+ const irys = new import_sdk.default({
365
+ url: config.irysUrl || "https://node1.irys.xyz",
366
+ token: config.token || "solana",
367
+ key: config.privateKey
368
+ });
369
+ const dataToUpload = serializeSoul(soul);
370
+ try {
371
+ const receipt = await irys.upload(dataToUpload);
372
+ return {
373
+ txId: receipt.id,
374
+ url: `https://gateway.irys.xyz/${receipt.id}`,
375
+ soul
376
+ };
377
+ } catch (e) {
378
+ throw new Error(`Failed to upload to Arweave: ${e}`);
379
+ }
380
+ };
381
+ var exportSoul = async (agentId, soul, config = {}) => {
382
+ if (config.privateKey) {
383
+ try {
384
+ return await uploadToArweave(soul, config);
385
+ } catch (e) {
386
+ console.warn("Direct Arweave upload failed, falling back to API", e);
387
+ }
388
+ }
389
+ const apiUrl = config.apiUrl || "https://api.forboc.ai";
390
+ try {
391
+ const response = await fetch(`${apiUrl}/agents/${agentId}/soul/export`, {
392
+ method: "POST",
393
+ headers: { "Content-Type": "application/json" },
394
+ body: JSON.stringify({ soul })
395
+ // Sending full soul for server to sign/upload
396
+ });
397
+ if (!response.ok) {
398
+ throw new Error(`Export failed: ${response.statusText}`);
399
+ }
400
+ const data = await response.json();
401
+ return {
402
+ txId: data.txId,
403
+ url: data.url,
404
+ soul
405
+ };
406
+ } catch (e) {
407
+ console.warn("API export failed, returning mock Arweave TXID used for dev");
408
+ const mockTxId = `mock_ar_${Date.now()}`;
409
+ return {
410
+ txId: mockTxId,
411
+ url: `https://arweave.net/${mockTxId}`,
412
+ soul
413
+ };
414
+ }
415
+ };
416
+ var importSoulFromArweave = async (txId, config = {}) => {
417
+ const gateway = config.gatewayUrl || "https://gateway.irys.xyz";
418
+ try {
419
+ const response = await fetch(`${gateway}/${txId}`, {
420
+ method: "GET",
421
+ headers: { "Content-Type": "application/json" }
422
+ });
423
+ if (!response.ok) {
424
+ throw new Error(`Import failed: ${response.statusText}`);
425
+ }
426
+ const data = await response.json();
427
+ if (!data.id || !data.persona) {
428
+ throw new Error("Invalid soul data from Arweave");
429
+ }
430
+ return data;
431
+ } catch (e) {
432
+ throw new Error(`Failed to import Soul from TXID ${txId}: ${e}`);
433
+ }
434
+ };
435
+ var getSoulList = async (limit = 50, apiUrl) => {
436
+ const url = apiUrl || "https://api.forboc.ai";
437
+ try {
438
+ const response = await fetch(`${url}/souls?limit=${limit}`);
439
+ if (!response.ok) throw new Error(response.statusText);
440
+ const data = await response.json();
441
+ return data.souls.map((s) => ({
442
+ txId: s.txId,
443
+ name: s.name,
444
+ agentId: s.agentId,
445
+ exportedAt: s.exportedAt,
446
+ url: s.url || `https://gateway.irys.xyz/${s.txId}`
447
+ }));
448
+ } catch (e) {
449
+ return [];
450
+ }
451
+ };
452
+ var createSoulInstance = (id, name, persona, state, memories = [], initialApiUrl) => {
453
+ const soulData = createSoul(id, name, persona, state, memories);
454
+ const defaultApiUrl = initialApiUrl || "https://api.forboc.ai";
455
+ const performExport = async (config) => {
456
+ return exportSoul(soulData.id, soulData, {
457
+ ...config,
458
+ apiUrl: config?.apiUrl || defaultApiUrl
459
+ });
460
+ };
461
+ return {
462
+ export: performExport,
463
+ toJSON: () => ({ ...soulData })
464
+ };
465
+ };
466
+ var validateSoul = (soul) => {
467
+ const errors = [];
468
+ if (!soul.id) errors.push("Missing id");
469
+ if (!soul.persona) errors.push("Missing persona");
470
+ if (!soul.state) errors.push("Missing state");
471
+ return {
472
+ valid: errors.length === 0,
473
+ errors
474
+ };
475
+ };
476
+
477
+ // src/ghost.ts
478
+ var startGhostSession = async (config) => {
479
+ const apiUrl = config.apiUrl || "https://api.forboc.ai";
480
+ try {
481
+ const response = await fetch(`${apiUrl}/ghost/run`, {
482
+ method: "POST",
483
+ headers: { "Content-Type": "application/json" },
484
+ body: JSON.stringify({
485
+ testSuite: config.testSuite,
486
+ duration: config.duration
487
+ })
488
+ });
489
+ if (!response.ok) {
490
+ throw new Error(`Failed to start Ghost session: ${response.statusText}`);
491
+ }
492
+ const data = await response.json();
493
+ return {
494
+ sessionId: data.sessionId,
495
+ status: data.runStatus
496
+ };
497
+ } catch (e) {
498
+ const mockId = `ghost_${Date.now()}_${Math.random().toString(36).substring(7)}`;
499
+ return {
500
+ sessionId: mockId,
501
+ status: "running"
502
+ };
503
+ }
504
+ };
505
+ var getGhostStatus = async (sessionId, apiUrl) => {
506
+ const url = apiUrl || "https://api.forboc.ai";
507
+ try {
508
+ const response = await fetch(`${url}/ghost/${sessionId}/status`, {
509
+ method: "GET",
510
+ headers: { "Content-Type": "application/json" }
511
+ });
512
+ if (!response.ok) {
513
+ throw new Error(`Failed to get Ghost status: ${response.statusText}`);
514
+ }
515
+ const data = await response.json();
516
+ return {
517
+ sessionId: data.ghostSessionId,
518
+ status: data.ghostStatus,
519
+ progress: data.ghostProgress,
520
+ startedAt: data.ghostStartedAt,
521
+ duration: data.ghostDuration,
522
+ errors: data.ghostErrors
523
+ };
524
+ } catch (e) {
525
+ return {
526
+ sessionId,
527
+ status: "running",
528
+ progress: Math.floor(Math.random() * 100),
529
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
530
+ duration: 60,
531
+ errors: 0
532
+ };
533
+ }
534
+ };
535
+ var getGhostResults = async (sessionId, apiUrl) => {
536
+ const url = apiUrl || "https://api.forboc.ai";
537
+ try {
538
+ const response = await fetch(`${url}/ghost/${sessionId}/results`, {
539
+ method: "GET",
540
+ headers: { "Content-Type": "application/json" }
541
+ });
542
+ if (!response.ok) {
543
+ throw new Error(`Failed to get Ghost results: ${response.statusText}`);
544
+ }
545
+ const data = await response.json();
546
+ return {
547
+ sessionId: data.resultsSessionId,
548
+ totalTests: data.resultsTotalTests,
549
+ passed: data.resultsPassed,
550
+ failed: data.resultsFailed,
551
+ skipped: data.resultsSkipped,
552
+ duration: data.resultsDuration,
553
+ tests: data.resultsTests.map((t) => ({
554
+ name: t.testName,
555
+ passed: t.testPassed,
556
+ duration: t.testDuration,
557
+ error: t.testError,
558
+ screenshot: t.testScreenshot
559
+ })),
560
+ coverage: data.resultsCoverage,
561
+ metrics: Object.fromEntries(data.resultsMetrics)
562
+ };
563
+ } catch (e) {
564
+ return {
565
+ sessionId,
566
+ totalTests: 5,
567
+ passed: 4,
568
+ failed: 1,
569
+ skipped: 0,
570
+ duration: 1245,
571
+ tests: [
572
+ { name: "test.navigation", passed: true, duration: 150 },
573
+ { name: "test.combat", passed: true, duration: 230 },
574
+ { name: "test.dialogue", passed: false, duration: 450, error: "Timeout" }
575
+ ],
576
+ coverage: 0.75,
577
+ metrics: {
578
+ avgFrameRate: 58.5,
579
+ memoryUsageMB: 512.3,
580
+ aiDecisionsPerSec: 15.2
581
+ }
582
+ };
583
+ }
584
+ };
585
+ var waitForGhostCompletion = async (sessionId, pollIntervalMs = 5e3, timeoutMs = 3e5, apiUrl, onProgress) => {
586
+ const startTime = Date.now();
587
+ while (Date.now() - startTime < timeoutMs) {
588
+ try {
589
+ const status = await getGhostStatus(sessionId, apiUrl);
590
+ if (onProgress) {
591
+ onProgress(status);
592
+ }
593
+ if (status.status === "completed") {
594
+ return getGhostResults(sessionId, apiUrl);
595
+ }
596
+ if (status.status === "failed") {
597
+ throw new Error(`Ghost session failed with ${status.errors} errors`);
598
+ }
599
+ } catch (e) {
600
+ }
601
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
602
+ }
603
+ throw new Error(`Ghost session timed out after ${timeoutMs}ms`);
604
+ };
605
+ var stopGhostSession = async (sessionId, apiUrl) => {
606
+ const url = apiUrl || "https://api.forboc.ai";
607
+ try {
608
+ const response = await fetch(`${url}/ghost/${sessionId}/stop`, {
609
+ method: "POST",
610
+ headers: { "Content-Type": "application/json" }
611
+ });
612
+ if (!response.ok) {
613
+ throw new Error(`Failed to stop Ghost session: ${response.statusText}`);
614
+ }
615
+ const data = await response.json();
616
+ return {
617
+ stopped: true,
618
+ status: data.status || "stopped"
619
+ };
620
+ } catch (e) {
621
+ return {
622
+ stopped: true,
623
+ status: "stopped"
624
+ };
625
+ }
626
+ };
627
+ var getGhostHistory = async (limit = 10, apiUrl) => {
628
+ const url = apiUrl || "https://api.forboc.ai";
629
+ try {
630
+ const response = await fetch(`${url}/ghost/history?limit=${limit}`, {
631
+ method: "GET",
632
+ headers: { "Content-Type": "application/json" }
633
+ });
634
+ if (!response.ok) {
635
+ throw new Error(`Failed to get Ghost history: ${response.statusText}`);
636
+ }
637
+ const data = await response.json();
638
+ return data.sessions.map((s) => ({
639
+ sessionId: s.sessionId,
640
+ testSuite: s.testSuite,
641
+ startedAt: s.startedAt,
642
+ completedAt: s.completedAt,
643
+ status: s.status,
644
+ passRate: s.passRate
645
+ }));
646
+ } catch (e) {
647
+ return [];
648
+ }
649
+ };
650
+ var createGhost = (config) => {
651
+ let sessionId = null;
652
+ const apiUrl = config.apiUrl || "https://api.forboc.ai";
653
+ const run = async () => {
654
+ const result = await startGhostSession(config);
655
+ sessionId = result.sessionId;
656
+ return sessionId;
657
+ };
658
+ const status = async () => {
659
+ if (!sessionId) {
660
+ throw new Error("Ghost session not started");
661
+ }
662
+ return getGhostStatus(sessionId, apiUrl);
663
+ };
664
+ const results = async () => {
665
+ if (!sessionId) {
666
+ throw new Error("Ghost session not started");
667
+ }
668
+ return getGhostResults(sessionId, apiUrl);
669
+ };
670
+ const stop = async () => {
671
+ sessionId = null;
672
+ };
673
+ const waitForCompletion = async (pollIntervalMs, timeoutMs, onProgress) => {
674
+ if (!sessionId) {
675
+ throw new Error("Ghost session not started");
676
+ }
677
+ return waitForGhostCompletion(
678
+ sessionId,
679
+ pollIntervalMs,
680
+ timeoutMs,
681
+ apiUrl,
682
+ onProgress
683
+ );
684
+ };
685
+ return {
686
+ run,
687
+ status,
688
+ results,
689
+ stop,
690
+ waitForCompletion
691
+ };
692
+ };
693
+
694
+ // src/cortex-remote.ts
695
+ var RemoteCortex = class {
696
+ constructor(apiUrl) {
697
+ this.apiUrl = apiUrl;
698
+ }
699
+ async init() {
700
+ return {
701
+ id: `remote_${Date.now()}`,
702
+ model: "api-integrated",
703
+ ready: true,
704
+ engine: "remote"
705
+ };
706
+ }
707
+ async complete(prompt, options) {
708
+ const response = await fetch(`${this.apiUrl}/cortex/complete`, {
709
+ method: "POST",
710
+ headers: { "Content-Type": "application/json" },
711
+ body: JSON.stringify({ prompt, ...options })
712
+ });
713
+ if (!response.ok) throw new Error(`Remote Cortex failed: ${response.statusText}`);
714
+ const data = await response.json();
715
+ return data.text;
716
+ }
717
+ async *completeStream(prompt, options) {
718
+ const result = await this.complete(prompt, options);
719
+ yield result;
720
+ }
721
+ };
722
+
723
+ // src/presets/index.ts
724
+ var presets_exports = {};
725
+ __export(presets_exports, {
726
+ RPG_MEMORY_TYPES: () => RPG_MEMORY_TYPES,
727
+ RPG_MOODS: () => RPG_MOODS,
728
+ attackRule: () => attackRule,
729
+ createRPGState: () => createRPGState,
730
+ interactRule: () => interactRule,
731
+ movementRule: () => movementRule,
732
+ puzzleRules: () => puzzleRules,
733
+ resourceRule: () => resourceRule,
734
+ rpgRules: () => rpgRules,
735
+ socialRules: () => socialRules,
736
+ spatialRules: () => spatialRules,
737
+ speakRule: () => speakRule
738
+ });
739
+
740
+ // src/presets/rpg.ts
741
+ var RPG_MOODS = {
742
+ hostile: "hostile",
743
+ suspicious: "suspicious",
744
+ neutral: "neutral",
745
+ friendly: "friendly",
746
+ loyal: "loyal"
747
+ };
748
+ var RPG_MEMORY_TYPES = {
749
+ observation: "observation",
750
+ experience: "experience",
751
+ knowledge: "knowledge",
752
+ emotion: "emotion"
753
+ };
754
+ var createRPGState = (partial) => {
755
+ return {
756
+ inventory: partial?.inventory ?? [],
757
+ hp: partial?.hp ?? 100,
758
+ mana: partial?.mana ?? 100,
759
+ skills: partial?.skills ?? {},
760
+ relationships: partial?.relationships ?? {},
761
+ mood: partial?.mood ?? "neutral",
762
+ ...partial
763
+ };
764
+ };
765
+ var movementRule = {
766
+ id: "core.movement",
767
+ name: "Movement Validation",
768
+ description: "Ensures MOVE actions have valid x,y coordinates",
769
+ actionTypes: ["MOVE", "move"],
770
+ validate: (action, context) => {
771
+ const payload = action.payload || {};
772
+ const target = payload.target;
773
+ if (!target || typeof target.x !== "number" || typeof target.y !== "number") {
774
+ return {
775
+ valid: false,
776
+ reason: "MOVE action must have target with numeric x,y coordinates",
777
+ correctedAction: {
778
+ ...action,
779
+ type: "IDLE",
780
+ reason: "Invalid MOVE target - defaulting to IDLE"
781
+ }
782
+ };
783
+ }
784
+ const world = context.worldState || {};
785
+ const maxX = world.maxX || Infinity;
786
+ const maxY = world.maxY || Infinity;
787
+ if (target.x < 0 || target.x > maxX || target.y < 0 || target.y > maxY) {
788
+ return {
789
+ valid: false,
790
+ reason: `MOVE target (${target.x}, ${target.y}) is out of bounds`,
791
+ correctedAction: {
792
+ ...action,
793
+ payload: {
794
+ ...payload,
795
+ target: {
796
+ x: Math.max(0, Math.min(maxX, target.x)),
797
+ y: Math.max(0, Math.min(maxY, target.y))
798
+ }
799
+ }
800
+ }
801
+ };
802
+ }
803
+ return { valid: true };
804
+ }
805
+ };
806
+ var attackRule = {
807
+ id: "core.attack",
808
+ name: "Attack Validation",
809
+ description: "Ensures ATTACK actions have valid targetId",
810
+ actionTypes: ["ATTACK", "attack"],
811
+ validate: (action, context) => {
812
+ if (!action.target && !action.payload?.targetId) {
813
+ return {
814
+ valid: false,
815
+ reason: "ATTACK action must have a target or targetId",
816
+ correctedAction: {
817
+ ...action,
818
+ type: "IDLE",
819
+ reason: "Invalid ATTACK - no target specified"
820
+ }
821
+ };
822
+ }
823
+ const world = context.worldState || {};
824
+ const entities = world.entities || [];
825
+ const targetId = action.target || action.payload?.targetId;
826
+ if (entities.length > 0 && !entities.includes(targetId)) {
827
+ return {
828
+ valid: false,
829
+ reason: `ATTACK target '${targetId}' does not exist in world`,
830
+ correctedAction: {
831
+ ...action,
832
+ type: "IDLE",
833
+ reason: "Target not found"
834
+ }
835
+ };
836
+ }
837
+ return { valid: true };
838
+ }
839
+ };
840
+ var interactRule = {
841
+ id: "core.interact",
842
+ name: "Interact Validation",
843
+ description: "Ensures INTERACT actions have valid objectId",
844
+ actionTypes: ["INTERACT", "interact"],
845
+ validate: (action, context) => {
846
+ if (!action.target && !action.payload?.objectId) {
847
+ return {
848
+ valid: false,
849
+ reason: "INTERACT action must have objectId",
850
+ correctedAction: {
851
+ ...action,
852
+ type: "IDLE",
853
+ reason: "Invalid INTERACT - no object specified"
854
+ }
855
+ };
856
+ }
857
+ return { valid: true };
858
+ }
859
+ };
860
+ var speakRule = {
861
+ id: "core.speak",
862
+ name: "Speak Validation",
863
+ description: "Ensures SPEAK actions have non-empty text",
864
+ actionTypes: ["SPEAK", "speak"],
865
+ validate: (action, context) => {
866
+ const text = action.payload?.text;
867
+ if (!text || text.trim().length === 0) {
868
+ return {
869
+ valid: false,
870
+ reason: "SPEAK action must have non-empty text",
871
+ correctedAction: {
872
+ ...action,
873
+ type: "IDLE",
874
+ reason: "Empty speech - defaulting to IDLE"
875
+ }
876
+ };
877
+ }
878
+ const maxLength = context.constraints?.maxSpeechLength || 1e3;
879
+ if (text.length > maxLength) {
880
+ return {
881
+ valid: true,
882
+ reason: `Speech truncated to ${maxLength} characters`,
883
+ correctedAction: {
884
+ ...action,
885
+ payload: {
886
+ ...action.payload,
887
+ text: text.substring(0, maxLength)
888
+ }
889
+ }
890
+ };
891
+ }
892
+ return { valid: true };
893
+ }
894
+ };
895
+ var resourceRule = {
896
+ id: "core.resources",
897
+ name: "Resource Validation",
898
+ description: "Ensures agent has required resources for action",
899
+ actionTypes: ["ATTACK", "CAST", "USE_ITEM"],
900
+ validate: (action, context) => {
901
+ const agent = context.agentState || {};
902
+ const hp = agent.hp ?? 100;
903
+ const mana = agent.mana ?? 100;
904
+ if (hp <= 0) {
905
+ return {
906
+ valid: false,
907
+ reason: "Agent is dead and cannot perform actions",
908
+ correctedAction: { ...action, type: "IDLE", reason: "Agent dead" }
909
+ };
910
+ }
911
+ if (action.type === "CAST" || action.type === "cast") {
912
+ const manaCost = action.payload?.manaCost || 10;
913
+ if (mana < manaCost) {
914
+ return {
915
+ valid: false,
916
+ reason: `Insufficient mana: need ${manaCost}, have ${mana}`,
917
+ correctedAction: { ...action, type: "IDLE", reason: "Not enough mana" }
918
+ };
919
+ }
920
+ }
921
+ return { valid: true };
922
+ }
923
+ };
924
+ var rpgRules = [movementRule, attackRule, interactRule, speakRule, resourceRule];
925
+ var spatialRules = [movementRule];
926
+ var socialRules = [speakRule, interactRule];
927
+ var puzzleRules = [movementRule, interactRule];
928
+
929
+ // src/index.ts
930
+ var SDK_VERSION = "0.4.4";
931
+ // Annotate the CommonJS export names for ESM import in node:
932
+ 0 && (module.exports = {
933
+ RemoteCortex,
934
+ SDK_VERSION,
935
+ createAgent,
936
+ createBridge,
937
+ createGhost,
938
+ createInitialState,
939
+ createSoul,
940
+ createSoulInstance,
941
+ deserializeSoul,
942
+ exportSoul,
943
+ exportToSoul,
944
+ fromSoul,
945
+ getGhostHistory,
946
+ getGhostResults,
947
+ getGhostStatus,
948
+ getSoulList,
949
+ importSoulFromArweave,
950
+ presets,
951
+ processAgentInput,
952
+ serializeSoul,
953
+ startGhostSession,
954
+ stopGhostSession,
955
+ updateAgentState,
956
+ uploadToArweave,
957
+ validateAction,
958
+ validateSoul,
959
+ waitForGhostCompletion
960
+ });