@forbocai/core 0.5.8 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3,9 +3,6 @@ var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __esm = (fn, res) => function __init() {
7
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
- };
9
6
  var __export = (target, all) => {
10
7
  for (var name in all)
11
8
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -20,310 +17,598 @@ var __copyProps = (to, from, except, desc) => {
20
17
  };
21
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
19
 
23
- // src/soul.ts
24
- var soul_exports = {};
25
- __export(soul_exports, {
26
- createSoul: () => createSoul,
27
- createSoulInstance: () => createSoulInstance,
28
- deserializeSoul: () => deserializeSoul,
29
- exportSoul: () => exportSoul,
30
- getSoulList: () => getSoulList,
31
- importSoulFromArweave: () => importSoulFromArweave,
32
- serializeSoul: () => serializeSoul,
33
- validateSoul: () => validateSoul
34
- });
35
- var createSoul, serializeSoul, deserializeSoul, exportSoul, importSoulFromArweave, getSoulList, createSoulInstance, validateSoul;
36
- var init_soul = __esm({
37
- "src/soul.ts"() {
38
- "use strict";
39
- createSoul = (id, name, persona, state, memories = []) => ({
40
- id,
41
- version: "1.0.0",
42
- name,
43
- persona,
44
- state: { ...state },
45
- memories: [...memories]
46
- });
47
- serializeSoul = (soul) => JSON.stringify(soul, null, 2);
48
- deserializeSoul = (json) => {
49
- const parsed = JSON.parse(json);
50
- if (!parsed.id || !parsed.persona || !parsed.state) {
51
- throw new Error("Invalid Soul format: missing required fields");
52
- }
53
- return {
54
- id: parsed.id,
55
- version: parsed.version || "1.0.0",
56
- name: parsed.name || "Unknown",
57
- persona: parsed.persona,
58
- state: parsed.state,
59
- memories: parsed.memories || [],
60
- signature: parsed.signature
61
- };
62
- };
63
- exportSoul = async (agentId, _soul, config = {}) => {
64
- const apiUrl = config.apiUrl || "https://api.forboc.ai";
65
- const response = await fetch(`${apiUrl}/agents/${agentId}/soul/export`, {
66
- method: "POST",
67
- headers: { "Content-Type": "application/json" },
68
- body: JSON.stringify({})
69
- // Future: allow specifying memories to include
70
- });
71
- if (!response.ok) {
72
- throw new Error(`Soul export failed: ${response.statusText}`);
73
- }
74
- const data = await response.json();
75
- return {
76
- txId: data.txId,
77
- url: data.url,
78
- soul: _soul
79
- // Return the local soul data as context
80
- };
81
- };
82
- importSoulFromArweave = async (txId, config = {}) => {
83
- const apiUrl = config.apiUrl || "https://api.forboc.ai";
84
- const response = await fetch(`${apiUrl}/souls/${txId}`);
85
- if (!response.ok) throw new Error(`Import failed: ${response.statusText}`);
86
- const data = await response.json();
87
- return data;
88
- };
89
- getSoulList = async (limit = 50, apiUrl = "https://api.forboc.ai") => {
90
- const response = await fetch(`${apiUrl}/souls?limit=${limit}`);
91
- if (!response.ok) return [];
92
- const data = await response.json();
93
- return data.souls || [];
94
- };
95
- createSoulInstance = (id, name, persona, state, memories = []) => {
96
- const soulData = createSoul(id, name, persona, state, memories);
97
- return {
98
- export: (config) => exportSoul(id, soulData, config),
99
- toJSON: () => ({ ...soulData })
100
- };
101
- };
102
- validateSoul = (soul) => {
103
- const errors = [
104
- !soul.id && "Missing id",
105
- !soul.persona && "Missing persona",
106
- !soul.state && "Missing state"
107
- ].filter((e) => !!e);
108
- return { valid: errors.length === 0, errors };
109
- };
110
- }
111
- });
112
-
113
20
  // src/index.ts
114
21
  var index_exports = {};
115
22
  __export(index_exports, {
116
23
  SDK_VERSION: () => SDK_VERSION,
117
- createAgent: () => createAgent,
118
- createBridge: () => createBridge,
119
- createGhost: () => createGhost,
24
+ addToHistory: () => addToHistory,
25
+ blockAction: () => blockAction,
26
+ bridgeSlice: () => bridgeSlice,
27
+ clearBlock: () => clearBlock,
28
+ clearBridgeValidation: () => clearBridgeValidation,
29
+ clearGhostSession: () => clearGhostSession,
30
+ clearSoulState: () => clearSoulState,
31
+ completeRemoteThunk: () => completeRemoteThunk,
32
+ cortexInitFailed: () => cortexInitFailed,
33
+ cortexInitStart: () => cortexInitStart,
34
+ cortexInitSuccess: () => cortexInitSuccess,
35
+ cortexSlice: () => cortexSlice,
120
36
  createInitialState: () => createInitialState,
121
- createRemoteCortex: () => createRemoteCortex,
122
- createSoul: () => createSoul,
123
- createSoulInstance: () => createSoulInstance,
37
+ createSDKStore: () => createSDKStore,
124
38
  delay: () => delay,
125
- deserializeSoul: () => deserializeSoul,
126
- exportSoul: () => exportSoul,
39
+ dialogueNPC: () => dialogueNPC,
40
+ dispatch: () => dispatch,
127
41
  exportToSoul: () => exportToSoul,
128
- fromSoul: () => fromSoul,
129
- getGhostHistory: () => getGhostHistory,
130
- getGhostResults: () => getGhostResults,
131
- getGhostStatus: () => getGhostStatus,
132
- getSoulList: () => getSoulList,
133
- importSoulFromArweave: () => importSoulFromArweave,
134
- loadPreset: () => loadPreset,
42
+ generateNPCId: () => generateNPCId,
43
+ getBridgeRulesThunk: () => getBridgeRulesThunk,
44
+ getGhostHistoryThunk: () => getGhostHistoryThunk,
45
+ getGhostResultsThunk: () => getGhostResultsThunk,
46
+ getGhostStatusThunk: () => getGhostStatusThunk,
47
+ getSoulListThunk: () => getSoulListThunk,
48
+ ghostSlice: () => ghostSlice,
49
+ importSoulFromArweaveThunk: () => importSoulFromArweaveThunk,
50
+ initRemoteCortexThunk: () => initRemoteCortexThunk,
51
+ loadBridgePresetThunk: () => loadBridgePresetThunk,
52
+ localExportSoulThunk: () => localExportSoulThunk,
135
53
  memoise: () => memoise,
136
54
  memoiseAsync: () => memoiseAsync,
55
+ memoryClear: () => memoryClear,
56
+ memoryRecallFailed: () => memoryRecallFailed,
57
+ memoryRecallStart: () => memoryRecallStart,
58
+ memoryRecallSuccess: () => memoryRecallSuccess,
59
+ memorySlice: () => memorySlice,
60
+ memoryStoreFailed: () => memoryStoreFailed,
61
+ memoryStoreStart: () => memoryStoreStart,
62
+ memoryStoreSuccess: () => memoryStoreSuccess,
63
+ npcSlice: () => npcSlice,
137
64
  pipe: () => pipe,
138
- serializeSoul: () => serializeSoul,
139
- startGhostSession: () => startGhostSession,
140
- stopGhostSession: () => stopGhostSession,
65
+ processNPC: () => processNPC,
66
+ remoteExportSoulThunk: () => remoteExportSoulThunk,
67
+ removeNPC: () => removeNPC,
68
+ sdkApi: () => sdkApi,
69
+ selectActiveNPC: () => selectActiveNPC,
70
+ selectActiveNpcId: () => selectActiveNpcId,
71
+ selectAllMemories: () => selectAllMemories,
72
+ selectAllNPCs: () => selectAllNPCs,
73
+ selectLastRecalledMemories: () => selectLastRecalledMemories,
74
+ selectMemoryById: () => selectMemoryById,
75
+ selectNPCById: () => selectNPCById,
76
+ selectNPCEntities: () => selectNPCEntities,
77
+ selectNPCIds: () => selectNPCIds,
78
+ selectTotalNPCs: () => selectTotalNPCs,
79
+ setActiveNPC: () => setActiveNPC,
80
+ setCortexStatus: () => setCortexStatus,
81
+ setHistory: () => setHistory,
82
+ setLastAction: () => setLastAction,
83
+ setNPCInfo: () => setNPCInfo,
84
+ setNPCState: () => setNPCState,
85
+ soulSlice: () => soulSlice,
86
+ speakNPC: () => speakNPC,
87
+ startGhostThunk: () => startGhostThunk,
88
+ stopGhostThunk: () => stopGhostThunk,
89
+ store: () => store,
141
90
  streamFromCortex: () => streamFromCortex,
142
91
  streamFromCortexWithDelay: () => streamFromCortexWithDelay,
143
92
  streamToCallback: () => streamToCallback,
144
93
  streamToString: () => streamToString,
145
- updateAgentState: () => updateAgentState,
146
- validateAction: () => validateAction,
147
- validateSoul: () => validateSoul,
148
- waitForGhostCompletion: () => waitForGhostCompletion
94
+ updateNPCState: () => updateNPCState,
95
+ updateNPCStateLocally: () => updateNPCStateLocally,
96
+ validateBridgeThunk: () => validateBridgeThunk
149
97
  });
150
98
  module.exports = __toCommonJS(index_exports);
151
99
 
152
- // src/agent.ts
100
+ // src/npc.ts
153
101
  var createInitialState = (partial) => ({ ...partial });
154
- var updateAgentState = (currentState, updates) => ({
102
+ var updateNPCStateLocally = (currentState, updates) => ({
155
103
  ...currentState,
156
104
  ...updates
157
105
  });
158
- var exportToSoul = (agentId, name, persona, state, memories) => ({
159
- id: agentId,
106
+ var exportToSoul = (npcId, name, persona, state, memories) => ({
107
+ id: npcId,
160
108
  version: "1.0.0",
161
109
  name,
162
110
  persona,
163
111
  memories: [...memories],
164
112
  state: { ...state }
165
113
  });
166
- var storeMemoriesRecursive = async (memory, instructions, index = 0) => {
167
- if (index >= instructions.length) return;
168
- const { text, type, importance } = instructions[index];
169
- await memory.store(text, type, importance).catch((e) => console.warn("Memory store failed:", e));
170
- return storeMemoriesRecursive(memory, instructions, index + 1);
114
+
115
+ // src/bridgeSlice.ts
116
+ var import_toolkit = require("@reduxjs/toolkit");
117
+
118
+ // src/apiSlice.ts
119
+ var import_query = require("@reduxjs/toolkit/query");
120
+ var sdkApi = (0, import_query.createApi)({
121
+ reducerPath: "forbocApi",
122
+ baseQuery: (0, import_query.fetchBaseQuery)({
123
+ baseUrl: "/",
124
+ prepareHeaders: (headers, { getState }) => {
125
+ return headers;
126
+ }
127
+ }),
128
+ tagTypes: ["NPC", "Memory", "Cortex", "Ghost", "Soul", "Bridge"],
129
+ endpoints: (builder) => ({
130
+ // NPC Endpoints
131
+ postDirective: builder.mutation({
132
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
133
+ url: `${apiUrl}/npcs/${npcId}/directive`,
134
+ method: "POST",
135
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
136
+ body: request
137
+ }),
138
+ invalidatesTags: ["NPC"],
139
+ transformResponse: (response) => response
140
+ }),
141
+ postContext: builder.mutation({
142
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
143
+ url: `${apiUrl}/npcs/${npcId}/context`,
144
+ method: "POST",
145
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
146
+ body: request
147
+ }),
148
+ invalidatesTags: (result, error, { npcId }) => [{ type: "NPC", id: npcId }],
149
+ transformResponse: (response) => response
150
+ }),
151
+ postVerdict: builder.mutation({
152
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
153
+ url: `${apiUrl}/npcs/${npcId}/verdict`,
154
+ method: "POST",
155
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
156
+ body: request
157
+ }),
158
+ invalidatesTags: (result, error, { npcId }) => [{ type: "NPC", id: npcId }],
159
+ transformResponse: (response) => {
160
+ const action = response.action ? {
161
+ type: response.action.gaType || response.action.type,
162
+ reason: response.action.actionReason || response.action.reason,
163
+ target: response.action.actionTarget || response.action.target,
164
+ signature: response.action.signature
165
+ } : void 0;
166
+ return {
167
+ ...response,
168
+ action
169
+ };
170
+ }
171
+ }),
172
+ postSpeak: builder.mutation({
173
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
174
+ url: `${apiUrl}/npcs/${npcId}/speak`,
175
+ method: "POST",
176
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
177
+ body: request
178
+ }),
179
+ invalidatesTags: (result, error, { npcId }) => [{ type: "NPC", id: npcId }],
180
+ transformResponse: (response) => response
181
+ }),
182
+ postDialogue: builder.mutation({
183
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
184
+ url: `${apiUrl}/npcs/${npcId}/dialogue`,
185
+ method: "POST",
186
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
187
+ body: request
188
+ }),
189
+ invalidatesTags: (result, error, { npcId }) => [{ type: "NPC", id: npcId }],
190
+ transformResponse: (response) => response
191
+ }),
192
+ // Ghost Endpoints
193
+ postGhostRun: builder.mutation({
194
+ query: ({ request, apiUrl }) => ({ url: `${apiUrl}/ghost/run`, method: "POST", body: request }),
195
+ invalidatesTags: ["Ghost"],
196
+ transformResponse: (response) => response
197
+ }),
198
+ getGhostStatus: builder.query({
199
+ query: ({ sessionId, apiUrl }) => ({ url: `${apiUrl}/ghost/${sessionId}/status`, method: "GET" }),
200
+ providesTags: (result, error, { sessionId }) => [{ type: "Ghost", id: sessionId }],
201
+ transformResponse: (response) => response
202
+ }),
203
+ getGhostResults: builder.query({
204
+ query: ({ sessionId, apiUrl }) => ({ url: `${apiUrl}/ghost/${sessionId}/results`, method: "GET" }),
205
+ providesTags: (result, error, { sessionId }) => [{ type: "Ghost", id: sessionId }],
206
+ transformResponse: (response) => response
207
+ }),
208
+ postGhostStop: builder.mutation({
209
+ query: ({ sessionId, apiUrl }) => ({ url: `${apiUrl}/ghost/${sessionId}/stop`, method: "POST" }),
210
+ invalidatesTags: (result, error, { sessionId }) => [{ type: "Ghost", id: sessionId }],
211
+ transformResponse: (response) => ({ stopped: true })
212
+ }),
213
+ getGhostHistory: builder.query({
214
+ query: ({ limit, apiUrl }) => ({ url: `${apiUrl}/ghost/history?limit=${limit}`, method: "GET" }),
215
+ providesTags: ["Ghost"],
216
+ transformResponse: (response) => response
217
+ }),
218
+ // Soul Endpoints
219
+ postSoulExport: builder.mutation({
220
+ query: ({ npcId, request, apiUrl }) => ({ url: `${apiUrl}/npcs/${npcId}/soul/export`, method: "POST", body: request }),
221
+ invalidatesTags: ["Soul"],
222
+ transformResponse: (response) => response
223
+ }),
224
+ getSoulImport: builder.query({
225
+ query: ({ txId, apiUrl }) => ({ url: `${apiUrl}/souls/${txId}`, method: "GET" }),
226
+ providesTags: (result, error, { txId }) => [{ type: "Soul", id: txId }],
227
+ transformResponse: (response) => response
228
+ }),
229
+ getSouls: builder.query({
230
+ query: ({ limit, apiUrl }) => ({ url: `${apiUrl}/souls?limit=${limit}`, method: "GET" }),
231
+ providesTags: ["Soul"],
232
+ transformResponse: (response) => response
233
+ }),
234
+ // Bridge Endpoints
235
+ postBridgeValidate: builder.mutation({
236
+ query: ({ request, npcId, apiUrl }) => ({
237
+ url: npcId ? `${apiUrl}/bridge/validate/${npcId}` : `${apiUrl}/bridge/validate`,
238
+ method: "POST",
239
+ body: request
240
+ }),
241
+ invalidatesTags: ["Bridge"],
242
+ transformResponse: (response) => response.brResult || response
243
+ }),
244
+ getBridgeRules: builder.query({
245
+ query: ({ apiUrl }) => ({ url: `${apiUrl}/rules`, method: "GET" }),
246
+ providesTags: ["Bridge"],
247
+ transformResponse: (response) => response
248
+ }),
249
+ postBridgePreset: builder.mutation({
250
+ query: ({ presetName, apiUrl }) => ({ url: `${apiUrl}/rules/presets/${presetName}`, method: "POST" }),
251
+ invalidatesTags: ["Bridge"],
252
+ transformResponse: (response) => response
253
+ }),
254
+ // Cortex Remote Endpoint
255
+ postCortexComplete: builder.mutation({
256
+ query: ({ cortexId, prompt, options, apiUrl, apiKey }) => ({
257
+ url: `${apiUrl}/cortex/${cortexId}/complete`,
258
+ method: "POST",
259
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
260
+ body: { prompt, ...options }
261
+ }),
262
+ invalidatesTags: ["Cortex"],
263
+ transformResponse: (response) => response
264
+ }),
265
+ // System Endpoints
266
+ getApiStatus: builder.query({
267
+ query: ({ apiUrl }) => ({ url: `${apiUrl}/status`, method: "GET" }),
268
+ transformResponse: (response) => response
269
+ })
270
+ })
271
+ });
272
+
273
+ // src/bridgeSlice.ts
274
+ var initialState = {
275
+ activePresets: [],
276
+ lastValidation: null,
277
+ status: "idle",
278
+ error: null
171
279
  };
