@forbocai/core 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -24,11 +24,15 @@ __export(index_exports, {
24
24
  addToHistory: () => addToHistory,
25
25
  blockAction: () => blockAction,
26
26
  bridgeSlice: () => bridgeSlice,
27
+ checkApiStatusThunk: () => checkApiStatusThunk,
27
28
  clearBlock: () => clearBlock,
28
29
  clearBridgeValidation: () => clearBridgeValidation,
30
+ clearDirectivesForNpc: () => clearDirectivesForNpc,
29
31
  clearGhostSession: () => clearGhostSession,
32
+ clearMemoryRemoteThunk: () => clearMemoryRemoteThunk,
30
33
  clearSoulState: () => clearSoulState,
31
34
  completeRemoteThunk: () => completeRemoteThunk,
35
+ contextComposed: () => contextComposed,
32
36
  cortexInitFailed: () => cortexInitFailed,
33
37
  cortexInitStart: () => cortexInitStart,
34
38
  cortexInitSuccess: () => cortexInitSuccess,
@@ -36,7 +40,11 @@ __export(index_exports, {
36
40
  createInitialState: () => createInitialState,
37
41
  createSDKStore: () => createSDKStore,
38
42
  delay: () => delay,
39
- dialogueNPC: () => dialogueNPC,
43
+ deleteRulesetThunk: () => deleteRulesetThunk,
44
+ directiveReceived: () => directiveReceived,
45
+ directiveRunFailed: () => directiveRunFailed,
46
+ directiveRunStarted: () => directiveRunStarted,
47
+ directiveSlice: () => directiveSlice,
40
48
  dispatch: () => dispatch,
41
49
  exportToSoul: () => exportToSoul,
42
50
  generateNPCId: () => generateNPCId,
@@ -46,8 +54,13 @@ __export(index_exports, {
46
54
  getGhostStatusThunk: () => getGhostStatusThunk,
47
55
  getSoulListThunk: () => getSoulListThunk,
48
56
  ghostSlice: () => ghostSlice,
57
+ importNpcFromSoulThunk: () => importNpcFromSoulThunk,
49
58
  importSoulFromArweaveThunk: () => importSoulFromArweaveThunk,
50
59
  initRemoteCortexThunk: () => initRemoteCortexThunk,
60
+ listCortexModelsThunk: () => listCortexModelsThunk,
61
+ listMemoryRemoteThunk: () => listMemoryRemoteThunk,
62
+ listRulePresetsThunk: () => listRulePresetsThunk,
63
+ listRulesetsThunk: () => listRulesetsThunk,
51
64
  loadBridgePresetThunk: () => loadBridgePresetThunk,
52
65
  localExportSoulThunk: () => localExportSoulThunk,
53
66
  memoise: () => memoise,
@@ -63,13 +76,19 @@ __export(index_exports, {
63
76
  npcSlice: () => npcSlice,
64
77
  pipe: () => pipe,
65
78
  processNPC: () => processNPC,
79
+ recallMemoryRemoteThunk: () => recallMemoryRemoteThunk,
80
+ registerRulesetThunk: () => registerRulesetThunk,
66
81
  remoteExportSoulThunk: () => remoteExportSoulThunk,
67
82
  removeNPC: () => removeNPC,
68
83
  sdkApi: () => sdkApi,
84
+ selectActiveDirective: () => selectActiveDirective,
85
+ selectActiveDirectiveId: () => selectActiveDirectiveId,
69
86
  selectActiveNPC: () => selectActiveNPC,
70
87
  selectActiveNpcId: () => selectActiveNpcId,
88
+ selectAllDirectives: () => selectAllDirectives,
71
89
  selectAllMemories: () => selectAllMemories,
72
90
  selectAllNPCs: () => selectAllNPCs,
91
+ selectDirectiveById: () => selectDirectiveById,
73
92
  selectLastRecalledMemories: () => selectLastRecalledMemories,
74
93
  selectMemoryById: () => selectMemoryById,
75
94
  selectNPCById: () => selectNPCById,
@@ -83,17 +102,19 @@ __export(index_exports, {
83
102
  setNPCInfo: () => setNPCInfo,
84
103
  setNPCState: () => setNPCState,
85
104
  soulSlice: () => soulSlice,
86
- speakNPC: () => speakNPC,
87
105
  startGhostThunk: () => startGhostThunk,
88
106
  stopGhostThunk: () => stopGhostThunk,
89
107
  store: () => store,
108
+ storeMemoryRemoteThunk: () => storeMemoryRemoteThunk,
90
109
  streamFromCortex: () => streamFromCortex,
91
110
  streamFromCortexWithDelay: () => streamFromCortexWithDelay,
92
111
  streamToCallback: () => streamToCallback,
93
112
  streamToString: () => streamToString,
94
113
  updateNPCState: () => updateNPCState,
95
114
  updateNPCStateLocally: () => updateNPCStateLocally,
96
- validateBridgeThunk: () => validateBridgeThunk
115
+ validateBridgeThunk: () => validateBridgeThunk,
116
+ verdictValidated: () => verdictValidated,
117
+ verifySoulThunk: () => verifySoulThunk
97
118
  });
98
119
  module.exports = __toCommonJS(index_exports);
99
120
 
@@ -125,9 +146,44 @@ var sdkApi = (0, import_query.createApi)({
125
146
  return headers;
126
147
  }
127
148
  }),
128
- tagTypes: ["NPC", "Memory", "Cortex", "Ghost", "Soul", "Bridge"],
149
+ tagTypes: ["NPC", "Memory", "Cortex", "Ghost", "Soul", "Bridge", "Rule"],
129
150
  endpoints: (builder) => ({
151
+ // Cortex Endpoints
152
+ getCortexModels: builder.query({
153
+ query: ({ apiUrl, apiKey }) => ({
154
+ url: `${apiUrl}/cortex/models`,
155
+ method: "GET",
156
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
157
+ }),
158
+ providesTags: ["Cortex"],
159
+ transformResponse: (response) => response || []
160
+ }),
161
+ postCortexInit: builder.mutation({
162
+ query: ({ request, apiUrl, apiKey }) => ({
163
+ url: `${apiUrl}/cortex/init`,
164
+ method: "POST",
165
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
166
+ body: request
167
+ }),
168
+ invalidatesTags: ["Cortex"],
169
+ transformResponse: (response) => response
170
+ }),
130
171
  // NPC Endpoints
172
+ /**
173
+ * User Story: As the SDK protocol loop, I need a single process endpoint
174
+ * that returns one atomic instruction per turn while echoing full tape state.
175
+ * ᚹ one hop in, one hop out, like passing a lit shard through vacuum.
176
+ */
177
+ postNpcProcess: builder.mutation({
178
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
179
+ url: `${apiUrl}/npcs/${npcId}/process`,
180
+ method: "POST",
181
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
182
+ body: request
183
+ }),
184
+ invalidatesTags: (result, error, { npcId }) => [{ type: "NPC", id: npcId }],
185
+ transformResponse: (response) => response
186
+ }),
131
187
  postDirective: builder.mutation({
132
188
  query: ({ npcId, request, apiUrl, apiKey }) => ({
133
189
  url: `${apiUrl}/npcs/${npcId}/directive`,
@@ -169,88 +225,214 @@ var sdkApi = (0, import_query.createApi)({
169
225
  };
170
226
  }
171
227
  }),
172
- postSpeak: builder.mutation({
228
+ postMemoryStore: builder.mutation({
173
229
  query: ({ npcId, request, apiUrl, apiKey }) => ({
174
- url: `${apiUrl}/npcs/${npcId}/speak`,
230
+ url: `${apiUrl}/npcs/${npcId}/memory`,
175
231
  method: "POST",
176
232
  headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
177
233
  body: request
178
234
  }),
179
- invalidatesTags: (result, error, { npcId }) => [{ type: "NPC", id: npcId }],
235
+ invalidatesTags: (result, error, { npcId }) => [{ type: "Memory", id: npcId }],
180
236
  transformResponse: (response) => response
181
237
  }),
182
- postDialogue: builder.mutation({
238
+ getMemoryList: builder.query({
239
+ query: ({ npcId, apiUrl, apiKey }) => ({
240
+ url: `${apiUrl}/npcs/${npcId}/memory`,
241
+ method: "GET",
242
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
243
+ }),
244
+ providesTags: (result, error, { npcId }) => [{ type: "Memory", id: npcId }],
245
+ transformResponse: (response) => response || []
246
+ }),
247
+ postMemoryRecall: builder.mutation({
183
248
  query: ({ npcId, request, apiUrl, apiKey }) => ({
184
- url: `${apiUrl}/npcs/${npcId}/dialogue`,
249
+ url: `${apiUrl}/npcs/${npcId}/memory/recall`,
185
250
  method: "POST",
186
251
  headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
187
252
  body: request
188
253
  }),
189
- invalidatesTags: (result, error, { npcId }) => [{ type: "NPC", id: npcId }],
254
+ invalidatesTags: (result, error, { npcId }) => [{ type: "Memory", id: npcId }],
255
+ transformResponse: (response) => response || []
256
+ }),
257
+ deleteMemoryClear: builder.mutation({
258
+ query: ({ npcId, apiUrl, apiKey }) => ({
259
+ url: `${apiUrl}/npcs/${npcId}/memory/clear`,
260
+ method: "DELETE",
261
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
262
+ }),
263
+ invalidatesTags: (result, error, { npcId }) => [{ type: "Memory", id: npcId }],
190
264
  transformResponse: (response) => response
191
265
  }),
192
266
  // Ghost Endpoints
193
267
  postGhostRun: builder.mutation({
194
- query: ({ request, apiUrl }) => ({ url: `${apiUrl}/ghost/run`, method: "POST", body: request }),
268
+ query: ({ request, apiUrl, apiKey }) => ({
269
+ url: `${apiUrl}/ghost/run`,
270
+ method: "POST",
271
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
272
+ body: request
273
+ }),
195
274
  invalidatesTags: ["Ghost"],
196
275
  transformResponse: (response) => response
197
276
  }),
198
277
  getGhostStatus: builder.query({
199
- query: ({ sessionId, apiUrl }) => ({ url: `${apiUrl}/ghost/${sessionId}/status`, method: "GET" }),
278
+ query: ({ sessionId, apiUrl, apiKey }) => ({
279
+ url: `${apiUrl}/ghost/${sessionId}/status`,
280
+ method: "GET",
281
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
282
+ }),
200
283
  providesTags: (result, error, { sessionId }) => [{ type: "Ghost", id: sessionId }],
201
284
  transformResponse: (response) => response
202
285
  }),
203
286
  getGhostResults: builder.query({
204
- query: ({ sessionId, apiUrl }) => ({ url: `${apiUrl}/ghost/${sessionId}/results`, method: "GET" }),
287
+ query: ({ sessionId, apiUrl, apiKey }) => ({
288
+ url: `${apiUrl}/ghost/${sessionId}/results`,
289
+ method: "GET",
290
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
291
+ }),
205
292
  providesTags: (result, error, { sessionId }) => [{ type: "Ghost", id: sessionId }],
206
293
  transformResponse: (response) => response
207
294
  }),
208
295
  postGhostStop: builder.mutation({
209
- query: ({ sessionId, apiUrl }) => ({ url: `${apiUrl}/ghost/${sessionId}/stop`, method: "POST" }),
296
+ query: ({ sessionId, apiUrl, apiKey }) => ({
297
+ url: `${apiUrl}/ghost/${sessionId}/stop`,
298
+ method: "POST",
299
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
300
+ }),
210
301
  invalidatesTags: (result, error, { sessionId }) => [{ type: "Ghost", id: sessionId }],
211
- transformResponse: (response) => ({ stopped: true })
302
+ transformResponse: (response) => ({
303
+ stopped: response?.stopStatus === "stopped",
304
+ stopStatus: response?.stopStatus,
305
+ stopSessionId: response?.stopSessionId
306
+ })
212
307
  }),
213
308
  getGhostHistory: builder.query({
214
- query: ({ limit, apiUrl }) => ({ url: `${apiUrl}/ghost/history?limit=${limit}`, method: "GET" }),
309
+ query: ({ limit, apiUrl, apiKey }) => ({
310
+ url: `${apiUrl}/ghost/history?limit=${limit}`,
311
+ method: "GET",
312
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
313
+ }),
215
314
  providesTags: ["Ghost"],
216
315
  transformResponse: (response) => response
217
316
  }),
218
317
  // Soul Endpoints
219
318
  postSoulExport: builder.mutation({
220
- query: ({ npcId, request, apiUrl }) => ({ url: `${apiUrl}/npcs/${npcId}/soul/export`, method: "POST", body: request }),
319
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
320
+ url: `${apiUrl}/npcs/${npcId}/soul/export`,
321
+ method: "POST",
322
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
323
+ body: request
324
+ }),
221
325
  invalidatesTags: ["Soul"],
222
326
  transformResponse: (response) => response
223
327
  }),
224
328
  getSoulImport: builder.query({
225
- query: ({ txId, apiUrl }) => ({ url: `${apiUrl}/souls/${txId}`, method: "GET" }),
329
+ query: ({ txId, apiUrl, apiKey }) => ({
330
+ url: `${apiUrl}/souls/${txId}`,
331
+ method: "GET",
332
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
333
+ }),
226
334
  providesTags: (result, error, { txId }) => [{ type: "Soul", id: txId }],
227
335
  transformResponse: (response) => response
228
336
  }),
229
337
  getSouls: builder.query({
230
- query: ({ limit, apiUrl }) => ({ url: `${apiUrl}/souls?limit=${limit}`, method: "GET" }),
338
+ query: ({ limit, apiUrl, apiKey }) => ({
339
+ url: `${apiUrl}/souls?limit=${limit}`,
340
+ method: "GET",
341
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
342
+ }),
231
343
  providesTags: ["Soul"],
232
344
  transformResponse: (response) => response
233
345
  }),
234
346
  // Bridge Endpoints
235
347
  postBridgeValidate: builder.mutation({
236
- query: ({ request, npcId, apiUrl }) => ({
348
+ query: ({ request, npcId, apiUrl, apiKey }) => ({
237
349
  url: npcId ? `${apiUrl}/bridge/validate/${npcId}` : `${apiUrl}/bridge/validate`,
238
350
  method: "POST",
351
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
239
352
  body: request
240
353
  }),
241
354
  invalidatesTags: ["Bridge"],
242
355
  transformResponse: (response) => response.brResult || response
243
356
  }),
244
357
  getBridgeRules: builder.query({
245
- query: ({ apiUrl }) => ({ url: `${apiUrl}/rules`, method: "GET" }),
358
+ query: ({ apiUrl, apiKey }) => ({
359
+ url: `${apiUrl}/bridge/rules`,
360
+ method: "GET",
361
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
362
+ }),
246
363
  providesTags: ["Bridge"],
247
364
  transformResponse: (response) => response
248
365
  }),
249
366
  postBridgePreset: builder.mutation({
250
- query: ({ presetName, apiUrl }) => ({ url: `${apiUrl}/rules/presets/${presetName}`, method: "POST" }),
367
+ query: ({ presetName, apiUrl, apiKey }) => ({
368
+ url: `${apiUrl}/rules/presets/${presetName}`,
369
+ method: "POST",
370
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
371
+ }),
251
372
  invalidatesTags: ["Bridge"],
252
373
  transformResponse: (response) => response
253
374
  }),
375
+ // Rules Endpoints
376
+ getRulesets: builder.query({
377
+ query: ({ apiUrl, apiKey }) => ({
378
+ url: `${apiUrl}/rules`,
379
+ method: "GET",
380
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
381
+ }),
382
+ providesTags: ["Rule"],
383
+ transformResponse: (response) => response || []
384
+ }),
385
+ getRulePresets: builder.query({
386
+ query: ({ apiUrl, apiKey }) => ({
387
+ url: `${apiUrl}/rules/presets`,
388
+ method: "GET",
389
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
390
+ }),
391
+ providesTags: ["Rule"],
392
+ transformResponse: (response) => response || []
393
+ }),
394
+ postRuleRegister: builder.mutation({
395
+ query: ({ request, apiUrl, apiKey }) => ({
396
+ url: `${apiUrl}/rules`,
397
+ method: "POST",
398
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
399
+ body: request
400
+ }),
401
+ invalidatesTags: ["Rule"],
402
+ transformResponse: (response) => response
403
+ }),
404
+ deleteRule: builder.mutation({
405
+ query: ({ rulesetId, apiUrl, apiKey }) => ({
406
+ url: `${apiUrl}/rules/${rulesetId}`,
407
+ method: "DELETE",
408
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
409
+ }),
410
+ invalidatesTags: ["Rule"],
411
+ transformResponse: (_response) => ({ deleted: true })
412
+ }),
413
+ // Additional Soul/NPC Endpoints
414
+ postSoulVerify: builder.mutation({
415
+ query: ({ txId, apiUrl, apiKey }) => ({
416
+ url: `${apiUrl}/souls/${txId}/verify`,
417
+ method: "POST",
418
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
419
+ }),
420
+ invalidatesTags: ["Soul"],
421
+ transformResponse: (response) => ({
422
+ valid: response.verifyValid ?? response.valid ?? false,
423
+ reason: response.verifyReason ?? response.reason
424
+ })
425
+ }),
426
+ postNpcImport: builder.mutation({
427
+ query: ({ request, apiUrl, apiKey }) => ({
428
+ url: `${apiUrl}/npcs/import`,
429
+ method: "POST",
430
+ headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
431
+ body: request
432
+ }),
433
+ invalidatesTags: ["NPC"],
434
+ transformResponse: (response) => response
435
+ }),
254
436
  // Cortex Remote Endpoint
255
437
  postCortexComplete: builder.mutation({
256
438
  query: ({ cortexId, prompt, options, apiUrl, apiKey }) => ({
@@ -273,19 +455,22 @@ var sdkApi = (0, import_query.createApi)({
273
455
  // src/bridgeSlice.ts
274
456
  var initialState = {
275
457
  activePresets: [],
458
+ availableRulesets: [],
459
+ availablePresetIds: [],
276
460
  lastValidation: null,
277
461
  status: "idle",
278
462
  error: null
279
463
  };
280
464
  var validateBridgeThunk = (0, import_toolkit.createAsyncThunk)(
281
465
  "bridge/validate",
282
- async ({ action, context, npcId, apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
466
+ async ({ action, context, npcId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
283
467
  try {
284
468
  const url = apiUrl || "https://api.forboc.ai";
285
469
  const data = await dispatch2(sdkApi.endpoints.postBridgeValidate.initiate({
286
470
  request: { action, context },
287
471
  npcId,
288
- apiUrl: url
472
+ apiUrl: url,
473
+ apiKey
289
474
  })).unwrap();
290
475
  return data;
291
476
  } catch (e) {
@@ -295,10 +480,10 @@ var validateBridgeThunk = (0, import_toolkit.createAsyncThunk)(
295
480
  );
296
481
  var loadBridgePresetThunk = (0, import_toolkit.createAsyncThunk)(
297
482
  "bridge/loadPreset",
298
- async ({ presetName, apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
483
+ async ({ presetName, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
299
484
  try {
300
485
  const url = apiUrl || "https://api.forboc.ai";
301
- return await dispatch2(sdkApi.endpoints.postBridgePreset.initiate({ presetName, apiUrl: url })).unwrap();
486
+ return await dispatch2(sdkApi.endpoints.postBridgePreset.initiate({ presetName, apiUrl: url, apiKey })).unwrap();
302
487
  } catch (e) {
303
488
  return rejectWithValue(e.message || "Failed to load preset");
304
489
  }
@@ -306,15 +491,59 @@ var loadBridgePresetThunk = (0, import_toolkit.createAsyncThunk)(
306
491
  );
307
492
  var getBridgeRulesThunk = (0, import_toolkit.createAsyncThunk)(
308
493
  "bridge/rules",
309
- async ({ apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
494
+ async ({ apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
310
495
  try {
311
496
  const url = apiUrl || "https://api.forboc.ai";
312
- return await dispatch2(sdkApi.endpoints.getBridgeRules.initiate({ apiUrl: url })).unwrap();
497
+ return await dispatch2(sdkApi.endpoints.getBridgeRules.initiate({ apiUrl: url, apiKey })).unwrap();
498
+ } catch (e) {
499
+ return rejectWithValue(e.message || "Failed to list bridge rules");
500
+ }
501
+ }
502
+ );
503
+ var listRulesetsThunk = (0, import_toolkit.createAsyncThunk)(
504
+ "bridge/listRulesets",
505
+ async ({ apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
506
+ try {
507
+ const url = apiUrl || "https://api.forboc.ai";
508
+ return await dispatch2(sdkApi.endpoints.getRulesets.initiate({ apiUrl: url, apiKey })).unwrap();
313
509
  } catch (e) {
314
510
  return rejectWithValue(e.message || "Failed to list rulesets");
315
511
  }
316
512
  }
317
513
  );
514
+ var listRulePresetsThunk = (0, import_toolkit.createAsyncThunk)(
515
+ "bridge/listRulePresets",
516
+ async ({ apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
517
+ try {
518
+ const url = apiUrl || "https://api.forboc.ai";
519
+ return await dispatch2(sdkApi.endpoints.getRulePresets.initiate({ apiUrl: url, apiKey })).unwrap();
520
+ } catch (e) {
521
+ return rejectWithValue(e.message || "Failed to list rule presets");
522
+ }
523
+ }
524
+ );
525
+ var registerRulesetThunk = (0, import_toolkit.createAsyncThunk)(
526
+ "bridge/registerRuleset",
527
+ async ({ ruleset, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
528
+ try {
529
+ const url = apiUrl || "https://api.forboc.ai";
530
+ return await dispatch2(sdkApi.endpoints.postRuleRegister.initiate({ request: ruleset, apiUrl: url, apiKey })).unwrap();
531
+ } catch (e) {
532
+ return rejectWithValue(e.message || "Failed to register ruleset");
533
+ }
534
+ }
535
+ );
536
+ var deleteRulesetThunk = (0, import_toolkit.createAsyncThunk)(
537
+ "bridge/deleteRuleset",
538
+ async ({ rulesetId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
539
+ try {
540
+ const url = apiUrl || "https://api.forboc.ai";
541
+ return await dispatch2(sdkApi.endpoints.deleteRule.initiate({ rulesetId, apiUrl: url, apiKey })).unwrap();
542
+ } catch (e) {
543
+ return rejectWithValue(e.message || "Failed to delete ruleset");
544
+ }
545
+ }
546
+ );
318
547
  var bridgeSlice = (0, import_toolkit.createSlice)({
319
548
  name: "bridge",
320
549
  initialState,
@@ -348,6 +577,10 @@ var bridgeSlice = (0, import_toolkit.createSlice)({
348
577
  state.status = "error";
349
578
  state.error = action.payload;
350
579
  }).addCase(getBridgeRulesThunk.fulfilled, (state, action) => {
580
+ }).addCase(listRulesetsThunk.fulfilled, (state, action) => {
581
+ state.availableRulesets = action.payload;
582
+ }).addCase(listRulePresetsThunk.fulfilled, (state, action) => {
583
+ state.availablePresetIds = action.payload;
351
584
  });
352
585
  }
353
586
  });
@@ -366,7 +599,7 @@ var initialState2 = {
366
599
  };
367
600
  var remoteExportSoulThunk = (0, import_toolkit2.createAsyncThunk)(
368
601
  "soul/export",
369
- async ({ npcId: argNpcId, apiUrl, memories = [] }, { getState, dispatch: dispatch2, rejectWithValue }) => {
602
+ async ({ npcId: argNpcId, apiUrl, apiKey, memories = [] }, { getState, dispatch: dispatch2, rejectWithValue }) => {
370
603
  try {
371
604
  const state = getState().npc;
372
605
  const npcId = argNpcId || state.activeNpcId;
@@ -376,7 +609,8 @@ var remoteExportSoulThunk = (0, import_toolkit2.createAsyncThunk)(
376
609
  const result = await dispatch2(sdkApi.endpoints.postSoulExport.initiate({
377
610
  npcId,
378
611
  request: { npcIdRef: npcId, persona: npc.persona || "NPC", npcState: npc.state },
379
- apiUrl: url
612
+ apiUrl: url,
613
+ apiKey
380
614
  })).unwrap();
381
615
  return {
382
616
  txId: result.txId,
@@ -390,10 +624,10 @@ var remoteExportSoulThunk = (0, import_toolkit2.createAsyncThunk)(
390
624
  );
391
625
  var importSoulFromArweaveThunk = (0, import_toolkit2.createAsyncThunk)(
392
626
  "soul/import",
393
- async ({ txId, apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
627
+ async ({ txId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
394
628
  try {
395
629
  const url = apiUrl || "https://api.forboc.ai";
396
- const data = await dispatch2(sdkApi.endpoints.getSoulImport.initiate({ txId, apiUrl: url })).unwrap();
630
+ const data = await dispatch2(sdkApi.endpoints.getSoulImport.initiate({ txId, apiUrl: url, apiKey })).unwrap();
397
631
  return data;
398
632
  } catch (e) {
399
633
  return rejectWithValue(e.message || "Soul import failed");
@@ -402,16 +636,42 @@ var importSoulFromArweaveThunk = (0, import_toolkit2.createAsyncThunk)(
402
636
  );
403
637
  var getSoulListThunk = (0, import_toolkit2.createAsyncThunk)(
404
638
  "soul/list",
405
- async ({ limit = 50, apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
639
+ async ({ limit = 50, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
406
640
  try {
407
641
  const url = apiUrl || "https://api.forboc.ai";
408
- const data = await dispatch2(sdkApi.endpoints.getSouls.initiate({ limit, apiUrl: url })).unwrap();
642
+ const data = await dispatch2(sdkApi.endpoints.getSouls.initiate({ limit, apiUrl: url, apiKey })).unwrap();
409
643
  return data.souls || [];
410
644
  } catch (e) {
411
645
  return rejectWithValue(e.message || "Failed to list souls");
412
646
  }
413
647
  }
414
648
  );
649
+ var verifySoulThunk = (0, import_toolkit2.createAsyncThunk)(
650
+ "soul/verify",
651
+ async ({ txId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
652
+ try {
653
+ const url = apiUrl || "https://api.forboc.ai";
654
+ return await dispatch2(sdkApi.endpoints.postSoulVerify.initiate({ txId, apiUrl: url, apiKey })).unwrap();
655
+ } catch (e) {
656
+ return rejectWithValue(e.message || "Soul verify failed");
657
+ }
658
+ }
659
+ );
660
+ var importNpcFromSoulThunk = (0, import_toolkit2.createAsyncThunk)(
661
+ "soul/importNpc",
662
+ async ({ txId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
663
+ try {
664
+ const url = apiUrl || "https://api.forboc.ai";
665
+ return await dispatch2(sdkApi.endpoints.postNpcImport.initiate({
666
+ request: { txIdRef: txId },
667
+ apiUrl: url,
668
+ apiKey
669
+ })).unwrap();
670
+ } catch (e) {
671
+ return rejectWithValue(e.message || "NPC import from soul failed");
672
+ }
673
+ }
674
+ );
415
675
  var soulSlice = (0, import_toolkit2.createSlice)({
416
676
  name: "soul",
417
677
  initialState: initialState2,
@@ -469,7 +729,8 @@ var startGhostThunk = (0, import_toolkit3.createAsyncThunk)(
469
729
  const apiUrl = config.apiUrl || "https://api.forboc.ai";
470
730
  const data = await dispatch2(sdkApi.endpoints.postGhostRun.initiate({
471
731
  request: { testSuite: config.testSuite, duration: config.duration ?? 300 },
472
- apiUrl
732
+ apiUrl,
733
+ apiKey: config.apiKey
473
734
  })).unwrap();
474
735
  return {
475
736
  sessionId: data.sessionId,
@@ -482,13 +743,13 @@ var startGhostThunk = (0, import_toolkit3.createAsyncThunk)(
482
743
  );
483
744
  var getGhostStatusThunk = (0, import_toolkit3.createAsyncThunk)(
484
745
  "ghost/status",
485
- async ({ sessionId, apiUrl }, { dispatch: dispatch2, getState, rejectWithValue }) => {
746
+ async ({ sessionId, apiUrl, apiKey }, { dispatch: dispatch2, getState, rejectWithValue }) => {
486
747
  try {
487
748
  const state = getState().ghost;
488
749
  const targetSession = sessionId || state.activeSessionId;
489
750
  if (!targetSession) throw new Error("No active Ghost session");
490
751
  const url = apiUrl || "https://api.forboc.ai";
491
- const data = await dispatch2(sdkApi.endpoints.getGhostStatus.initiate({ sessionId: targetSession, apiUrl: url })).unwrap();
752
+ const data = await dispatch2(sdkApi.endpoints.getGhostStatus.initiate({ sessionId: targetSession, apiUrl: url, apiKey })).unwrap();
492
753
  return {
493
754
  sessionId: data.ghostSessionId,
494
755
  status: data.ghostStatus,
@@ -504,13 +765,13 @@ var getGhostStatusThunk = (0, import_toolkit3.createAsyncThunk)(
504
765
  );
505
766
  var getGhostResultsThunk = (0, import_toolkit3.createAsyncThunk)(
506
767
  "ghost/results",
507
- async ({ sessionId, apiUrl }, { dispatch: dispatch2, getState, rejectWithValue }) => {
768
+ async ({ sessionId, apiUrl, apiKey }, { dispatch: dispatch2, getState, rejectWithValue }) => {
508
769
  try {
509
770
  const state = getState().ghost;
510
771
  const targetSession = sessionId || state.activeSessionId;
511
772
  if (!targetSession) throw new Error("No active Ghost session");
512
773
  const url = apiUrl || "https://api.forboc.ai";
513
- const data = await dispatch2(sdkApi.endpoints.getGhostResults.initiate({ sessionId: targetSession, apiUrl: url })).unwrap();
774
+ const data = await dispatch2(sdkApi.endpoints.getGhostResults.initiate({ sessionId: targetSession, apiUrl: url, apiKey })).unwrap();
514
775
  return {
515
776
  sessionId: data.resultsSessionId,
516
777
  totalTests: data.resultsTotalTests,
@@ -535,25 +796,29 @@ var getGhostResultsThunk = (0, import_toolkit3.createAsyncThunk)(
535
796
  );
536
797
  var stopGhostThunk = (0, import_toolkit3.createAsyncThunk)(
537
798
  "ghost/stop",
538
- async ({ sessionId, apiUrl }, { dispatch: dispatch2, getState, rejectWithValue }) => {
799
+ async ({ sessionId, apiUrl, apiKey }, { dispatch: dispatch2, getState, rejectWithValue }) => {
539
800
  try {
540
801
  const state = getState().ghost;
541
802
  const targetSession = sessionId || state.activeSessionId;
542
803
  if (!targetSession) throw new Error("No active Ghost session");
543
804
  const url = apiUrl || "https://api.forboc.ai";
544
- await dispatch2(sdkApi.endpoints.postGhostStop.initiate({ sessionId: targetSession, apiUrl: url })).unwrap();
545
- return { stopped: true };
805
+ const data = await dispatch2(sdkApi.endpoints.postGhostStop.initiate({ sessionId: targetSession, apiUrl: url, apiKey })).unwrap();
806
+ return {
807
+ stopped: data.stopped,
808
+ status: data.stopStatus,
809
+ sessionId: data.stopSessionId
810
+ };
546
811
  } catch (e) {
547
- return { stopped: true };
812
+ return rejectWithValue(e.message || "Failed to stop ghost session");
548
813
  }
549
814
  }
550
815
  );
551
816
  var getGhostHistoryThunk = (0, import_toolkit3.createAsyncThunk)(
552
817
  "ghost/history",
553
- async ({ limit = 10, apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
818
+ async ({ limit = 10, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
554
819
  try {
555
820
  const url = apiUrl || "https://api.forboc.ai";
556
- const data = await dispatch2(sdkApi.endpoints.getGhostHistory.initiate({ limit, apiUrl: url })).unwrap();
821
+ const data = await dispatch2(sdkApi.endpoints.getGhostHistory.initiate({ limit, apiUrl: url, apiKey })).unwrap();
557
822
  return (data.sessions || []).map((s) => ({
558
823
  sessionId: s.sessionId,
559
824
  testSuite: s.testSuite,
@@ -596,8 +861,14 @@ var ghostSlice = (0, import_toolkit3.createSlice)({
596
861
  }).addCase(getGhostResultsThunk.fulfilled, (state, action) => {
597
862
  state.results = action.payload;
598
863
  state.status = "completed";
599
- }).addCase(stopGhostThunk.fulfilled, (state) => {
600
- state.status = "failed";
864
+ }).addCase(stopGhostThunk.fulfilled, (state, action) => {
865
+ if (action.payload.stopped) {
866
+ state.status = "failed";
867
+ } else {
868
+ state.error = action.payload.status || "Ghost stop request did not stop a session";
869
+ }
870
+ }).addCase(stopGhostThunk.rejected, (state, action) => {
871
+ state.error = action.payload;
601
872
  }).addCase(getGhostHistoryThunk.fulfilled, (state, action) => {
602
873
  state.history = action.payload;
603
874
  });
@@ -606,11 +877,19 @@ var ghostSlice = (0, import_toolkit3.createSlice)({
606
877
  var { clearGhostSession } = ghostSlice.actions;
607
878
  var ghostSlice_default = ghostSlice.reducer;
608
879
 
609
- // src/utils.ts
610
- var SDK_VERSION = "0.5.9";
880
+ // src/utils/sdkVersion.ts
881
+ var SDK_VERSION = "0.6.1";
882
+
883
+ // src/utils/generateNPCId.ts
611
884
  var generateNPCId = () => `ag_${Date.now().toString(36)}`;
885
+
886
+ // src/utils/delay.ts
612
887
  var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
888
+
889
+ // src/utils/pipe.ts
613
890
  var pipe = (...fns) => (initialValue) => fns.reduce((acc, fn) => fn(acc), initialValue);
891
+
892
+ // src/utils/memoiseAsync.ts
614
893
  var memoiseAsync = (fn) => {
615
894
  let cached = null;
616
895
  let promise = null;
@@ -624,6 +903,8 @@ var memoiseAsync = (fn) => {
624
903
  return promise;
625
904
  };
626
905
  };
906
+
907
+ // src/utils/memoise.ts
627
908
  var memoise = (fn) => {
628
909
  let cached = null;
629
910
  let initialized = false;
@@ -660,7 +941,7 @@ var streamFromCortexWithDelay = async (cortex, prompt, onChunk, options) => {
660
941
  };
661
942
 
662
943
  // src/store.ts
663
- var import_toolkit8 = require("@reduxjs/toolkit");
944
+ var import_toolkit9 = require("@reduxjs/toolkit");
664
945
 
665
946
  // src/npcSlice.ts
666
947
  var import_toolkit4 = require("@reduxjs/toolkit");
@@ -760,13 +1041,34 @@ var initialState4 = {
760
1041
  };
761
1042
  var initRemoteCortexThunk = (0, import_toolkit5.createAsyncThunk)(
762
1043
  "cortex/initRemote",
763
- async ({ model = "api-integrated" }) => {
764
- return {
765
- id: `remote_${Date.now()}`,
766
- model,
767
- ready: true,
768
- engine: "remote"
769
- };
1044
+ async ({ model = "api-integrated", authKey, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
1045
+ try {
1046
+ const url = apiUrl || "https://api.forboc.ai";
1047
+ const data = await dispatch2(sdkApi.endpoints.postCortexInit.initiate({
1048
+ request: { requestedModel: model, authKey },
1049
+ apiUrl: url,
1050
+ apiKey
1051
+ })).unwrap();
1052
+ return {
1053
+ id: data.cortexId,
1054
+ model,
1055
+ ready: data.state?.toLowerCase() === "ready",
1056
+ engine: "remote"
1057
+ };
1058
+ } catch (e) {
1059
+ return rejectWithValue(e.message || "Remote cortex init failed");
1060
+ }
1061
+ }
1062
+ );
1063
+ var listCortexModelsThunk = (0, import_toolkit5.createAsyncThunk)(
1064
+ "cortex/listModels",
1065
+ async ({ apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
1066
+ try {
1067
+ const url = apiUrl || "https://api.forboc.ai";
1068
+ return await dispatch2(sdkApi.endpoints.getCortexModels.initiate({ apiUrl: url, apiKey })).unwrap();
1069
+ } catch (e) {
1070
+ return rejectWithValue(e.message || "Failed to list cortex models");
1071
+ }
770
1072
  }
771
1073
  );
772
1074
  var completeRemoteThunk = (0, import_toolkit5.createAsyncThunk)(
@@ -885,15 +1187,108 @@ var selectLastRecalledMemories = (state) => {
885
1187
  };
886
1188
  var memorySlice_default = memorySlice.reducer;
887
1189
 
888
- // src/listeners.ts
1190
+ // src/directiveSlice.ts
889
1191
  var import_toolkit7 = require("@reduxjs/toolkit");
890
- var sdkListenerMiddleware = (0, import_toolkit7.createListenerMiddleware)();
1192
+ var directiveAdapter = (0, import_toolkit7.createEntityAdapter)();
1193
+ var directiveSlice = (0, import_toolkit7.createSlice)({
1194
+ name: "directive",
1195
+ initialState: directiveAdapter.getInitialState({
1196
+ activeDirectiveId: ""
1197
+ }),
1198
+ reducers: {
1199
+ directiveRunStarted: (state, action) => {
1200
+ const { id, npcId, observation } = action.payload;
1201
+ directiveAdapter.upsertOne(state, {
1202
+ id,
1203
+ npcId,
1204
+ observation,
1205
+ status: "running",
1206
+ startedAt: Date.now()
1207
+ });
1208
+ state.activeDirectiveId = id;
1209
+ },
1210
+ directiveReceived: (state, action) => {
1211
+ const { id, response } = action.payload;
1212
+ directiveAdapter.updateOne(state, {
1213
+ id,
1214
+ changes: { memoryRecall: response.memoryRecall }
1215
+ });
1216
+ },
1217
+ contextComposed: (state, action) => {
1218
+ const { id, prompt, constraints } = action.payload;
1219
+ directiveAdapter.updateOne(state, {
1220
+ id,
1221
+ changes: { contextPrompt: prompt, contextConstraints: constraints }
1222
+ });
1223
+ },
1224
+ verdictValidated: (state, action) => {
1225
+ const { id, verdict } = action.payload;
1226
+ directiveAdapter.updateOne(state, {
1227
+ id,
1228
+ changes: {
1229
+ status: "completed",
1230
+ completedAt: Date.now(),
1231
+ verdictValid: verdict.valid,
1232
+ verdictDialogue: verdict.dialogue,
1233
+ verdictActionType: verdict.action?.type
1234
+ }
1235
+ });
1236
+ },
1237
+ directiveRunFailed: (state, action) => {
1238
+ const { id, error } = action.payload;
1239
+ directiveAdapter.updateOne(state, {
1240
+ id,
1241
+ changes: {
1242
+ status: "failed",
1243
+ completedAt: Date.now(),
1244
+ error
1245
+ }
1246
+ });
1247
+ },
1248
+ clearDirectivesForNpc: (state, action) => {
1249
+ const npcId = action.payload;
1250
+ const idsToRemove = Object.values(state.entities).filter((item) => Boolean(item)).filter((item) => item.npcId === npcId).map((item) => item.id);
1251
+ directiveAdapter.removeMany(state, idsToRemove);
1252
+ if (idsToRemove.includes(state.activeDirectiveId)) {
1253
+ state.activeDirectiveId = "";
1254
+ }
1255
+ }
1256
+ }
1257
+ });
1258
+ var {
1259
+ directiveRunStarted,
1260
+ directiveReceived,
1261
+ contextComposed,
1262
+ verdictValidated,
1263
+ directiveRunFailed,
1264
+ clearDirectivesForNpc
1265
+ } = directiveSlice.actions;
1266
+ var {
1267
+ selectById: selectDirectiveById,
1268
+ selectAll: selectAllDirectives
1269
+ } = directiveAdapter.getSelectors((state) => state.directive);
1270
+ var selectActiveDirectiveId = (state) => state.directive.activeDirectiveId;
1271
+ var selectActiveDirective = (state) => {
1272
+ const id = selectActiveDirectiveId(state);
1273
+ return state.directive.entities[id];
1274
+ };
1275
+ var directiveSlice_default = directiveSlice.reducer;
1276
+
1277
+ // src/listeners.ts
1278
+ var import_toolkit8 = require("@reduxjs/toolkit");
1279
+ var sdkListenerMiddleware = (0, import_toolkit8.createListenerMiddleware)();
891
1280
  var startAppListening = sdkListenerMiddleware.startListening.withTypes();
892
1281
  startAppListening({
893
1282
  actionCreator: removeNPC,
894
1283
  effect: async (action, listenerApi) => {
1284
+ const removedNpcId = action.payload;
895
1285
  const state = listenerApi.getState();
896
- if (action.payload === state.npc.activeNpcId) {
1286
+ listenerApi.dispatch(clearDirectivesForNpc(removedNpcId));
1287
+ listenerApi.dispatch(clearBridgeValidation());
1288
+ listenerApi.dispatch(clearGhostSession());
1289
+ listenerApi.dispatch(clearSoulState());
1290
+ listenerApi.dispatch(clearBlock(removedNpcId));
1291
+ if (removedNpcId === state.npc.activeNpcId) {
897
1292
  listenerApi.dispatch(memoryClear());
898
1293
  }
899
1294
  }
@@ -901,12 +1296,13 @@ startAppListening({
901
1296
 
902
1297
  // src/store.ts
903
1298
  var createSDKStore = (extraReducers = {}) => {
904
- return (0, import_toolkit8.configureStore)({
1299
+ return (0, import_toolkit9.configureStore)({
905
1300
  reducer: {
906
1301
  [sdkApi.reducerPath]: sdkApi.reducer,
907
1302
  npc: npcSlice_default,
908
1303
  cortex: cortexSlice_default,
909
1304
  memory: memorySlice_default,
1305
+ directive: directiveSlice_default,
910
1306
  ghost: ghostSlice_default,
911
1307
  soul: soulSlice_default,
912
1308
  bridge: bridgeSlice_default,
@@ -922,128 +1318,241 @@ var store = createSDKStore();
922
1318
  var dispatch = store.dispatch;
923
1319
 
924
1320
  // src/thunks.ts
925
- var import_toolkit9 = require("@reduxjs/toolkit");
926
- var processNPC = (0, import_toolkit9.createAsyncThunk)(
1321
+ var import_toolkit10 = require("@reduxjs/toolkit");
1322
+ var extractThunkErrorMessage = (e) => {
1323
+ if (typeof e === "string") return e;
1324
+ if (e?.data?.message) return String(e.data.message);
1325
+ if (e?.error) return String(e.error);
1326
+ if (e?.message) return String(e.message);
1327
+ return "Protocol processing failed";
1328
+ };
1329
+ var processNPC = (0, import_toolkit10.createAsyncThunk)(
927
1330
  "npc/process",
928
- async ({ npcId: argNpcId, text, context = {}, apiUrl, apiKey, memory, cortex, persona: argPersona }, { getState, dispatch: dispatch2 }) => {
1331
+ async ({ npcId: argNpcId, text, context = {}, apiUrl, apiKey, memory, cortex, persona: argPersona }, { getState, dispatch: dispatch2, rejectWithValue }) => {
929
1332
  const stateNpcId = selectActiveNpcId(getState());
930
1333
  const activeNpc = selectActiveNPC(getState());
931
1334
  const npcId = argNpcId || stateNpcId;
932
1335
  const persona = argPersona || activeNpc?.persona;
933
1336
  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 || "";
1337
+ if (!npcId) {
1338
+ return rejectWithValue("No npcId provided and no active NPC selected");
965
1339
  }
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" } };
1340
+ if (!persona) {
1341
+ return rejectWithValue("No persona provided and no active NPC persona available");
972
1342
  }
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
- }
1343
+ if (!cortex) {
1344
+ return rejectWithValue("No local cortex provided. SDK remote cortex fallback is disabled.");
977
1345
  }
978
- if (verdictResult.stateDelta) {
979
- dispatch2(updateNPCState({ id: npcId, delta: verdictResult.stateDelta }));
1346
+ if (argNpcId && argNpcId !== stateNpcId) {
1347
+ dispatch2(setNPCInfo({ id: argNpcId, persona }));
980
1348
  }
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 }));
1349
+ const directiveId = `${npcId}:${Date.now()}`;
1350
+ dispatch2(directiveRunStarted({ id: directiveId, npcId, observation: text }));
1351
+ try {
1352
+ const initialTape = {
1353
+ observation: text,
1354
+ context,
1355
+ npcState: currentState,
1356
+ persona,
1357
+ memories: [],
1358
+ vectorQueried: false
1359
+ };
1360
+ const maxTurns = 12;
1361
+ const persistMemoryInstructionsRecursively = async (instructions, index = 0) => {
1362
+ if (!memory || index >= instructions.length) {
1363
+ return;
1364
+ }
1365
+ const inst = instructions[index];
1366
+ await memory.store(inst.text, inst.type, inst.importance);
1367
+ await persistMemoryInstructionsRecursively(instructions, index + 1);
1368
+ };
1369
+ const runProtocolRecursively = async (tape, lastResult, turn) => {
1370
+ if (turn >= maxTurns) {
1371
+ return rejectWithValue(`Protocol loop exceeded max turns (${maxTurns})`);
1372
+ }
1373
+ const request = { tape, lastResult };
1374
+ const processResult = await dispatch2(
1375
+ sdkApi.endpoints.postNpcProcess.initiate({ npcId, request, apiUrl, apiKey })
1376
+ ).unwrap();
1377
+ const nextTape = processResult.tape;
1378
+ const instruction = processResult.instruction;
1379
+ if (instruction.type === "IdentifyActor") {
1380
+ return runProtocolRecursively(nextTape, {
1381
+ type: "IdentifyActorResult",
1382
+ actor: {
1383
+ npcId,
1384
+ persona,
1385
+ data: nextTape.npcState
1386
+ }
1387
+ }, turn + 1);
1388
+ }
1389
+ if (instruction.type === "QueryVector") {
1390
+ dispatch2(directiveReceived({
1391
+ id: directiveId,
1392
+ response: { memoryRecall: { query: instruction.query, limit: instruction.limit, threshold: instruction.threshold } }
1393
+ }));
1394
+ if (!memory) {
1395
+ return rejectWithValue("API requested memory recall, but no memory engine is configured");
1396
+ }
1397
+ const recalled = await memory.recall(instruction.query, instruction.limit, instruction.threshold);
1398
+ return runProtocolRecursively(nextTape, {
1399
+ type: "QueryVectorResult",
1400
+ memories: recalled.map((m) => ({ text: m.text, type: m.type, importance: m.importance, similarity: m.similarity }))
1401
+ }, turn + 1);
1402
+ }
1403
+ if (instruction.type === "ExecuteInference") {
1404
+ dispatch2(contextComposed({ id: directiveId, prompt: instruction.prompt, constraints: instruction.constraints }));
1405
+ const generatedText = await cortex.complete(instruction.prompt, {
1406
+ maxTokens: instruction.constraints.maxTokens,
1407
+ temperature: instruction.constraints.temperature,
1408
+ stop: instruction.constraints.stop
1409
+ });
1410
+ return runProtocolRecursively(nextTape, {
1411
+ type: "ExecuteInferenceResult",
1412
+ generatedOutput: generatedText
1413
+ }, turn + 1);
1414
+ }
1415
+ if (instruction.type === "Finalize") {
1416
+ const finalize = instruction;
1417
+ dispatch2(verdictValidated({
1418
+ id: directiveId,
1419
+ verdict: {
1420
+ valid: finalize.valid,
1421
+ signature: finalize.signature,
1422
+ memoryStore: finalize.memoryStore,
1423
+ stateDelta: finalize.stateTransform,
1424
+ action: finalize.action,
1425
+ dialogue: finalize.dialogue
1426
+ }
1427
+ }));
1428
+ if (!finalize.valid) {
1429
+ dispatch2(blockAction({ id: npcId, reason: finalize.dialogue || "Validation Failed" }));
1430
+ return {
1431
+ dialogue: finalize.dialogue,
1432
+ action: finalize.action,
1433
+ thought: finalize.dialogue
1434
+ };
1435
+ }
1436
+ if (finalize.memoryStore?.length && !memory) {
1437
+ return rejectWithValue("API returned memoryStore instructions, but no memory engine is configured");
1438
+ }
1439
+ await persistMemoryInstructionsRecursively(finalize.memoryStore || []);
1440
+ if (finalize.stateTransform) {
1441
+ dispatch2(updateNPCState({ id: npcId, delta: finalize.stateTransform }));
1442
+ }
1443
+ dispatch2(setLastAction({ id: npcId, action: finalize.action }));
1444
+ dispatch2(addToHistory({ id: npcId, role: "user", content: text }));
1445
+ dispatch2(addToHistory({ id: npcId, role: "assistant", content: finalize.dialogue }));
1446
+ return {
1447
+ dialogue: finalize.dialogue,
1448
+ action: finalize.action,
1449
+ thought: finalize.dialogue
1450
+ };
1451
+ }
1452
+ return rejectWithValue("API returned unknown instruction type");
1453
+ };
1454
+ return runProtocolRecursively(initialTape, void 0, 0);
1455
+ } catch (e) {
1456
+ const message = extractThunkErrorMessage(e);
1457
+ dispatch2(directiveRunFailed({ id: directiveId, error: String(message) }));
1458
+ return rejectWithValue(String(message));
1007
1459
  }
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
1460
  }
1024
1461
  );
1025
- var localExportSoulThunk = (0, import_toolkit9.createAsyncThunk)(
1462
+ var localExportSoulThunk = (0, import_toolkit10.createAsyncThunk)(
1026
1463
  "npc/localExportSoul",
1027
1464
  async ({ id, memory }, { getState }) => {
1028
1465
  const state = getState().npc;
1029
1466
  const npcId = id || state.activeNpcId;
1030
1467
  const npc = state.entities[npcId];
1031
1468
  if (!npc) throw new Error(`NPC ${npcId} not found`);
1032
- const memories = memory ? await memory.export().catch(() => []) : [];
1469
+ const memories = memory ? await memory.export() : [];
1033
1470
  return exportToSoul(npcId, "NPC", npc.persona, npc.state, memories);
1034
1471
  }
1035
1472
  );
1473
+ var checkApiStatusThunk = (0, import_toolkit10.createAsyncThunk)(
1474
+ "system/checkApiStatus",
1475
+ async ({ apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
1476
+ try {
1477
+ return await dispatch2(sdkApi.endpoints.getApiStatus.initiate({ apiUrl })).unwrap();
1478
+ } catch (e) {
1479
+ return rejectWithValue(e?.message || "Connection failed");
1480
+ }
1481
+ }
1482
+ );
1483
+ var listMemoryRemoteThunk = (0, import_toolkit10.createAsyncThunk)(
1484
+ "memory/listRemote",
1485
+ async ({ npcId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
1486
+ try {
1487
+ const data = await dispatch2(sdkApi.endpoints.getMemoryList.initiate({ npcId, apiUrl, apiKey })).unwrap();
1488
+ return data || [];
1489
+ } catch (e) {
1490
+ return rejectWithValue(e?.message || "Failed to list memories");
1491
+ }
1492
+ }
1493
+ );
1494
+ var recallMemoryRemoteThunk = (0, import_toolkit10.createAsyncThunk)(
1495
+ "memory/recallRemote",
1496
+ async ({ npcId, query, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
1497
+ try {
1498
+ const data = await dispatch2(
1499
+ sdkApi.endpoints.postMemoryRecall.initiate({
1500
+ npcId,
1501
+ request: { query },
1502
+ apiUrl,
1503
+ apiKey
1504
+ })
1505
+ ).unwrap();
1506
+ return data || [];
1507
+ } catch (e) {
1508
+ return rejectWithValue(e?.message || "Failed to recall memories");
1509
+ }
1510
+ }
1511
+ );
1512
+ var storeMemoryRemoteThunk = (0, import_toolkit10.createAsyncThunk)(
1513
+ "memory/storeRemote",
1514
+ async ({ npcId, observation, importance = 0.8, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
1515
+ try {
1516
+ return await dispatch2(
1517
+ sdkApi.endpoints.postMemoryStore.initiate({
1518
+ npcId,
1519
+ request: { observation, importance },
1520
+ apiUrl,
1521
+ apiKey
1522
+ })
1523
+ ).unwrap();
1524
+ } catch (e) {
1525
+ return rejectWithValue(e?.message || "Failed to store memory");
1526
+ }
1527
+ }
1528
+ );
1529
+ var clearMemoryRemoteThunk = (0, import_toolkit10.createAsyncThunk)(
1530
+ "memory/clearRemote",
1531
+ async ({ npcId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
1532
+ try {
1533
+ return await dispatch2(
1534
+ sdkApi.endpoints.deleteMemoryClear.initiate({ npcId, apiUrl, apiKey })
1535
+ ).unwrap();
1536
+ } catch (e) {
1537
+ return rejectWithValue(e?.message || "Failed to clear memories");
1538
+ }
1539
+ }
1540
+ );
1036
1541
  // Annotate the CommonJS export names for ESM import in node:
1037
1542
  0 && (module.exports = {
1038
1543
  SDK_VERSION,
1039
1544
  addToHistory,
1040
1545
  blockAction,
1041
1546
  bridgeSlice,
1547
+ checkApiStatusThunk,
1042
1548
  clearBlock,
1043
1549
  clearBridgeValidation,
1550
+ clearDirectivesForNpc,
1044
1551
  clearGhostSession,
1552
+ clearMemoryRemoteThunk,
1045
1553
  clearSoulState,
1046
1554
  completeRemoteThunk,
1555
+ contextComposed,
1047
1556
  cortexInitFailed,
1048
1557
  cortexInitStart,
1049
1558
  cortexInitSuccess,
@@ -1051,7 +1560,11 @@ var localExportSoulThunk = (0, import_toolkit9.createAsyncThunk)(
1051
1560
  createInitialState,
1052
1561
  createSDKStore,
1053
1562
  delay,
1054
- dialogueNPC,
1563
+ deleteRulesetThunk,
1564
+ directiveReceived,
1565
+ directiveRunFailed,
1566
+ directiveRunStarted,
1567
+ directiveSlice,
1055
1568
  dispatch,
1056
1569
  exportToSoul,
1057
1570
  generateNPCId,
@@ -1061,8 +1574,13 @@ var localExportSoulThunk = (0, import_toolkit9.createAsyncThunk)(
1061
1574
  getGhostStatusThunk,
1062
1575
  getSoulListThunk,
1063
1576
  ghostSlice,
1577
+ importNpcFromSoulThunk,
1064
1578
  importSoulFromArweaveThunk,
1065
1579
  initRemoteCortexThunk,
1580
+ listCortexModelsThunk,
1581
+ listMemoryRemoteThunk,
1582
+ listRulePresetsThunk,
1583
+ listRulesetsThunk,
1066
1584
  loadBridgePresetThunk,
1067
1585
  localExportSoulThunk,
1068
1586
  memoise,
@@ -1078,13 +1596,19 @@ var localExportSoulThunk = (0, import_toolkit9.createAsyncThunk)(
1078
1596
  npcSlice,
1079
1597
  pipe,
1080
1598
  processNPC,
1599
+ recallMemoryRemoteThunk,
1600
+ registerRulesetThunk,
1081
1601
  remoteExportSoulThunk,
1082
1602
  removeNPC,
1083
1603
  sdkApi,
1604
+ selectActiveDirective,
1605
+ selectActiveDirectiveId,
1084
1606
  selectActiveNPC,
1085
1607
  selectActiveNpcId,
1608
+ selectAllDirectives,
1086
1609
  selectAllMemories,
1087
1610
  selectAllNPCs,
1611
+ selectDirectiveById,
1088
1612
  selectLastRecalledMemories,
1089
1613
  selectMemoryById,
1090
1614
  selectNPCById,
@@ -1098,15 +1622,17 @@ var localExportSoulThunk = (0, import_toolkit9.createAsyncThunk)(
1098
1622
  setNPCInfo,
1099
1623
  setNPCState,
1100
1624
  soulSlice,
1101
- speakNPC,
1102
1625
  startGhostThunk,
1103
1626
  stopGhostThunk,
1104
1627
  store,
1628
+ storeMemoryRemoteThunk,
1105
1629
  streamFromCortex,
1106
1630
  streamFromCortexWithDelay,
1107
1631
  streamToCallback,
1108
1632
  streamToString,
1109
1633
  updateNPCState,
1110
1634
  updateNPCStateLocally,
1111
- validateBridgeThunk
1635
+ validateBridgeThunk,
1636
+ verdictValidated,
1637
+ verifySoulThunk
1112
1638
  });