172
- var createAgent = (config) => {
173
- let _state = createInitialState(config.initialState);
174
- const cortex = config.cortex;
175
- const apiUrl = config.apiUrl || "https://api.forboc.ai";
176
- const agentId = config.id || "agent-" + Math.random().toString(36).substring(7);
177
- const authHeaders = config.apiKey ? { "Content-Type": "application/json", "Authorization": `Bearer ${config.apiKey}` } : { "Content-Type": "application/json" };
178
- const getState = () => ({ ..._state });
179
- const setState = (newState) => {
180
- _state = newState;
181
- };
182
- const process = async (input, context = {}) => {
183
- const currentState = getState();
184
- const dirRes = await fetch(`${apiUrl}/agents/${agentId}/directive`, {
185
- method: "POST",
186
- headers: authHeaders,
187
- body: JSON.stringify({ observation: input, agentState: currentState, context })
188
- });
189
- if (!dirRes.ok) throw new Error(`API Directive Error: ${dirRes.status}`);
190
- const directiveData = await dirRes.json();
191
- const recalledMemories = config.memory && directiveData.memoryRecall ? await config.memory.recall(
192
- directiveData.memoryRecall.query,
193
- directiveData.memoryRecall.limit,
194
- directiveData.memoryRecall.threshold
195
- ).then((mems) => mems.map((m) => ({ text: m.text, type: m.type, importance: m.importance, similarity: void 0 }))).catch(() => []) : [];
196
- const ctxRes = await fetch(`${apiUrl}/agents/${agentId}/context`, {
197
- method: "POST",
198
- headers: authHeaders,
199
- body: JSON.stringify({ memories: recalledMemories, observation: input, agentState: currentState })
200
- });
201
- if (!ctxRes.ok) throw new Error(`API Context Error: ${ctxRes.status}`);
202
- const contextData = await ctxRes.json();
203
- const generatedText = await cortex.complete(contextData.prompt, {
204
- maxTokens: contextData.constraints.maxTokens,
205
- temperature: contextData.constraints.temperature,
206
- stop: contextData.constraints.stop
207
- });
208
- const verRes = await fetch(`${apiUrl}/agents/${agentId}/verdict`, {
209
- method: "POST",
210
- headers: authHeaders,
211
- body: JSON.stringify({ generatedOutput: generatedText, observation: input, agentState: currentState })
212
- });
213
- if (!verRes.ok) throw new Error(`API Verdict Error: ${verRes.status}`);
214
- const verdictData = await verRes.json();
215
- if (!verdictData.valid) {
216
- return { dialogue: "... [Blocked]", action: { type: "BLOCKED", reason: "Validation Failed" } };
280
+ var validateBridgeThunk = (0, import_toolkit.createAsyncThunk)(
281
+ "bridge/validate",
282
+ async ({ action, context, npcId, apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
283
+ try {
284
+ const url = apiUrl || "https://api.forboc.ai";
285
+ const data = await dispatch2(sdkApi.endpoints.postBridgeValidate.initiate({
286
+ request: { action, context },
287
+ npcId,
288
+ apiUrl: url
289
+ })).unwrap();
290
+ return data;
291
+ } catch (e) {
292
+ return rejectWithValue(e.message || "Bridge validation failed");
217
293
  }
218
- if (config.memory && verdictData.memoryStore) {
219
- storeMemoriesRecursive(config.memory, verdictData.memoryStore);
294
+ }
295
+ );
296
+ var loadBridgePresetThunk = (0, import_toolkit.createAsyncThunk)(
297
+ "bridge/loadPreset",
298
+ async ({ presetName, apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
299
+ try {
300
+ const url = apiUrl || "https://api.forboc.ai";
301
+ return await dispatch2(sdkApi.endpoints.postBridgePreset.initiate({ presetName, apiUrl: url })).unwrap();
302
+ } catch (e) {
303
+ return rejectWithValue(e.message || "Failed to load preset");
220
304
  }
221
- if (verdictData.stateDelta) {
222
- setState(updateAgentState(_state, verdictData.stateDelta));
305
+ }
306
+ );
307
+ var getBridgeRulesThunk = (0, import_toolkit.createAsyncThunk)(
308
+ "bridge/rules",
309
+ async ({ apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
310
+ try {
311
+ const url = apiUrl || "https://api.forboc.ai";
312
+ return await dispatch2(sdkApi.endpoints.getBridgeRules.initiate({ apiUrl: url })).unwrap();
313
+ } catch (e) {
314
+ return rejectWithValue(e.message || "Failed to list rulesets");
223
315
  }
224
- return {
225
- dialogue: generatedText,
226
- action: verdictData.action ? { ...verdictData.action, signature: verdictData.signature } : void 0,
227
- thought: generatedText
228
- };
229
- };
230
- const speak = async (message, context = {}) => {
231
- const res = await fetch(`${apiUrl}/agents/${agentId}/speak`, {
232
- method: "POST",
233
- headers: authHeaders,
234
- body: JSON.stringify({ speakMessage: message, speakContext: context, speakAgentState: getState() })
235
- });
236
- if (!res.ok) throw new Error(`API Speak Error: ${res.status}`);
237
- const data = await res.json();
238
- if (data.speakHistory) setState(updateAgentState(_state, { conversationHistory: data.speakHistory }));
239
- return data.speakReply;
240
- };
241
- const dialogue = async (message, context = []) => {
242
- const res = await fetch(`${apiUrl}/agents/${agentId}/dialogue`, {
243
- method: "POST",
244
- headers: authHeaders,
245
- body: JSON.stringify({ diagMessage: message, diagContext: context })
316
+ }
317
+ );
318
+ var bridgeSlice = (0, import_toolkit.createSlice)({
319
+ name: "bridge",
320
+ initialState,
321
+ reducers: {
322
+ clearBridgeValidation: (state) => {
323
+ state.lastValidation = null;
324
+ state.status = "idle";
325
+ state.error = null;
326
+ }
327
+ },
328
+ extraReducers: (builder) => {
329
+ builder.addCase(validateBridgeThunk.pending, (state) => {
330
+ state.status = "validating";
331
+ state.error = null;
332
+ }).addCase(validateBridgeThunk.fulfilled, (state, action) => {
333
+ state.status = "idle";
334
+ state.lastValidation = action.payload;
335
+ }).addCase(validateBridgeThunk.rejected, (state, action) => {
336
+ state.status = "error";
337
+ state.error = action.payload;
338
+ state.lastValidation = { valid: false, reason: action.payload };
339
+ }).addCase(loadBridgePresetThunk.pending, (state) => {
340
+ state.status = "loading_preset";
341
+ state.error = null;
342
+ }).addCase(loadBridgePresetThunk.fulfilled, (state, action) => {
343
+ state.status = "idle";
344
+ if (!state.activePresets.find((p) => p.id === action.payload.id)) {
345
+ state.activePresets.push(action.payload);
346
+ }
347
+ }).addCase(loadBridgePresetThunk.rejected, (state, action) => {
348
+ state.status = "error";
349
+ state.error = action.payload;
350
+ }).addCase(getBridgeRulesThunk.fulfilled, (state, action) => {
246
351
  });
247
- if (!res.ok) throw new Error(`API Dialogue Error: ${res.status}`);
248
- const data = await res.json();
249
- return data.diagReply;
250
- };
251
- const exportSoul2 = async () => {
252
- const memories = config.memory ? await config.memory.export().catch(() => []) : [];
253
- return exportToSoul(agentId, "Agent", config.persona, _state, memories);
254
- };
255
- const exportSoulToArweave = async (soulConfig) => {
256
- const soul = await exportSoul2();
257
- const { exportSoul: exportFunc } = await Promise.resolve().then(() => (init_soul(), soul_exports));
258
- return exportFunc(agentId, soul, { ...soulConfig, apiUrl });
259
- };
260
- return { process, speak, dialogue, reply: speak, getState, setState, export: exportSoul2, exportSoul: exportSoulToArweave };
261
- };
262
- var fromSoul = async (soul, cortex, memory) => {
263
- const agent = createAgent({
264
- id: soul.id,
265
- cortex,
266
- memory: memory || null,
267
- persona: soul.persona,
268
- initialState: soul.state
269
- });
270
- if (memory && soul.memories && soul.memories.length > 0) {
271
- await memory.import(soul.memories).catch((e) => console.warn("Memory hydration failed:", e));
272
352
  }
273
- return agent;
353
+ });
354
+ var { clearBridgeValidation } = bridgeSlice.actions;
355
+ var bridgeSlice_default = bridgeSlice.reducer;
356
+
357
+ // src/soulSlice.ts
358
+ var import_toolkit2 = require("@reduxjs/toolkit");
359
+ var initialState2 = {
360
+ exportStatus: "idle",
361
+ importStatus: "idle",
362
+ lastExport: null,
363
+ lastImport: null,
364
+ availableSouls: [],
365
+ error: null
274
366
  };
367
+ var remoteExportSoulThunk = (0, import_toolkit2.createAsyncThunk)(
368
+ "soul/export",
369
+ async ({ npcId: argNpcId, apiUrl, memories = [] }, { getState, dispatch: dispatch2, rejectWithValue }) => {
370
+ try {
371
+ const state = getState().npc;
372
+ const npcId = argNpcId || state.activeNpcId;
373
+ const npc = state.entities[npcId];
374
+ if (!npc) throw new Error(`NPC ${npcId} not found`);
375
+ const url = apiUrl || "https://api.forboc.ai";
376
+ const result = await dispatch2(sdkApi.endpoints.postSoulExport.initiate({
377
+ npcId,
378
+ request: { npcIdRef: npcId, persona: npc.persona || "NPC", npcState: npc.state },
379
+ apiUrl: url
380
+ })).unwrap();
381
+ return {
382
+ txId: result.txId,
383
+ url: result.arweaveUrl,
384
+ soul: result.soul
385
+ };
386
+ } catch (e) {
387
+ return rejectWithValue(e.message || "Soul export failed");
388
+ }
389
+ }
390
+ );
391
+ var importSoulFromArweaveThunk = (0, import_toolkit2.createAsyncThunk)(
392
+ "soul/import",
393
+ async ({ txId, apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
394
+ try {
395
+ const url = apiUrl || "https://api.forboc.ai";
396
+ const data = await dispatch2(sdkApi.endpoints.getSoulImport.initiate({ txId, apiUrl: url })).unwrap();
397
+ return data;
398
+ } catch (e) {
399
+ return rejectWithValue(e.message || "Soul import failed");
400
+ }
401
+ }
402
+ );
403
+ var getSoulListThunk = (0, import_toolkit2.createAsyncThunk)(
404
+ "soul/list",
405
+ async ({ limit = 50, apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
406
+ try {
407
+ const url = apiUrl || "https://api.forboc.ai";
408
+ const data = await dispatch2(sdkApi.endpoints.getSouls.initiate({ limit, apiUrl: url })).unwrap();
409
+ return data.souls || [];
410
+ } catch (e) {
411
+ return rejectWithValue(e.message || "Failed to list souls");
412
+ }
413
+ }
414
+ );
415
+ var soulSlice = (0, import_toolkit2.createSlice)({
416
+ name: "soul",
417
+ initialState: initialState2,
418
+ reducers: {
419
+ clearSoulState: (state) => {
420
+ state.exportStatus = "idle";
421
+ state.importStatus = "idle";
422
+ state.lastExport = null;
423
+ state.lastImport = null;
424
+ state.error = null;
425
+ }
426
+ },
427
+ extraReducers: (builder) => {
428
+ builder.addCase(remoteExportSoulThunk.pending, (state) => {
429
+ state.exportStatus = "exporting";
430
+ state.error = null;
431
+ }).addCase(remoteExportSoulThunk.fulfilled, (state, action) => {
432
+ state.exportStatus = "success";
433
+ state.lastExport = action.payload;
434
+ }).addCase(remoteExportSoulThunk.rejected, (state, action) => {
435
+ state.exportStatus = "failed";
436
+ state.error = action.payload;
437
+ }).addCase(importSoulFromArweaveThunk.pending, (state) => {
438
+ state.importStatus = "importing";
439
+ state.error = null;
440
+ }).addCase(importSoulFromArweaveThunk.fulfilled, (state, action) => {
441
+ state.importStatus = "success";
442
+ state.lastImport = action.payload;
443
+ }).addCase(importSoulFromArweaveThunk.rejected, (state, action) => {
444
+ state.importStatus = "failed";
445
+ state.error = action.payload;
446
+ }).addCase(getSoulListThunk.fulfilled, (state, action) => {
447
+ state.availableSouls = action.payload;
448
+ });
449
+ }
450
+ });
451
+ var { clearSoulState } = soulSlice.actions;
452
+ var soulSlice_default = soulSlice.reducer;
275
453
 
276
- // src/bridge.ts
277
- var createBridge = (config = {}) => {
278
- const apiUrl = config.apiUrl || "https://api.forboc.ai";
279
- const agentId = config.agentId;
280
- const validate = async (action, context = {}) => {
281
- const endpoint = agentId ? `${apiUrl}/bridge/validate/${agentId}` : `${apiUrl}/bridge/validate`;
454
+ // src/ghostSlice.ts
455
+ var import_toolkit3 = require("@reduxjs/toolkit");
456
+ var initialState3 = {
457
+ activeSessionId: null,
458
+ status: null,
459
+ progress: 0,
460
+ results: null,
461
+ history: [],
462
+ loading: false,
463
+ error: null
464
+ };
465
+ var startGhostThunk = (0, import_toolkit3.createAsyncThunk)(
466
+ "ghost/start",
467
+ async (config, { dispatch: dispatch2, rejectWithValue }) => {
282
468
  try {
283
- const response = await fetch(endpoint, {
284
- method: "POST",
285
- headers: { "Content-Type": "application/json" },
286
- body: JSON.stringify({ action, context })
287
- });
288
- if (!response.ok) {
289
- const error = await response.text();
290
- throw new Error(`Bridge validation failed: ${error}`);
291
- }
292
- const data = await response.json();
293
- return data.brResult || data;
469
+ const apiUrl = config.apiUrl || "https://api.forboc.ai";
470
+ const data = await dispatch2(sdkApi.endpoints.postGhostRun.initiate({
471
+ request: { testSuite: config.testSuite, duration: config.duration ?? 300 },
472
+ apiUrl
473
+ })).unwrap();
474
+ return {
475
+ sessionId: data.sessionId,
476
+ status: data.runStatus
477
+ };
294
478
  } catch (e) {
295
- console.error("[Bridge] Validation error:", e);
479
+ return rejectWithValue(e.message || "Failed to start Ghost");
480
+ }
481
+ }
482
+ );
483
+ var getGhostStatusThunk = (0, import_toolkit3.createAsyncThunk)(
484
+ "ghost/status",
485
+ async ({ sessionId, apiUrl }, { dispatch: dispatch2, getState, rejectWithValue }) => {
486
+ try {
487
+ const state = getState().ghost;
488
+ const targetSession = sessionId || state.activeSessionId;
489
+ if (!targetSession) throw new Error("No active Ghost session");
490
+ const url = apiUrl || "https://api.forboc.ai";
491
+ const data = await dispatch2(sdkApi.endpoints.getGhostStatus.initiate({ sessionId: targetSession, apiUrl: url })).unwrap();
296
492
  return {
297
- valid: false,
298
- reason: `Network error reaching validation API: ${e instanceof Error ? e.message : String(e)}`
493
+ sessionId: data.ghostSessionId,
494
+ status: data.ghostStatus,
495
+ progress: data.ghostProgress,
496
+ startedAt: data.ghostStartedAt,
497
+ duration: data.ghostDuration || 0,
498
+ errors: data.ghostErrors
299
499
  };
500
+ } catch (e) {
501
+ return rejectWithValue(e.message || "Failed to get ghost status");
300
502
  }
301
- };
302
- const listRulesets = async () => {
303
- const response = await fetch(`${apiUrl}/rules`);
304
- if (!response.ok) return [];
305
- return response.json();
306
- };
307
- return { validate, listRulesets };
308
- };
309
- var validateAction = async (action, context = {}, config = {}) => {
310
- const bridge = createBridge(config);
311
- return bridge.validate(action, context);
312
- };
313
- var loadPreset = async (presetName, apiUrl = "https://api.forboc.ai") => {
314
- const response = await fetch(`${apiUrl}/rules/presets/${presetName}`, {
315
- method: "POST"
316
- });
317
- if (!response.ok) {
318
- throw new Error(`Failed to load preset '${presetName}': ${response.statusText}`);
319
503
  }
320
- return response.json();
321
- };
322
-
323
- // src/index.ts
324
- init_soul();
504
+ );
505
+ var getGhostResultsThunk = (0, import_toolkit3.createAsyncThunk)(
506
+ "ghost/results",
507
+ async ({ sessionId, apiUrl }, { dispatch: dispatch2, getState, rejectWithValue }) => {
508
+ try {
509
+ const state = getState().ghost;
510
+ const targetSession = sessionId || state.activeSessionId;
511
+ if (!targetSession) throw new Error("No active Ghost session");
512
+ const url = apiUrl || "https://api.forboc.ai";
513
+ const data = await dispatch2(sdkApi.endpoints.getGhostResults.initiate({ sessionId: targetSession, apiUrl: url })).unwrap();
514
+ return {
515
+ sessionId: data.resultsSessionId,
516
+ totalTests: data.resultsTotalTests,
517
+ passed: data.resultsPassed,
518
+ failed: data.resultsFailed,
519
+ skipped: data.resultsSkipped,
520
+ duration: data.resultsDuration,
521
+ tests: (data.resultsTests || []).map((t) => ({
522
+ name: t.testName,
523
+ passed: t.testPassed,
524
+ duration: t.testDuration,
525
+ error: t.testError,
526
+ screenshot: t.testScreenshot
527
+ })),
528
+ coverage: data.resultsCoverage,
529
+ metrics: Object.fromEntries(data.resultsMetrics || [])
530
+ };
531
+ } catch (e) {
532
+ return rejectWithValue(e.message || "Failed to get ghost results");
533
+ }
534
+ }
535
+ );
536
+ var stopGhostThunk = (0, import_toolkit3.createAsyncThunk)(
537
+ "ghost/stop",
538
+ async ({ sessionId, apiUrl }, { dispatch: dispatch2, getState, rejectWithValue }) => {
539
+ try {
540
+ const state = getState().ghost;
541
+ const targetSession = sessionId || state.activeSessionId;
542
+ if (!targetSession) throw new Error("No active Ghost session");
543
+ const url = apiUrl || "https://api.forboc.ai";
544
+ await dispatch2(sdkApi.endpoints.postGhostStop.initiate({ sessionId: targetSession, apiUrl: url })).unwrap();
545
+ return { stopped: true };
546
+ } catch (e) {
547
+ return { stopped: true };
548
+ }
549
+ }
550
+ );
551
+ var getGhostHistoryThunk = (0, import_toolkit3.createAsyncThunk)(
552
+ "ghost/history",
553
+ async ({ limit = 10, apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
554
+ try {
555
+ const url = apiUrl || "https://api.forboc.ai";
556
+ const data = await dispatch2(sdkApi.endpoints.getGhostHistory.initiate({ limit, apiUrl: url })).unwrap();
557
+ return (data.sessions || []).map((s) => ({
558
+ sessionId: s.sessionId,
559
+ testSuite: s.testSuite,
560
+ startedAt: s.startedAt,
561
+ completedAt: s.completedAt,
562
+ status: s.status,
563
+ passRate: s.passRate
564
+ }));
565
+ } catch (e) {
566
+ return rejectWithValue(e.message || "Failed to get ghost history");
567
+ }
568
+ }
569
+ );
570
+ var ghostSlice = (0, import_toolkit3.createSlice)({
571
+ name: "ghost",
572
+ initialState: initialState3,
573
+ reducers: {
574
+ clearGhostSession: (state) => {
575
+ state.activeSessionId = null;
576
+ state.status = null;
577
+ state.progress = 0;
578
+ state.results = null;
579
+ }
580
+ },
581
+ extraReducers: (builder) => {
582
+ builder.addCase(startGhostThunk.pending, (state) => {
583
+ state.loading = true;
584
+ state.error = null;
585
+ }).addCase(startGhostThunk.fulfilled, (state, action) => {
586
+ state.loading = false;
587
+ state.activeSessionId = action.payload.sessionId;
588
+ state.status = "running";
589
+ state.progress = 0;
590
+ }).addCase(startGhostThunk.rejected, (state, action) => {
591
+ state.loading = false;
592
+ state.error = action.payload;
593
+ }).addCase(getGhostStatusThunk.fulfilled, (state, action) => {
594
+ state.status = action.payload.status;
595
+ state.progress = action.payload.progress;
596
+ }).addCase(getGhostResultsThunk.fulfilled, (state, action) => {
597
+ state.results = action.payload;
598
+ state.status = "completed";
599
+ }).addCase(stopGhostThunk.fulfilled, (state) => {
600
+ state.status = "failed";
601
+ }).addCase(getGhostHistoryThunk.fulfilled, (state, action) => {
602
+ state.history = action.payload;
603
+ });
604
+ }
605
+ });
606
+ var { clearGhostSession } = ghostSlice.actions;
607
+ var ghostSlice_default = ghostSlice.reducer;
325
608
 
326
609
  // src/utils.ts
610
+ var SDK_VERSION = "0.5.9";
611
+ var generateNPCId = () => `ag_${Date.now().toString(36)}`;
327
612
  var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
328
613
  var pipe = (...fns) => (initialValue) => fns.reduce((acc, fn) => fn(acc), initialValue);
329
614
  var memoiseAsync = (fn) => {
@@ -350,161 +635,6 @@ var memoise = (fn) => {
350
635
  };
351
636
  };
352
637
 
353
- // src/ghost.ts
354
- var DEFAULT_API_URL = "https://api.forboc.ai";
355
- var startGhostSession = async (config) => {
356
- const apiUrl = config.apiUrl || DEFAULT_API_URL;
357
- const response = await fetch(`${apiUrl}/ghost/run`, {
358
- method: "POST",
359
- headers: { "Content-Type": "application/json" },
360
- body: JSON.stringify({
361
- testSuite: config.testSuite,
362
- duration: config.duration
363
- })
364
- });
365
- if (!response.ok) throw new Error(`Failed to start Ghost: ${response.statusText}`);
366
- const data = await response.json();
367
- return {
368
- sessionId: data.sessionId,
369
- status: data.runStatus
370
- };
371
- };
372
- var getGhostStatus = async (sessionId, apiUrl) => {
373
- const url = apiUrl || DEFAULT_API_URL;
374
- const response = await fetch(`${url}/ghost/${sessionId}/status`, {
375
- method: "GET",
376
- headers: { "Content-Type": "application/json" }
377
- });
378
- if (!response.ok) throw new Error(`Failed to get status: ${response.statusText}`);
379
- const data = await response.json();
380
- return {
381
- sessionId: data.ghostSessionId,
382
- status: data.ghostStatus,
383
- progress: data.ghostProgress,
384
- startedAt: data.ghostStartedAt,
385
- duration: data.ghostDuration,
386
- errors: data.ghostErrors
387
- };
388
- };
389
- var getGhostResults = async (sessionId, apiUrl) => {
390
- const url = apiUrl || DEFAULT_API_URL;
391
- const response = await fetch(`${url}/ghost/${sessionId}/results`, {
392
- method: "GET",
393
- headers: { "Content-Type": "application/json" }
394
- });
395
- if (!response.ok) throw new Error(`Failed to get results: ${response.statusText}`);
396
- const data = await response.json();
397
- return {
398
- sessionId: data.resultsSessionId,
399
- totalTests: data.resultsTotalTests,
400
- passed: data.resultsPassed,
401
- failed: data.resultsFailed,
402
- skipped: data.resultsSkipped,
403
- duration: data.resultsDuration,
404
- tests: data.resultsTests.map((t) => ({
405
- name: t.testName,
406
- passed: t.testPassed,
407
- duration: t.testDuration,
408
- error: t.testError,
409
- screenshot: t.testScreenshot
410
- })),
411
- coverage: data.resultsCoverage,
412
- metrics: Object.fromEntries(data.resultsMetrics || [])
413
- };
414
- };
415
- var pollForCompletion = async (sessionId, pollIntervalMs, timeoutMs, startTime, apiUrl, onProgress) => {
416
- if (Date.now() - startTime > timeoutMs) {
417
- throw new Error(`Ghost session timed out after ${timeoutMs}ms`);
418
- }
419
- try {
420
- const status = await getGhostStatus(sessionId, apiUrl);
421
- if (onProgress) onProgress(status);
422
- if (status.status === "completed") return getGhostResults(sessionId, apiUrl);
423
- if (status.status === "failed") throw new Error(`Ghost session failed with ${status.errors} errors`);
424
- } catch (e) {
425
- }
426
- await delay(pollIntervalMs);
427
- return pollForCompletion(sessionId, pollIntervalMs, timeoutMs, startTime, apiUrl, onProgress);
428
- };
429
- var waitForGhostCompletion = (sessionId, pollIntervalMs = 5e3, timeoutMs = 3e5, apiUrl, onProgress) => pollForCompletion(sessionId, pollIntervalMs, timeoutMs, Date.now(), apiUrl, onProgress);
430
- var stopGhostSession = async (sessionId, apiUrl) => {
431
- const url = apiUrl || DEFAULT_API_URL;
432
- try {
433
- const response = await fetch(`${url}/ghost/${sessionId}/stop`, { method: "POST" });
434
- return { stopped: response.ok };
435
- } catch (e) {
436
- return { stopped: true };
437
- }
438
- };
439
- var getGhostHistory = async (limit = 10, apiUrl) => {
440
- const url = apiUrl || DEFAULT_API_URL;
441
- try {
442
- const response = await fetch(`${url}/ghost/history?limit=${limit}`);
443
- if (!response.ok) return [];
444
- const data = await response.json();
445
- return data.sessions.map((s) => ({
446
- sessionId: s.sessionId,
447
- testSuite: s.testSuite,
448
- startedAt: s.startedAt,
449
- completedAt: s.completedAt,
450
- status: s.status,
451
- passRate: s.passRate
452
- }));
453
- } catch (e) {
454
- return [];
455
- }
456
- };
457
- var createGhost = (config) => {
458
- let _sessionId = null;
459
- const apiUrl = config.apiUrl || DEFAULT_API_URL;
460
- const run = async () => {
461
- const result = await startGhostSession(config);
462
- _sessionId = result.sessionId;
463
- return _sessionId;
464
- };
465
- const ensureSessionId = () => {
466
- if (!_sessionId) throw new Error("Ghost session not started");
467
- return _sessionId;
468
- };
469
- const status = async () => getGhostStatus(ensureSessionId(), apiUrl);
470
- const results = async () => getGhostResults(ensureSessionId(), apiUrl);
471
- const stop = async () => {
472
- if (_sessionId) await stopGhostSession(_sessionId, apiUrl);
473
- _sessionId = null;
474
- };
475
- const waitForCompletion = (pollIntervalMs, timeoutMs, onProgress) => waitForGhostCompletion(ensureSessionId(), pollIntervalMs, timeoutMs, apiUrl, onProgress);
476
- return { run, status, results, stop, waitForCompletion };
477
- };
478
-
479
- // src/cortex-remote.ts
480
- var createRemoteCortex = (apiUrl, cortexId = "local", apiKey) => {
481
- const authHeaders = {
482
- "Content-Type": "application/json",
483
- ...apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
484
- };
485
- const init = async () => ({
486
- id: `remote_${Date.now()}`,
487
- model: "api-integrated",
488
- ready: true,
489
- engine: "remote"
490
- });
491
- const complete = async (prompt, options) => {
492
- const response = await fetch(`${apiUrl}/cortex/${cortexId}/complete`, {
493
- method: "POST",
494
- headers: authHeaders,
495
- body: JSON.stringify({ prompt, ...options })
496
- });
497
- if (!response.ok) throw new Error(`Remote Cortex failed: ${response.statusText}`);
498
- const data = await response.json();
499
- return data.text;
500
- };
501
- const completeStream = async function* (prompt, options) {
502
- const result = await complete(prompt, options);
503
- yield result;
504
- };
505
- return { init, complete, completeStream };
506
- };
507
-
508
638
  // src/stream.ts
509
639
  var consumeStream = async (stream, onChunk, acc = "", delayMs = 0) => {
510
640
  const { value, done } = await stream.next();
@@ -529,41 +659,454 @@ var streamFromCortexWithDelay = async (cortex, prompt, onChunk, options) => {
529
659
  return consumeStream(cortex.completeStream(prompt, completionOptions), onChunk, "", delayMs);
530
660
  };
531
661
 
532
- // src/index.ts
533
- var SDK_VERSION = "0.5.7";
662
+ // src/store.ts
663
+ var import_toolkit8 = require("@reduxjs/toolkit");
664
+
665
+ // src/npcSlice.ts
666
+ var import_toolkit4 = require("@reduxjs/toolkit");
667
+ var npcAdapter = (0, import_toolkit4.createEntityAdapter)();
668
+ var npcSlice = (0, import_toolkit4.createSlice)({
669
+ name: "npc",
670
+ initialState: npcAdapter.getInitialState({
671
+ activeNpcId: ""
672
+ }),
673
+ reducers: {
674
+ setNPCInfo: (state, action) => {
675
+ const { id, persona, initialState: initialState5 } = action.payload;
676
+ npcAdapter.upsertOne(state, {
677
+ id,
678
+ persona,
679
+ state: initialState5 || {},
680
+ history: [],
681
+ isBlocked: false
682
+ });
683
+ state.activeNpcId = id;
684
+ },
685
+ setActiveNPC: (state, action) => {
686
+ state.activeNpcId = action.payload;
687
+ },
688
+ setNPCState: (state, action) => {
689
+ const { id, state: npcState } = action.payload;
690
+ npcAdapter.updateOne(state, { id, changes: { state: npcState } });
691
+ },
692
+ updateNPCState: (state, action) => {
693
+ const { id, delta } = action.payload;
694
+ const npc = state.entities[id];
695
+ if (npc) {
696
+ npc.state = { ...npc.state, ...delta };
697
+ }
698
+ },
699
+ addToHistory: (state, action) => {
700
+ const { id, role, content } = action.payload;
701
+ const npc = state.entities[id];
702
+ if (npc) {
703
+ npc.history.push({ role, content });
704
+ }
705
+ },
706
+ setHistory: (state, action) => {
707
+ const { id, history } = action.payload;
708
+ npcAdapter.updateOne(state, { id, changes: { history } });
709
+ },
710
+ setLastAction: (state, action) => {
711
+ const { id, action: npcAction } = action.payload;
712
+ npcAdapter.updateOne(state, { id, changes: { lastAction: npcAction } });
713
+ },
714
+ blockAction: (state, action) => {
715
+ const { id, reason } = action.payload;
716
+ npcAdapter.updateOne(state, { id, changes: { isBlocked: true, blockReason: reason } });
717
+ },
718
+ clearBlock: (state, action) => {
719
+ npcAdapter.updateOne(state, { id: action.payload, changes: { isBlocked: false, blockReason: void 0 } });
720
+ },
721
+ removeNPC: npcAdapter.removeOne
722
+ }
723
+ });
724
+ var {
725
+ setNPCInfo,
726
+ setActiveNPC,
727
+ setNPCState,
728
+ updateNPCState,
729
+ addToHistory,
730
+ setHistory,
731
+ setLastAction,
732
+ blockAction,
733
+ clearBlock,
734
+ removeNPC
735
+ } = npcSlice.actions;
736
+ var {
737
+ selectById: selectNPCById,
738
+ selectIds: selectNPCIds,
739
+ selectEntities: selectNPCEntities,
740
+ selectAll: selectAllNPCs,
741
+ selectTotal: selectTotalNPCs
742
+ } = npcAdapter.getSelectors((state) => state.npc);
743
+ var selectActiveNpcId = (state) => state.npc.activeNpcId;
744
+ var selectActiveNPC = (state) => {
745
+ const id = selectActiveNpcId(state);
746
+ return state.npc.entities[id];
747
+ };
748
+ var npcSlice_default = npcSlice.reducer;
749
+
750
+ // src/cortexSlice.ts
751
+ var import_toolkit5 = require("@reduxjs/toolkit");
752
+ var initialState4 = {
753
+ status: {
754
+ id: "init",
755
+ model: "none",
756
+ ready: false,
757
+ engine: "mock"
758
+ },
759
+ isInitializing: false
760
+ };
761
+ var initRemoteCortexThunk = (0, import_toolkit5.createAsyncThunk)(
762
+ "cortex/initRemote",
763
+ async ({ model = "api-integrated" }) => {
764
+ return {
765
+ id: `remote_${Date.now()}`,
766
+ model,
767
+ ready: true,
768
+ engine: "remote"
769
+ };
770
+ }
771
+ );
772
+ var completeRemoteThunk = (0, import_toolkit5.createAsyncThunk)(
773
+ "cortex/completeRemote",
774
+ async ({ cortexId, prompt, options, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
775
+ try {
776
+ const data = await dispatch2(sdkApi.endpoints.postCortexComplete.initiate({
777
+ cortexId,
778
+ prompt,
779
+ options,
780
+ apiUrl,
781
+ apiKey
782
+ })).unwrap();
783
+ return data.text;
784
+ } catch (e) {
785
+ return rejectWithValue(e.message || "Remote completing failed");
786
+ }
787
+ }
788
+ );
789
+ var cortexSlice = (0, import_toolkit5.createSlice)({
790
+ name: "cortex",
791
+ initialState: initialState4,
792
+ reducers: {
793
+ cortexInitStart: (state) => {
794
+ state.isInitializing = true;
795
+ state.error = void 0;
796
+ },
797
+ cortexInitSuccess: (state, action) => {
798
+ state.status = action.payload;
799
+ state.isInitializing = false;
800
+ state.error = void 0;
801
+ },
802
+ cortexInitFailed: (state, action) => {
803
+ state.isInitializing = false;
804
+ state.error = action.payload;
805
+ },
806
+ setCortexStatus: (state, action) => {
807
+ state.status = action.payload;
808
+ }
809
+ },
810
+ extraReducers: (builder) => {
811
+ builder.addCase(initRemoteCortexThunk.fulfilled, (state, action) => {
812
+ state.status = action.payload;
813
+ state.isInitializing = false;
814
+ }).addCase(completeRemoteThunk.rejected, (state, action) => {
815
+ state.error = action.payload;
816
+ });
817
+ }
818
+ });
819
+ var {
820
+ cortexInitStart,
821
+ cortexInitSuccess,
822
+ cortexInitFailed,
823
+ setCortexStatus
824
+ } = cortexSlice.actions;
825
+ var cortexSlice_default = cortexSlice.reducer;
826
+
827
+ // src/memorySlice.ts
828
+ var import_toolkit6 = require("@reduxjs/toolkit");
829
+ var memoryAdapter = (0, import_toolkit6.createEntityAdapter)();
830
+ var memorySlice = (0, import_toolkit6.createSlice)({
831
+ name: "memory",
832
+ initialState: memoryAdapter.getInitialState({
833
+ storageStatus: "idle",
834
+ recallStatus: "idle",
835
+ error: null,
836
+ lastRecalledIds: []
837
+ }),
838
+ reducers: {
839
+ memoryStoreStart: (state) => {
840
+ state.storageStatus = "storing";
841
+ state.error = null;
842
+ },
843
+ memoryStoreSuccess: (state, action) => {
844
+ state.storageStatus = "idle";
845
+ memoryAdapter.upsertOne(state, action.payload);
846
+ },
847
+ memoryStoreFailed: (state, action) => {
848
+ state.storageStatus = "error";
849
+ state.error = action.payload;
850
+ },
851
+ memoryRecallStart: (state) => {
852
+ state.recallStatus = "recalling";
853
+ state.error = null;
854
+ },
855
+ memoryRecallSuccess: (state, action) => {
856
+ state.recallStatus = "idle";
857
+ memoryAdapter.upsertMany(state, action.payload);
858
+ state.lastRecalledIds = action.payload.map((m) => memoryAdapter.selectId(m));
859
+ },
860
+ memoryRecallFailed: (state, action) => {
861
+ state.recallStatus = "error";
862
+ state.error = action.payload;
863
+ },
864
+ memoryClear: (state) => {
865
+ memoryAdapter.removeAll(state);
866
+ state.lastRecalledIds = [];
867
+ }
868
+ }
869
+ });
870
+ var {
871
+ memoryStoreStart,
872
+ memoryStoreSuccess,
873
+ memoryStoreFailed,
874
+ memoryRecallStart,
875
+ memoryRecallSuccess,
876
+ memoryRecallFailed,
877
+ memoryClear
878
+ } = memorySlice.actions;
879
+ var {
880
+ selectById: selectMemoryById,
881
+ selectAll: selectAllMemories
882
+ } = memoryAdapter.getSelectors((state) => state.memory);
883
+ var selectLastRecalledMemories = (state) => {
884
+ return state.memory.lastRecalledIds.map((id) => state.memory.entities[id]).filter(Boolean);
885
+ };
886
+ var memorySlice_default = memorySlice.reducer;
887
+
888
+ // src/listeners.ts
889
+ var import_toolkit7 = require("@reduxjs/toolkit");
890
+ var sdkListenerMiddleware = (0, import_toolkit7.createListenerMiddleware)();
891
+ var startAppListening = sdkListenerMiddleware.startListening.withTypes();
892
+ startAppListening({
893
+ actionCreator: removeNPC,
894
+ effect: async (action, listenerApi) => {
895
+ const state = listenerApi.getState();
896
+ if (action.payload === state.npc.activeNpcId) {
897
+ listenerApi.dispatch(memoryClear());
898
+ }
899
+ }
900
+ });
901
+
902
+ // src/store.ts
903
+ var createSDKStore = (extraReducers = {}) => {
904
+ return (0, import_toolkit8.configureStore)({
905
+ reducer: {
906
+ [sdkApi.reducerPath]: sdkApi.reducer,
907
+ npc: npcSlice_default,
908
+ cortex: cortexSlice_default,
909
+ memory: memorySlice_default,
910
+ ghost: ghostSlice_default,
911
+ soul: soulSlice_default,
912
+ bridge: bridgeSlice_default,
913
+ ...extraReducers
914
+ },
915
+ middleware: (getDefaultMiddleware) => getDefaultMiddleware({
916
+ serializableCheck: false
917
+ // Allow non-serializable for engine refs in specific slices if needed, though we try to keep them external
918
+ }).prepend(sdkListenerMiddleware.middleware).concat(sdkApi.middleware)
919
+ });
920
+ };
921
+ var store = createSDKStore();
922
+ var dispatch = store.dispatch;
923
+
924
+ // src/thunks.ts
925
+ var import_toolkit9 = require("@reduxjs/toolkit");
926
+ var processNPC = (0, import_toolkit9.createAsyncThunk)(
927
+ "npc/process",
928
+ async ({ npcId: argNpcId, text, context = {}, apiUrl, apiKey, memory, cortex, persona: argPersona }, { getState, dispatch: dispatch2 }) => {
929
+ const stateNpcId = selectActiveNpcId(getState());
930
+ const activeNpc = selectActiveNPC(getState());
931
+ const npcId = argNpcId || stateNpcId;
932
+ const persona = argPersona || activeNpc?.persona;
933
+ const currentState = activeNpc?.state || {};
934
+ if (argNpcId && argNpcId !== stateNpcId) {
935
+ dispatch2(setNPCInfo({ id: argNpcId, persona: persona || "Default" }));
936
+ }
937
+ const directiveResult = await dispatch2(
938
+ sdkApi.endpoints.postDirective.initiate({ npcId, request: { observation: text, npcState: currentState, context }, apiUrl, apiKey })
939
+ ).unwrap();
940
+ const recalledMemories = memory && directiveResult.memoryRecall ? await memory.recall(
941
+ directiveResult.memoryRecall.query,
942
+ directiveResult.memoryRecall.limit,
943
+ directiveResult.memoryRecall.threshold
944
+ ).then((mems) => mems.map((m) => ({ text: m.text, type: m.type, importance: m.importance }))).catch(() => []) : [];
945
+ const contextResult = await dispatch2(
946
+ sdkApi.endpoints.postContext.initiate({ npcId, request: { memories: recalledMemories, observation: text, npcState: currentState, persona: persona || "Default" }, apiUrl, apiKey })
947
+ ).unwrap();
948
+ let generatedText = "";
949
+ if (cortex) {
950
+ generatedText = await cortex.complete(contextResult.prompt, {
951
+ maxTokens: contextResult.constraints.maxTokens,
952
+ temperature: contextResult.constraints.temperature,
953
+ stop: contextResult.constraints.stop
954
+ });
955
+ } else {
956
+ const remoteResult = await dispatch2(sdkApi.endpoints.postCortexComplete.initiate({
957
+ cortexId: "remote",
958
+ // Or generic
959
+ prompt: contextResult.prompt,
960
+ options: contextResult.constraints,
961
+ apiUrl,
962
+ apiKey
963
+ })).unwrap();
964
+ generatedText = remoteResult.text || "";
965
+ }
966
+ const verdictResult = await dispatch2(
967
+ sdkApi.endpoints.postVerdict.initiate({ npcId, request: { generatedOutput: generatedText, observation: text, npcState: currentState }, apiUrl, apiKey })
968
+ ).unwrap();
969
+ if (!verdictResult.valid) {
970
+ dispatch2(blockAction({ id: npcId, reason: "Validation Failed" }));
971
+ return { dialogue: "... [Blocked]", action: { type: "BLOCKED", reason: "Validation Failed" } };
972
+ }
973
+ if (memory && verdictResult.memoryStore) {
974
+ for (const inst of verdictResult.memoryStore) {
975
+ await memory.store(inst.text, inst.type, inst.importance).catch((e) => console.warn("Memory store failed:", e));
976
+ }
977
+ }
978
+ if (verdictResult.stateDelta) {
979
+ dispatch2(updateNPCState({ id: npcId, delta: verdictResult.stateDelta }));
980
+ }
981
+ const action = verdictResult.action ? { ...verdictResult.action, signature: verdictResult.signature } : void 0;
982
+ dispatch2(setLastAction({ id: npcId, action }));
983
+ dispatch2(addToHistory({ id: npcId, role: "user", content: text }));
984
+ dispatch2(addToHistory({ id: npcId, role: "assistant", content: verdictResult.dialogue }));
985
+ return {
986
+ dialogue: verdictResult.dialogue,
987
+ action,
988
+ thought: verdictResult.dialogue
989
+ };
990
+ }
991
+ );
992
+ var speakNPC = (0, import_toolkit9.createAsyncThunk)(
993
+ "npc/speak",
994
+ async ({ npcId: argNpcId, text, context = {}, apiUrl, apiKey }, { getState, dispatch: dispatch2 }) => {
995
+ const stateNpcId = selectActiveNpcId(getState());
996
+ const activeNpc = selectActiveNPC(getState());
997
+ const npcId = argNpcId || stateNpcId;
998
+ const currentState = activeNpc?.state || {};
999
+ const data = await dispatch2(sdkApi.endpoints.postSpeak.initiate({
1000
+ npcId,
1001
+ request: { speakMessage: text, speakContext: context, speakNPCState: currentState },
1002
+ apiUrl,
1003
+ apiKey
1004
+ })).unwrap();
1005
+ if (data.speakHistory) {
1006
+ dispatch2(setHistory({ id: npcId, history: data.speakHistory }));
1007
+ }
1008
+ return data.speakReply;
1009
+ }
1010
+ );
1011
+ var dialogueNPC = (0, import_toolkit9.createAsyncThunk)(
1012
+ "npc/dialogue",
1013
+ async ({ npcId: argNpcId, text, context = [], apiUrl, apiKey }, { getState, dispatch: dispatch2 }) => {
1014
+ const stateNpcId = selectActiveNpcId(getState());
1015
+ const npcId = argNpcId || stateNpcId;
1016
+ const data = await dispatch2(sdkApi.endpoints.postDialogue.initiate({
1017
+ npcId,
1018
+ request: { diagMessage: text, diagContext: context },
1019
+ apiUrl,
1020
+ apiKey
1021
+ })).unwrap();
1022
+ return data.diagReply;
1023
+ }
1024
+ );
1025
+ var localExportSoulThunk = (0, import_toolkit9.createAsyncThunk)(
1026
+ "npc/localExportSoul",
1027
+ async ({ id, memory }, { getState }) => {
1028
+ const state = getState().npc;
1029
+ const npcId = id || state.activeNpcId;
1030
+ const npc = state.entities[npcId];
1031
+ if (!npc) throw new Error(`NPC ${npcId} not found`);
1032
+ const memories = memory ? await memory.export().catch(() => []) : [];
1033
+ return exportToSoul(npcId, "NPC", npc.persona, npc.state, memories);
1034
+ }
1035
+ );
534
1036
  // Annotate the CommonJS export names for ESM import in node:
535
1037
  0 && (module.exports = {
536
1038
  SDK_VERSION,
537
- createAgent,
538
- createBridge,
539
- createGhost,
1039
+ addToHistory,
1040
+ blockAction,
1041
+ bridgeSlice,
1042
+ clearBlock,
1043
+ clearBridgeValidation,
1044
+ clearGhostSession,
1045
+ clearSoulState,
1046
+ completeRemoteThunk,
1047
+ cortexInitFailed,
1048
+ cortexInitStart,
1049
+ cortexInitSuccess,
1050
+ cortexSlice,
540
1051
  createInitialState,
541
- createRemoteCortex,
542
- createSoul,
543
- createSoulInstance,
1052
+ createSDKStore,
544
1053
  delay,
545
- deserializeSoul,
546
- exportSoul,
1054
+ dialogueNPC,
1055
+ dispatch,
547
1056
  exportToSoul,
548
- fromSoul,
549
- getGhostHistory,
550
- getGhostResults,
551
- getGhostStatus,
552
- getSoulList,
553
- importSoulFromArweave,
554
- loadPreset,
1057
+ generateNPCId,
1058
+ getBridgeRulesThunk,
1059
+ getGhostHistoryThunk,
1060
+ getGhostResultsThunk,
1061
+ getGhostStatusThunk,
1062
+ getSoulListThunk,
1063
+ ghostSlice,
1064
+ importSoulFromArweaveThunk,
1065
+ initRemoteCortexThunk,
1066
+ loadBridgePresetThunk,
1067
+ localExportSoulThunk,
555
1068
  memoise,
556
1069
  memoiseAsync,
1070
+ memoryClear,
1071
+ memoryRecallFailed,
1072
+ memoryRecallStart,
1073
+ memoryRecallSuccess,
1074
+ memorySlice,
1075
+ memoryStoreFailed,
1076
+ memoryStoreStart,
1077
+ memoryStoreSuccess,
1078
+ npcSlice,
557
1079
  pipe,
558
- serializeSoul,
559
- startGhostSession,
560
- stopGhostSession,
1080
+ processNPC,
1081
+ remoteExportSoulThunk,
1082
+ removeNPC,
1083
+ sdkApi,
1084
+ selectActiveNPC,
1085
+ selectActiveNpcId,
1086
+ selectAllMemories,
1087
+ selectAllNPCs,
1088
+ selectLastRecalledMemories,
1089
+ selectMemoryById,
1090
+ selectNPCById,
1091
+ selectNPCEntities,
1092
+ selectNPCIds,
1093
+ selectTotalNPCs,
1094
+ setActiveNPC,
1095
+ setCortexStatus,
1096
+ setHistory,
1097
+ setLastAction,
1098
+ setNPCInfo,
1099
+ setNPCState,
1100
+ soulSlice,
1101
+ speakNPC,
1102
+ startGhostThunk,
1103
+ stopGhostThunk,
1104
+ store,
561
1105
  streamFromCortex,
562
1106
  streamFromCortexWithDelay,
563
1107
  streamToCallback,
564
1108
  streamToString,
565
- updateAgentState,
566
- validateAction,
567
- validateSoul,
568
- waitForGhostCompletion
1109
+ updateNPCState,
1110
+ updateNPCStateLocally,
1111
+ validateBridgeThunk
569
1112
  });