@forbocai/core 0.6.2 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -18,320 +18,461 @@ import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
18
18
 
19
19
  // src/apiSlice.ts
20
20
  import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query";
21
- var sdkApi = createApi({
22
- reducerPath: "forbocApi",
23
- baseQuery: fetchBaseQuery({
24
- baseUrl: "/",
25
- prepareHeaders: (headers, { getState }) => {
26
- return headers;
27
- }
21
+
22
+ // src/api/endpoints/arweave.ts
23
+ var buildArweaveEndpoints = (builder) => ({
24
+ postArweaveUpload: builder.mutation({
25
+ queryFn: async (instruction) => {
26
+ const maxRetries = instruction.maxRetries ?? 3;
27
+ const headers = {
28
+ "Content-Type": instruction.auiContentType || "application/json"
29
+ };
30
+ const walletToken = typeof globalThis !== "undefined" ? globalThis.process?.env?.ARWEAVE_WALLET_JWK ?? null : null;
31
+ const authToken = instruction.auiAuthHeader ?? (walletToken ? `Bearer ${walletToken}` : null);
32
+ if (authToken) headers.Authorization = authToken;
33
+ const attempt = async (n) => {
34
+ try {
35
+ const controller = new AbortController();
36
+ const timeout = setTimeout(() => controller.abort(), 6e4);
37
+ const response = await fetch(instruction.auiEndpoint, {
38
+ method: "POST",
39
+ headers,
40
+ body: JSON.stringify(instruction.auiPayload),
41
+ signal: controller.signal
42
+ });
43
+ clearTimeout(timeout);
44
+ const responseBody = await response.json().catch(() => null);
45
+ const txId = responseBody?.id ?? `ar_tx_sdk_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
46
+ const success = response.status >= 200 && response.status < 300;
47
+ return !success && n + 1 < maxRetries ? new Promise((resolve) => setTimeout(() => resolve(attempt(n + 1)), 250 * 2 ** n)) : {
48
+ data: {
49
+ aurTxId: txId,
50
+ aurStatus: response.status,
51
+ aurSuccess: success,
52
+ aurError: success ? null : `upload_failed_status_${response.status}`
53
+ }
54
+ };
55
+ } catch (error) {
56
+ const message = error instanceof Error ? error.message : String(error);
57
+ return n + 1 < maxRetries ? new Promise((resolve) => setTimeout(() => resolve(attempt(n + 1)), 250 * 2 ** n)) : {
58
+ data: {
59
+ aurTxId: `ar_tx_failed_${Date.now()}`,
60
+ aurStatus: 0,
61
+ aurSuccess: false,
62
+ aurError: `upload_request_failed:${message}`
63
+ }
64
+ };
65
+ }
66
+ };
67
+ return attempt(0);
68
+ },
69
+ invalidatesTags: ["Soul"]
28
70
  }),
29
- tagTypes: ["NPC", "Memory", "Cortex", "Ghost", "Soul", "Bridge", "Rule"],
30
- endpoints: (builder) => ({
31
- // Cortex Endpoints
32
- getCortexModels: builder.query({
33
- query: ({ apiUrl, apiKey }) => ({
34
- url: `${apiUrl}/cortex/models`,
35
- method: "GET",
36
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
37
- }),
38
- providesTags: ["Cortex"],
39
- transformResponse: (response) => response || []
71
+ postArweaveDownload: builder.mutation({
72
+ queryFn: async (instruction) => {
73
+ try {
74
+ const controller = new AbortController();
75
+ const timeout = setTimeout(() => controller.abort(), 6e4);
76
+ const response = await fetch(instruction.adiGatewayUrl, { method: "GET", signal: controller.signal });
77
+ clearTimeout(timeout);
78
+ return response.status < 200 || response.status >= 300 ? { data: { adrBody: null, adrStatus: response.status, adrSuccess: false, adrError: `download_failed_status_${response.status}` } } : response.json().then((body) => ({ data: { adrBody: body, adrStatus: response.status, adrSuccess: true, adrError: null } })).catch(() => ({ data: { adrBody: null, adrStatus: response.status, adrSuccess: false, adrError: "download_invalid_json" } }));
79
+ } catch (error) {
80
+ return {
81
+ data: {
82
+ adrBody: null,
83
+ adrStatus: 0,
84
+ adrSuccess: false,
85
+ adrError: error instanceof Error ? error.message : String(error)
86
+ }
87
+ };
88
+ }
89
+ },
90
+ invalidatesTags: ["Soul"]
91
+ })
92
+ });
93
+
94
+ // src/api/endpoints/builder.ts
95
+ var authHeaders = (apiKey) => apiKey ? { Authorization: `Bearer ${apiKey}` } : {};
96
+
97
+ // src/api/endpoints/cortex.ts
98
+ var buildCortexEndpoints = (builder) => ({
99
+ getCortexModels: builder.query({
100
+ query: ({ apiUrl, apiKey }) => ({
101
+ url: `${apiUrl}/cortex/models`,
102
+ method: "GET",
103
+ headers: authHeaders(apiKey)
40
104
  }),
41
- postCortexInit: builder.mutation({
42
- query: ({ request, apiUrl, apiKey }) => ({
43
- url: `${apiUrl}/cortex/init`,
44
- method: "POST",
45
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
46
- body: request
47
- }),
48
- invalidatesTags: ["Cortex"],
49
- transformResponse: (response) => response
105
+ providesTags: ["Cortex"],
106
+ transformResponse: (response) => response || []
107
+ }),
108
+ postCortexInit: builder.mutation({
109
+ query: ({ request, apiUrl, apiKey }) => ({
110
+ url: `${apiUrl}/cortex/init`,
111
+ method: "POST",
112
+ headers: authHeaders(apiKey),
113
+ body: request
50
114
  }),
51
- // NPC Endpoints
52
- /**
53
- * User Story: As the SDK protocol loop, I need a single process endpoint
54
- * that returns one atomic instruction per turn while echoing full tape state.
55
- * one hop in, one hop out, like passing a lit shard through vacuum.
56
- */
57
- postNpcProcess: builder.mutation({
58
- query: ({ npcId, request, apiUrl, apiKey }) => ({
59
- url: `${apiUrl}/npcs/${npcId}/process`,
60
- method: "POST",
61
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
62
- body: request
63
- }),
64
- invalidatesTags: (result, error, { npcId }) => [{ type: "NPC", id: npcId }],
65
- transformResponse: (response) => response
115
+ invalidatesTags: ["Cortex"],
116
+ transformResponse: (response) => response
117
+ }),
118
+ postCortexComplete: builder.mutation({
119
+ query: ({ cortexId, prompt, options, apiUrl, apiKey }) => ({
120
+ url: `${apiUrl}/cortex/${cortexId}/complete`,
121
+ method: "POST",
122
+ headers: authHeaders(apiKey),
123
+ body: { prompt, ...options }
66
124
  }),
67
- postDirective: builder.mutation({
68
- query: ({ npcId, request, apiUrl, apiKey }) => ({
69
- url: `${apiUrl}/npcs/${npcId}/directive`,
70
- method: "POST",
71
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
72
- body: request
73
- }),
74
- invalidatesTags: ["NPC"],
75
- transformResponse: (response) => response
125
+ invalidatesTags: ["Cortex"],
126
+ transformResponse: (response) => response
127
+ })
128
+ });
129
+
130
+ // src/api/endpoints/ghost.ts
131
+ var ghostTag = (sessionId) => [{ type: "Ghost", id: sessionId }];
132
+ var buildGhostEndpoints = (builder) => ({
133
+ postGhostRun: builder.mutation({
134
+ query: ({ request, apiUrl, apiKey }) => ({
135
+ url: `${apiUrl}/ghost/run`,
136
+ method: "POST",
137
+ headers: authHeaders(apiKey),
138
+ body: request
76
139
  }),
77
- postContext: builder.mutation({
78
- query: ({ npcId, request, apiUrl, apiKey }) => ({
79
- url: `${apiUrl}/npcs/${npcId}/context`,
80
- method: "POST",
81
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
82
- body: request
83
- }),
84
- invalidatesTags: (result, error, { npcId }) => [{ type: "NPC", id: npcId }],
85
- transformResponse: (response) => response
140
+ invalidatesTags: ["Ghost"],
141
+ transformResponse: (response) => response
142
+ }),
143
+ getGhostStatus: builder.query({
144
+ query: ({ sessionId, apiUrl, apiKey }) => ({
145
+ url: `${apiUrl}/ghost/${sessionId}/status`,
146
+ method: "GET",
147
+ headers: authHeaders(apiKey)
86
148
  }),
87
- postVerdict: builder.mutation({
88
- query: ({ npcId, request, apiUrl, apiKey }) => ({
89
- url: `${apiUrl}/npcs/${npcId}/verdict`,
90
- method: "POST",
91
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
92
- body: request
93
- }),
94
- invalidatesTags: (result, error, { npcId }) => [{ type: "NPC", id: npcId }],
95
- transformResponse: (response) => {
96
- const action = response.action ? {
97
- type: response.action.gaType || response.action.type,
98
- reason: response.action.actionReason || response.action.reason,
99
- target: response.action.actionTarget || response.action.target,
100
- signature: response.action.signature
101
- } : void 0;
102
- return {
103
- ...response,
104
- action
105
- };
106
- }
149
+ providesTags: (_result, _error, { sessionId }) => ghostTag(sessionId),
150
+ transformResponse: (response) => response
151
+ }),
152
+ getGhostResults: builder.query({
153
+ query: ({ sessionId, apiUrl, apiKey }) => ({
154
+ url: `${apiUrl}/ghost/${sessionId}/results`,
155
+ method: "GET",
156
+ headers: authHeaders(apiKey)
107
157
  }),
108
- postMemoryStore: builder.mutation({
109
- query: ({ npcId, request, apiUrl, apiKey }) => ({
110
- url: `${apiUrl}/npcs/${npcId}/memory`,
111
- method: "POST",
112
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
113
- body: request
114
- }),
115
- invalidatesTags: (result, error, { npcId }) => [{ type: "Memory", id: npcId }],
116
- transformResponse: (response) => response
158
+ providesTags: (_result, _error, { sessionId }) => ghostTag(sessionId),
159
+ transformResponse: (response) => response
160
+ }),
161
+ postGhostStop: builder.mutation({
162
+ query: ({ sessionId, apiUrl, apiKey }) => ({
163
+ url: `${apiUrl}/ghost/${sessionId}/stop`,
164
+ method: "POST",
165
+ headers: authHeaders(apiKey)
117
166
  }),
118
- getMemoryList: builder.query({
119
- query: ({ npcId, apiUrl, apiKey }) => ({
120
- url: `${apiUrl}/npcs/${npcId}/memory`,
121
- method: "GET",
122
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
123
- }),
124
- providesTags: (result, error, { npcId }) => [{ type: "Memory", id: npcId }],
125
- transformResponse: (response) => response || []
167
+ invalidatesTags: (_result, _error, { sessionId }) => ghostTag(sessionId),
168
+ transformResponse: (response) => ({
169
+ stopped: response?.stopStatus === "stopped",
170
+ stopStatus: response?.stopStatus,
171
+ stopSessionId: response?.stopSessionId
172
+ })
173
+ }),
174
+ getGhostHistory: builder.query({
175
+ query: ({ limit, apiUrl, apiKey }) => ({
176
+ url: `${apiUrl}/ghost/history?limit=${limit}`,
177
+ method: "GET",
178
+ headers: authHeaders(apiKey)
126
179
  }),
127
- postMemoryRecall: builder.mutation({
128
- query: ({ npcId, request, apiUrl, apiKey }) => ({
129
- url: `${apiUrl}/npcs/${npcId}/memory/recall`,
130
- method: "POST",
131
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
132
- body: request
133
- }),
134
- invalidatesTags: (result, error, { npcId }) => [{ type: "Memory", id: npcId }],
135
- transformResponse: (response) => response || []
180
+ providesTags: ["Ghost"],
181
+ transformResponse: (response) => response
182
+ })
183
+ });
184
+
185
+ // src/api/endpoints/npc.ts
186
+ var memoryTag = (npcId) => [{ type: "Memory", id: npcId }];
187
+ var npcTag = (npcId) => [{ type: "NPC", id: npcId }];
188
+ var buildNpcEndpoints = (builder) => ({
189
+ postNpcProcess: builder.mutation({
190
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
191
+ url: `${apiUrl}/npcs/${npcId}/process`,
192
+ method: "POST",
193
+ headers: authHeaders(apiKey),
194
+ body: request
136
195
  }),
137
- deleteMemoryClear: builder.mutation({
138
- query: ({ npcId, apiUrl, apiKey }) => ({
139
- url: `${apiUrl}/npcs/${npcId}/memory/clear`,
140
- method: "DELETE",
141
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
142
- }),
143
- invalidatesTags: (result, error, { npcId }) => [{ type: "Memory", id: npcId }],
144
- transformResponse: (response) => response
196
+ invalidatesTags: (_result, _error, { npcId }) => npcTag(npcId),
197
+ transformResponse: (response) => response
198
+ }),
199
+ postDirective: builder.mutation({
200
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
201
+ url: `${apiUrl}/npcs/${npcId}/directive`,
202
+ method: "POST",
203
+ headers: authHeaders(apiKey),
204
+ body: request
145
205
  }),
146
- // Ghost Endpoints
147
- postGhostRun: builder.mutation({
148
- query: ({ request, apiUrl, apiKey }) => ({
149
- url: `${apiUrl}/ghost/run`,
150
- method: "POST",
151
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
152
- body: request
153
- }),
154
- invalidatesTags: ["Ghost"],
155
- transformResponse: (response) => response
206
+ invalidatesTags: ["NPC"],
207
+ transformResponse: (response) => response
208
+ }),
209
+ postContext: builder.mutation({
210
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
211
+ url: `${apiUrl}/npcs/${npcId}/context`,
212
+ method: "POST",
213
+ headers: authHeaders(apiKey),
214
+ body: request
156
215
  }),
157
- getGhostStatus: builder.query({
158
- query: ({ sessionId, apiUrl, apiKey }) => ({
159
- url: `${apiUrl}/ghost/${sessionId}/status`,
160
- method: "GET",
161
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
162
- }),
163
- providesTags: (result, error, { sessionId }) => [{ type: "Ghost", id: sessionId }],
164
- transformResponse: (response) => response
216
+ invalidatesTags: (_result, _error, { npcId }) => npcTag(npcId),
217
+ transformResponse: (response) => response
218
+ }),
219
+ postVerdict: builder.mutation({
220
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
221
+ url: `${apiUrl}/npcs/${npcId}/verdict`,
222
+ method: "POST",
223
+ headers: authHeaders(apiKey),
224
+ body: request
165
225
  }),
166
- getGhostResults: builder.query({
167
- query: ({ sessionId, apiUrl, apiKey }) => ({
168
- url: `${apiUrl}/ghost/${sessionId}/results`,
169
- method: "GET",
170
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
171
- }),
172
- providesTags: (result, error, { sessionId }) => [{ type: "Ghost", id: sessionId }],
173
- transformResponse: (response) => response
226
+ invalidatesTags: (_result, _error, { npcId }) => npcTag(npcId),
227
+ transformResponse: (response) => {
228
+ const action = response.action ? {
229
+ type: response.action.gaType || response.action.type,
230
+ reason: response.action.actionReason || response.action.reason,
231
+ target: response.action.actionTarget || response.action.target,
232
+ signature: response.action.signature
233
+ } : void 0;
234
+ return {
235
+ ...response,
236
+ action
237
+ };
238
+ }
239
+ }),
240
+ postMemoryStore: builder.mutation({
241
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
242
+ url: `${apiUrl}/npcs/${npcId}/memory`,
243
+ method: "POST",
244
+ headers: authHeaders(apiKey),
245
+ body: request
174
246
  }),
175
- postGhostStop: builder.mutation({
176
- query: ({ sessionId, apiUrl, apiKey }) => ({
177
- url: `${apiUrl}/ghost/${sessionId}/stop`,
178
- method: "POST",
179
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
180
- }),
181
- invalidatesTags: (result, error, { sessionId }) => [{ type: "Ghost", id: sessionId }],
182
- transformResponse: (response) => ({
183
- stopped: response?.stopStatus === "stopped",
184
- stopStatus: response?.stopStatus,
185
- stopSessionId: response?.stopSessionId
186
- })
247
+ invalidatesTags: (_result, _error, { npcId }) => memoryTag(npcId),
248
+ transformResponse: (response) => response
249
+ }),
250
+ getMemoryList: builder.query({
251
+ query: ({ npcId, apiUrl, apiKey }) => ({
252
+ url: `${apiUrl}/npcs/${npcId}/memory`,
253
+ method: "GET",
254
+ headers: authHeaders(apiKey)
187
255
  }),
188
- getGhostHistory: builder.query({
189
- query: ({ limit, apiUrl, apiKey }) => ({
190
- url: `${apiUrl}/ghost/history?limit=${limit}`,
191
- method: "GET",
192
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
193
- }),
194
- providesTags: ["Ghost"],
195
- transformResponse: (response) => response
256
+ providesTags: (_result, _error, { npcId }) => memoryTag(npcId),
257
+ transformResponse: (response) => response || []
258
+ }),
259
+ postMemoryRecall: builder.mutation({
260
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
261
+ url: `${apiUrl}/npcs/${npcId}/memory/recall`,
262
+ method: "POST",
263
+ headers: authHeaders(apiKey),
264
+ body: request
196
265
  }),
197
- // Soul Endpoints
198
- postSoulExport: builder.mutation({
199
- query: ({ npcId, request, apiUrl, apiKey }) => ({
200
- url: `${apiUrl}/npcs/${npcId}/soul/export`,
201
- method: "POST",
202
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
203
- body: request
204
- }),
205
- invalidatesTags: ["Soul"],
206
- transformResponse: (response) => response
266
+ invalidatesTags: (_result, _error, { npcId }) => memoryTag(npcId),
267
+ transformResponse: (response) => response || []
268
+ }),
269
+ deleteMemoryClear: builder.mutation({
270
+ query: ({ npcId, apiUrl, apiKey }) => ({
271
+ url: `${apiUrl}/npcs/${npcId}/memory/clear`,
272
+ method: "DELETE",
273
+ headers: authHeaders(apiKey)
207
274
  }),
208
- getSoulImport: builder.query({
209
- query: ({ txId, apiUrl, apiKey }) => ({
210
- url: `${apiUrl}/souls/${txId}`,
211
- method: "GET",
212
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
213
- }),
214
- providesTags: (result, error, { txId }) => [{ type: "Soul", id: txId }],
215
- transformResponse: (response) => response
275
+ invalidatesTags: (_result, _error, { npcId }) => memoryTag(npcId),
276
+ transformResponse: (response) => response
277
+ })
278
+ });
279
+
280
+ // src/api/endpoints/rules.ts
281
+ var buildBridgeAndRuleEndpoints = (builder) => ({
282
+ postBridgeValidate: builder.mutation({
283
+ query: ({ request, npcId, apiUrl, apiKey }) => ({
284
+ url: npcId ? `${apiUrl}/bridge/validate/${npcId}` : `${apiUrl}/bridge/validate`,
285
+ method: "POST",
286
+ headers: authHeaders(apiKey),
287
+ body: request
216
288
  }),
217
- getSouls: builder.query({
218
- query: ({ limit, apiUrl, apiKey }) => ({
219
- url: `${apiUrl}/souls?limit=${limit}`,
220
- method: "GET",
221
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
222
- }),
223
- providesTags: ["Soul"],
224
- transformResponse: (response) => response
289
+ invalidatesTags: ["Bridge"],
290
+ transformResponse: (response) => response.brResult || response
291
+ }),
292
+ getBridgeRules: builder.query({
293
+ query: ({ apiUrl, apiKey }) => ({
294
+ url: `${apiUrl}/bridge/rules`,
295
+ method: "GET",
296
+ headers: authHeaders(apiKey)
225
297
  }),
226
- // Bridge Endpoints
227
- postBridgeValidate: builder.mutation({
228
- query: ({ request, npcId, apiUrl, apiKey }) => ({
229
- url: npcId ? `${apiUrl}/bridge/validate/${npcId}` : `${apiUrl}/bridge/validate`,
230
- method: "POST",
231
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
232
- body: request
233
- }),
234
- invalidatesTags: ["Bridge"],
235
- transformResponse: (response) => response.brResult || response
298
+ providesTags: ["Bridge"],
299
+ transformResponse: (response) => response
300
+ }),
301
+ postBridgePreset: builder.mutation({
302
+ query: ({ presetName, apiUrl, apiKey }) => ({
303
+ url: `${apiUrl}/rules/presets/${presetName}`,
304
+ method: "POST",
305
+ headers: authHeaders(apiKey)
236
306
  }),
237
- getBridgeRules: builder.query({
238
- query: ({ apiUrl, apiKey }) => ({
239
- url: `${apiUrl}/bridge/rules`,
240
- method: "GET",
241
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
242
- }),
243
- providesTags: ["Bridge"],
244
- transformResponse: (response) => response
307
+ invalidatesTags: ["Bridge"],
308
+ transformResponse: (response) => response
309
+ }),
310
+ getRulesets: builder.query({
311
+ query: ({ apiUrl, apiKey }) => ({
312
+ url: `${apiUrl}/rules`,
313
+ method: "GET",
314
+ headers: authHeaders(apiKey)
245
315
  }),
246
- postBridgePreset: builder.mutation({
247
- query: ({ presetName, apiUrl, apiKey }) => ({
248
- url: `${apiUrl}/rules/presets/${presetName}`,
249
- method: "POST",
250
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
251
- }),
252
- invalidatesTags: ["Bridge"],
253
- transformResponse: (response) => response
316
+ providesTags: ["Rule"],
317
+ transformResponse: (response) => response || []
318
+ }),
319
+ getRulePresets: builder.query({
320
+ query: ({ apiUrl, apiKey }) => ({
321
+ url: `${apiUrl}/rules/presets`,
322
+ method: "GET",
323
+ headers: authHeaders(apiKey)
254
324
  }),
255
- // Rules Endpoints
256
- getRulesets: builder.query({
257
- query: ({ apiUrl, apiKey }) => ({
258
- url: `${apiUrl}/rules`,
259
- method: "GET",
260
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
261
- }),
262
- providesTags: ["Rule"],
263
- transformResponse: (response) => response || []
325
+ providesTags: ["Rule"],
326
+ transformResponse: (response) => response || []
327
+ }),
328
+ postRuleRegister: builder.mutation({
329
+ query: ({ request, apiUrl, apiKey }) => ({
330
+ url: `${apiUrl}/rules`,
331
+ method: "POST",
332
+ headers: authHeaders(apiKey),
333
+ body: request
264
334
  }),
265
- getRulePresets: builder.query({
266
- query: ({ apiUrl, apiKey }) => ({
267
- url: `${apiUrl}/rules/presets`,
268
- method: "GET",
269
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
270
- }),
271
- providesTags: ["Rule"],
272
- transformResponse: (response) => response || []
335
+ invalidatesTags: ["Rule"],
336
+ transformResponse: (response) => response
337
+ }),
338
+ deleteRule: builder.mutation({
339
+ query: ({ rulesetId, apiUrl, apiKey }) => ({
340
+ url: `${apiUrl}/rules/${rulesetId}`,
341
+ method: "DELETE",
342
+ headers: authHeaders(apiKey)
273
343
  }),
274
- postRuleRegister: builder.mutation({
275
- query: ({ request, apiUrl, apiKey }) => ({
276
- url: `${apiUrl}/rules`,
277
- method: "POST",
278
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
279
- body: request
280
- }),
281
- invalidatesTags: ["Rule"],
282
- transformResponse: (response) => response
344
+ invalidatesTags: ["Rule"],
345
+ transformResponse: (_response) => ({ deleted: true })
346
+ })
347
+ });
348
+
349
+ // src/api/endpoints/soul.ts
350
+ var soulTag = (id) => [{ type: "Soul", id }];
351
+ var buildSoulEndpoints = (builder) => ({
352
+ postSoulExport: builder.mutation({
353
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
354
+ url: `${apiUrl}/npcs/${npcId}/soul/export`,
355
+ method: "POST",
356
+ headers: authHeaders(apiKey),
357
+ body: request
283
358
  }),
284
- deleteRule: builder.mutation({
285
- query: ({ rulesetId, apiUrl, apiKey }) => ({
286
- url: `${apiUrl}/rules/${rulesetId}`,
287
- method: "DELETE",
288
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
289
- }),
290
- invalidatesTags: ["Rule"],
291
- transformResponse: (_response) => ({ deleted: true })
359
+ invalidatesTags: ["Soul"],
360
+ transformResponse: (response) => response
361
+ }),
362
+ postSoulExportConfirm: builder.mutation({
363
+ query: ({ npcId, request, apiUrl, apiKey }) => ({
364
+ url: `${apiUrl}/npcs/${npcId}/soul/confirm`,
365
+ method: "POST",
366
+ headers: authHeaders(apiKey),
367
+ body: request
292
368
  }),
293
- // Additional Soul/NPC Endpoints
294
- postSoulVerify: builder.mutation({
295
- query: ({ txId, apiUrl, apiKey }) => ({
296
- url: `${apiUrl}/souls/${txId}/verify`,
297
- method: "POST",
298
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {}
299
- }),
300
- invalidatesTags: ["Soul"],
301
- transformResponse: (response) => ({
302
- valid: response.verifyValid ?? response.valid ?? false,
303
- reason: response.verifyReason ?? response.reason
304
- })
369
+ invalidatesTags: ["Soul"],
370
+ transformResponse: (response) => response
371
+ }),
372
+ getSoulImport: builder.query({
373
+ query: ({ txId, apiUrl, apiKey }) => ({
374
+ url: `${apiUrl}/souls/${txId}`,
375
+ method: "GET",
376
+ headers: authHeaders(apiKey)
305
377
  }),
306
- postNpcImport: builder.mutation({
307
- query: ({ request, apiUrl, apiKey }) => ({
308
- url: `${apiUrl}/npcs/import`,
309
- method: "POST",
310
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
311
- body: request
312
- }),
313
- invalidatesTags: ["NPC"],
314
- transformResponse: (response) => response
378
+ providesTags: (_result, _error, { txId }) => soulTag(txId),
379
+ transformResponse: (response) => response
380
+ }),
381
+ getSouls: builder.query({
382
+ query: ({ limit, apiUrl, apiKey }) => ({
383
+ url: `${apiUrl}/souls?limit=${limit}`,
384
+ method: "GET",
385
+ headers: authHeaders(apiKey)
315
386
  }),
316
- // Cortex Remote Endpoint
317
- postCortexComplete: builder.mutation({
318
- query: ({ cortexId, prompt, options, apiUrl, apiKey }) => ({
319
- url: `${apiUrl}/cortex/${cortexId}/complete`,
320
- method: "POST",
321
- headers: apiKey ? { "Authorization": `Bearer ${apiKey}` } : {},
322
- body: { prompt, ...options }
323
- }),
324
- invalidatesTags: ["Cortex"],
325
- transformResponse: (response) => response
387
+ providesTags: ["Soul"],
388
+ transformResponse: (response) => response
389
+ }),
390
+ postSoulVerify: builder.mutation({
391
+ query: ({ txId, apiUrl, apiKey }) => ({
392
+ url: `${apiUrl}/souls/${txId}/verify`,
393
+ method: "POST",
394
+ headers: authHeaders(apiKey)
326
395
  }),
327
- // System Endpoints
328
- getApiStatus: builder.query({
329
- query: ({ apiUrl }) => ({ url: `${apiUrl}/status`, method: "GET" }),
330
- transformResponse: (response) => response
396
+ invalidatesTags: ["Soul"],
397
+ transformResponse: (response) => ({
398
+ valid: response.verifyValid ?? response.valid ?? false,
399
+ reason: response.verifyReason ?? response.reason
331
400
  })
401
+ }),
402
+ postNpcImport: builder.mutation({
403
+ query: ({ request, apiUrl, apiKey }) => ({
404
+ url: `${apiUrl}/npcs/import`,
405
+ method: "POST",
406
+ headers: authHeaders(apiKey),
407
+ body: request
408
+ }),
409
+ invalidatesTags: ["NPC"],
410
+ transformResponse: (response) => response
411
+ }),
412
+ postNpcImportConfirm: builder.mutation({
413
+ query: ({ request, apiUrl, apiKey }) => ({
414
+ url: `${apiUrl}/npcs/import/confirm`,
415
+ method: "POST",
416
+ headers: authHeaders(apiKey),
417
+ body: request
418
+ }),
419
+ invalidatesTags: ["NPC"],
420
+ transformResponse: (response) => response
421
+ })
422
+ });
423
+
424
+ // src/api/endpoints/system.ts
425
+ var buildSystemEndpoints = (builder) => ({
426
+ getApiStatus: builder.query({
427
+ query: ({ apiUrl }) => ({ url: `${apiUrl}/status`, method: "GET" }),
428
+ providesTags: ["NPC"],
429
+ transformResponse: (response) => response
430
+ })
431
+ });
432
+
433
+ // src/apiSlice.ts
434
+ var api = createApi({
435
+ reducerPath: "api",
436
+ baseQuery: fetchBaseQuery({
437
+ baseUrl: "/",
438
+ prepareHeaders: (headers, { getState }) => {
439
+ return headers;
440
+ }
441
+ }),
442
+ tagTypes: ["NPC", "Memory", "Cortex", "Ghost", "Soul", "Bridge", "Rule"],
443
+ endpoints: (builder) => ({
444
+ ...buildCortexEndpoints(builder),
445
+ ...buildNpcEndpoints(builder),
446
+ ...buildGhostEndpoints(builder),
447
+ ...buildSoulEndpoints(builder),
448
+ ...buildBridgeAndRuleEndpoints(builder),
449
+ ...buildArweaveEndpoints(builder),
450
+ ...buildSystemEndpoints(builder)
332
451
  })
333
452
  });
334
453
 
454
+ // src/errors.ts
455
+ var DEFAULT_API_URL = "http://localhost:8080";
456
+ var PRODUCTION_API_URL = "https://api.forboc.ai";
457
+ var resolveApiUrl = (apiUrl) => apiUrl || DEFAULT_API_URL;
458
+ var extractThunkErrorMessage = (error, fallback) => {
459
+ if (typeof error === "string") return error;
460
+ if (error && typeof error === "object") {
461
+ const e = error;
462
+ if (typeof e.data === "object" && e.data?.message) return String(e.data.message);
463
+ if (typeof e.data === "string") return e.data;
464
+ if (e.message) return e.message;
465
+ if (e.error) return e.error;
466
+ }
467
+ return fallback;
468
+ };
469
+ var requireApiKeyGuidance = (apiUrl, apiKey) => {
470
+ const normalized = apiUrl.toLowerCase();
471
+ if (normalized.includes("api.forboc.ai") && !apiKey) {
472
+ throw new Error("Missing API key. Set FORBOCAI_API_KEY (or run `forboc config set apiKey <key>`) for production API calls.");
473
+ }
474
+ };
475
+
335
476
  // src/bridgeSlice.ts
336
477
  var initialState = {
337
478
  activePresets: [],
@@ -345,16 +486,17 @@ var validateBridgeThunk = createAsyncThunk(
345
486
  "bridge/validate",
346
487
  async ({ action, context, npcId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
347
488
  try {
348
- const url = apiUrl || "https://api.forboc.ai";
349
- const data = await dispatch2(sdkApi.endpoints.postBridgeValidate.initiate({
489
+ const url = resolveApiUrl(apiUrl);
490
+ requireApiKeyGuidance(url, apiKey);
491
+ const data = await dispatch2(api.endpoints.postBridgeValidate.initiate({
350
492
  request: { action, context },
351
493
  npcId,
352
494
  apiUrl: url,
353
495
  apiKey
354
496
  })).unwrap();
355
497
  return data;
356
- } catch (e) {
357
- return rejectWithValue(e.message || "Bridge validation failed");
498
+ } catch (error) {
499
+ return rejectWithValue(extractThunkErrorMessage(error, "Bridge validation failed"));
358
500
  }
359
501
  }
360
502
  );
@@ -362,10 +504,11 @@ var loadBridgePresetThunk = createAsyncThunk(
362
504
  "bridge/loadPreset",
363
505
  async ({ presetName, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
364
506
  try {
365
- const url = apiUrl || "https://api.forboc.ai";
366
- return await dispatch2(sdkApi.endpoints.postBridgePreset.initiate({ presetName, apiUrl: url, apiKey })).unwrap();
367
- } catch (e) {
368
- return rejectWithValue(e.message || "Failed to load preset");
507
+ const url = resolveApiUrl(apiUrl);
508
+ requireApiKeyGuidance(url, apiKey);
509
+ return await dispatch2(api.endpoints.postBridgePreset.initiate({ presetName, apiUrl: url, apiKey })).unwrap();
510
+ } catch (error) {
511
+ return rejectWithValue(extractThunkErrorMessage(error, "Failed to load preset"));
369
512
  }
370
513
  }
371
514
  );
@@ -373,10 +516,11 @@ var getBridgeRulesThunk = createAsyncThunk(
373
516
  "bridge/rules",
374
517
  async ({ apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
375
518
  try {
376
- const url = apiUrl || "https://api.forboc.ai";
377
- return await dispatch2(sdkApi.endpoints.getBridgeRules.initiate({ apiUrl: url, apiKey })).unwrap();
378
- } catch (e) {
379
- return rejectWithValue(e.message || "Failed to list bridge rules");
519
+ const url = resolveApiUrl(apiUrl);
520
+ requireApiKeyGuidance(url, apiKey);
521
+ return await dispatch2(api.endpoints.getBridgeRules.initiate({ apiUrl: url, apiKey })).unwrap();
522
+ } catch (error) {
523
+ return rejectWithValue(extractThunkErrorMessage(error, "Failed to list bridge rules"));
380
524
  }
381
525
  }
382
526
  );
@@ -384,10 +528,11 @@ var listRulesetsThunk = createAsyncThunk(
384
528
  "bridge/listRulesets",
385
529
  async ({ apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
386
530
  try {
387
- const url = apiUrl || "https://api.forboc.ai";
388
- return await dispatch2(sdkApi.endpoints.getRulesets.initiate({ apiUrl: url, apiKey })).unwrap();
389
- } catch (e) {
390
- return rejectWithValue(e.message || "Failed to list rulesets");
531
+ const url = resolveApiUrl(apiUrl);
532
+ requireApiKeyGuidance(url, apiKey);
533
+ return await dispatch2(api.endpoints.getRulesets.initiate({ apiUrl: url, apiKey })).unwrap();
534
+ } catch (error) {
535
+ return rejectWithValue(extractThunkErrorMessage(error, "Failed to list rulesets"));
391
536
  }
392
537
  }
393
538
  );
@@ -395,10 +540,11 @@ var listRulePresetsThunk = createAsyncThunk(
395
540
  "bridge/listRulePresets",
396
541
  async ({ apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
397
542
  try {
398
- const url = apiUrl || "https://api.forboc.ai";
399
- return await dispatch2(sdkApi.endpoints.getRulePresets.initiate({ apiUrl: url, apiKey })).unwrap();
400
- } catch (e) {
401
- return rejectWithValue(e.message || "Failed to list rule presets");
543
+ const url = resolveApiUrl(apiUrl);
544
+ requireApiKeyGuidance(url, apiKey);
545
+ return await dispatch2(api.endpoints.getRulePresets.initiate({ apiUrl: url, apiKey })).unwrap();
546
+ } catch (error) {
547
+ return rejectWithValue(extractThunkErrorMessage(error, "Failed to list rule presets"));
402
548
  }
403
549
  }
404
550
  );
@@ -406,10 +552,11 @@ var registerRulesetThunk = createAsyncThunk(
406
552
  "bridge/registerRuleset",
407
553
  async ({ ruleset, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
408
554
  try {
409
- const url = apiUrl || "https://api.forboc.ai";
410
- return await dispatch2(sdkApi.endpoints.postRuleRegister.initiate({ request: ruleset, apiUrl: url, apiKey })).unwrap();
411
- } catch (e) {
412
- return rejectWithValue(e.message || "Failed to register ruleset");
555
+ const url = resolveApiUrl(apiUrl);
556
+ requireApiKeyGuidance(url, apiKey);
557
+ return await dispatch2(api.endpoints.postRuleRegister.initiate({ request: ruleset, apiUrl: url, apiKey })).unwrap();
558
+ } catch (error) {
559
+ return rejectWithValue(extractThunkErrorMessage(error, "Failed to register ruleset"));
413
560
  }
414
561
  }
415
562
  );
@@ -417,10 +564,11 @@ var deleteRulesetThunk = createAsyncThunk(
417
564
  "bridge/deleteRuleset",
418
565
  async ({ rulesetId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
419
566
  try {
420
- const url = apiUrl || "https://api.forboc.ai";
421
- return await dispatch2(sdkApi.endpoints.deleteRule.initiate({ rulesetId, apiUrl: url, apiKey })).unwrap();
422
- } catch (e) {
423
- return rejectWithValue(e.message || "Failed to delete ruleset");
567
+ const url = resolveApiUrl(apiUrl);
568
+ requireApiKeyGuidance(url, apiKey);
569
+ return await dispatch2(api.endpoints.deleteRule.initiate({ rulesetId, apiUrl: url, apiKey })).unwrap();
570
+ } catch (error) {
571
+ return rejectWithValue(extractThunkErrorMessage(error, "Failed to delete ruleset"));
424
572
  }
425
573
  }
426
574
  );
@@ -469,6 +617,85 @@ var bridgeSlice_default = bridgeSlice.reducer;
469
617
 
470
618
  // src/soulSlice.ts
471
619
  import { createSlice as createSlice2, createAsyncThunk as createAsyncThunk2 } from "@reduxjs/toolkit";
620
+
621
+ // src/functional_core.ts
622
+ var just = (value) => ({
623
+ _tag: "Just",
624
+ map: (f) => just(f(value)),
625
+ chain: (f) => f(value),
626
+ getOrElse: (_defaultValue) => value,
627
+ match: (cases) => cases.just(value)
628
+ });
629
+ var nothing = () => ({
630
+ _tag: "Nothing",
631
+ map: (_f) => nothing(),
632
+ chain: (_f) => nothing(),
633
+ getOrElse: (defaultValue) => defaultValue,
634
+ match: (cases) => cases.nothing()
635
+ });
636
+ var fmap = (m, f) => m.map(f);
637
+ var mbind = (m, f) => m.chain(f);
638
+ var orElse = (m, defaultValue) => m.getOrElse(defaultValue);
639
+ var match = (m, onJust, onNothing) => m.match({ just: onJust, nothing: onNothing });
640
+ var isJust = (m) => m._tag === "Just";
641
+ var isNothing = (m) => m._tag === "Nothing";
642
+ var fromNullable = (value) => value != null ? just(value) : nothing();
643
+ var requireJust = (m, errorMsg) => m.match({
644
+ just: (v) => v,
645
+ nothing: () => {
646
+ throw new Error(errorMsg);
647
+ }
648
+ });
649
+ var left = (error) => ({
650
+ _tag: "Left",
651
+ map: (_f) => left(error),
652
+ chain: (_f) => left(error),
653
+ getOrElse: (defaultValue) => defaultValue,
654
+ match: (cases) => cases.left(error)
655
+ });
656
+ var right = (value) => ({
657
+ _tag: "Right",
658
+ map: (f) => right(f(value)),
659
+ chain: (f) => f(value),
660
+ getOrElse: (_defaultValue) => value,
661
+ match: (cases) => cases.right(value)
662
+ });
663
+ var efmap = (e, f) => e.map(f);
664
+ var ebind = (e, f) => e.chain(f);
665
+ var ematch = (e, onLeft, onRight) => e.match({ left: onLeft, right: onRight });
666
+ var isLeft = (e) => e._tag === "Left";
667
+ var isRight = (e) => e._tag === "Right";
668
+ function compose(...fns) {
669
+ return (...args) => {
670
+ const last = fns[fns.length - 1];
671
+ const rest = fns.slice(0, -1);
672
+ return rest.reduceRight((acc, fn) => fn(acc), last(...args));
673
+ };
674
+ }
675
+ function curry(fn) {
676
+ const arity = fn.length;
677
+ const curried = (...args) => args.length >= arity ? fn(...args) : (...moreArgs) => curried(...args, ...moreArgs);
678
+ return curried;
679
+ }
680
+ var createDispatcher = (entries) => {
681
+ const table = new Map(entries);
682
+ return {
683
+ dispatch: (key, ...args) => {
684
+ const handler = table.get(key);
685
+ return handler ? just(handler(...args)) : nothing();
686
+ },
687
+ has: (key) => table.has(key),
688
+ keys: () => [...table.keys()]
689
+ };
690
+ };
691
+ var _ = /* @__PURE__ */ Symbol.for("forbocai_wildcard");
692
+ var testCase = (value, predicate, handler) => predicate === _ ? just(handler(value)) : typeof predicate === "function" ? predicate(value) ? just(handler(value)) : nothing() : predicate === value ? just(handler(value)) : nothing();
693
+ var multiMatch = (value, cases) => cases.length === 0 ? nothing() : testCase(value, cases[0][0], cases[0][1]).match({
694
+ just: (v) => just(v),
695
+ nothing: () => multiMatch(value, cases.slice(1))
696
+ });
697
+
698
+ // src/soulSlice.ts
472
699
  var initialState2 = {
473
700
  exportStatus: "idle",
474
701
  importStatus: "idle",
@@ -479,26 +706,46 @@ var initialState2 = {
479
706
  };
480
707
  var remoteExportSoulThunk = createAsyncThunk2(
481
708
  "soul/export",
482
- async ({ npcId: argNpcId, apiUrl, apiKey, memories = [] }, { getState, dispatch: dispatch2, rejectWithValue }) => {
709
+ async ({ npcId: argNpcId, apiUrl, apiKey }, { getState, dispatch: dispatch2, rejectWithValue }) => {
483
710
  try {
484
711
  const state = getState().npc;
485
712
  const npcId = argNpcId || state.activeNpcId;
486
- const npc = state.entities[npcId];
487
- if (!npc) throw new Error(`NPC ${npcId} not found`);
488
- const url = apiUrl || "https://api.forboc.ai";
489
- const result = await dispatch2(sdkApi.endpoints.postSoulExport.initiate({
490
- npcId,
491
- request: { npcIdRef: npcId, persona: npc.persona || "NPC", npcState: npc.state },
492
- apiUrl: url,
493
- apiKey
494
- })).unwrap();
713
+ const npc = requireJust(fromNullable(state.entities[npcId]), `NPC ${npcId} not found`);
714
+ const url = resolveApiUrl(apiUrl);
715
+ requireApiKeyGuidance(url, apiKey);
716
+ const phase1 = await dispatch2(
717
+ api.endpoints.postSoulExport.initiate({
718
+ npcId,
719
+ request: { npcIdRef: npcId, persona: npc.persona || "NPC", npcState: npc.state },
720
+ apiUrl: url,
721
+ apiKey
722
+ })
723
+ ).unwrap();
724
+ const uploadResult = await dispatch2(
725
+ api.endpoints.postArweaveUpload.initiate({
726
+ ...phase1.se1Instruction,
727
+ auiAuthHeader: phase1.se1Instruction.auiAuthHeader ?? null
728
+ })
729
+ ).unwrap();
730
+ const final = await dispatch2(
731
+ api.endpoints.postSoulExportConfirm.initiate({
732
+ npcId,
733
+ request: {
734
+ secUploadResult: uploadResult,
735
+ secSignedPayload: phase1.se1SignedPayload,
736
+ secSignature: phase1.se1Signature
737
+ },
738
+ apiUrl: url,
739
+ apiKey
740
+ })
741
+ ).unwrap();
495
742
  return {
496
- txId: result.txId,
497
- url: result.arweaveUrl,
498
- soul: result.soul
743
+ txId: final.txId,
744
+ url: final.arweaveUrl,
745
+ soul: final.soul
499
746
  };
500
- } catch (e) {
501
- return rejectWithValue(e.message || "Soul export failed");
747
+ } catch (error) {
748
+ return rejectWithValue(extractThunkErrorMessage(error, "Soul export failed"));
502
749
  }
503
750
  }
504
751
  );
@@ -506,11 +753,34 @@ var importSoulFromArweaveThunk = createAsyncThunk2(
506
753
  "soul/import",
507
754
  async ({ txId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
508
755
  try {
509
- const url = apiUrl || "https://api.forboc.ai";
510
- const data = await dispatch2(sdkApi.endpoints.getSoulImport.initiate({ txId, apiUrl: url, apiKey })).unwrap();
511
- return data;
512
- } catch (e) {
513
- return rejectWithValue(e.message || "Soul import failed");
756
+ const url = resolveApiUrl(apiUrl);
757
+ requireApiKeyGuidance(url, apiKey);
758
+ const phase1 = await dispatch2(
759
+ api.endpoints.postNpcImport.initiate({ request: { txIdRef: txId }, apiUrl: url, apiKey })
760
+ ).unwrap();
761
+ const downloadResult = await dispatch2(
762
+ api.endpoints.postArweaveDownload.initiate(phase1.si1Instruction)
763
+ ).unwrap();
764
+ const npc = await dispatch2(
765
+ api.endpoints.postNpcImportConfirm.initiate({
766
+ request: {
767
+ sicTxId: txId,
768
+ sicDownloadResult: downloadResult
769
+ },
770
+ apiUrl: url,
771
+ apiKey
772
+ })
773
+ ).unwrap();
774
+ return {
775
+ id: txId,
776
+ version: "2.0.0",
777
+ name: npc.npcId,
778
+ persona: npc.persona,
779
+ memories: [],
780
+ state: npc.data || {}
781
+ };
782
+ } catch (error) {
783
+ return rejectWithValue(extractThunkErrorMessage(error, "Soul import failed"));
514
784
  }
515
785
  }
516
786
  );
@@ -518,11 +788,12 @@ var getSoulListThunk = createAsyncThunk2(
518
788
  "soul/list",
519
789
  async ({ limit = 50, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
520
790
  try {
521
- const url = apiUrl || "https://api.forboc.ai";
522
- const data = await dispatch2(sdkApi.endpoints.getSouls.initiate({ limit, apiUrl: url, apiKey })).unwrap();
791
+ const url = resolveApiUrl(apiUrl);
792
+ requireApiKeyGuidance(url, apiKey);
793
+ const data = await dispatch2(api.endpoints.getSouls.initiate({ limit, apiUrl: url, apiKey })).unwrap();
523
794
  return data.souls || [];
524
- } catch (e) {
525
- return rejectWithValue(e.message || "Failed to list souls");
795
+ } catch (error) {
796
+ return rejectWithValue(extractThunkErrorMessage(error, "Failed to list souls"));
526
797
  }
527
798
  }
528
799
  );
@@ -530,10 +801,11 @@ var verifySoulThunk = createAsyncThunk2(
530
801
  "soul/verify",
531
802
  async ({ txId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
532
803
  try {
533
- const url = apiUrl || "https://api.forboc.ai";
534
- return await dispatch2(sdkApi.endpoints.postSoulVerify.initiate({ txId, apiUrl: url, apiKey })).unwrap();
535
- } catch (e) {
536
- return rejectWithValue(e.message || "Soul verify failed");
804
+ const url = resolveApiUrl(apiUrl);
805
+ requireApiKeyGuidance(url, apiKey);
806
+ return await dispatch2(api.endpoints.postSoulVerify.initiate({ txId, apiUrl: url, apiKey })).unwrap();
807
+ } catch (error) {
808
+ return rejectWithValue(extractThunkErrorMessage(error, "Soul verify failed"));
537
809
  }
538
810
  }
539
811
  );
@@ -541,14 +813,27 @@ var importNpcFromSoulThunk = createAsyncThunk2(
541
813
  "soul/importNpc",
542
814
  async ({ txId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
543
815
  try {
544
- const url = apiUrl || "https://api.forboc.ai";
545
- return await dispatch2(sdkApi.endpoints.postNpcImport.initiate({
546
- request: { txIdRef: txId },
547
- apiUrl: url,
548
- apiKey
549
- })).unwrap();
550
- } catch (e) {
551
- return rejectWithValue(e.message || "NPC import from soul failed");
816
+ const url = resolveApiUrl(apiUrl);
817
+ requireApiKeyGuidance(url, apiKey);
818
+ const phase1 = await dispatch2(
819
+ api.endpoints.postNpcImport.initiate({
820
+ request: { txIdRef: txId },
821
+ apiUrl: url,
822
+ apiKey
823
+ })
824
+ ).unwrap();
825
+ const downloadResult = await dispatch2(
826
+ api.endpoints.postArweaveDownload.initiate(phase1.si1Instruction)
827
+ ).unwrap();
828
+ return await dispatch2(
829
+ api.endpoints.postNpcImportConfirm.initiate({
830
+ request: { sicTxId: txId, sicDownloadResult: downloadResult },
831
+ apiUrl: url,
832
+ apiKey
833
+ })
834
+ ).unwrap();
835
+ } catch (error) {
836
+ return rejectWithValue(extractThunkErrorMessage(error, "NPC import from soul failed"));
552
837
  }
553
838
  }
554
839
  );
@@ -606,8 +891,9 @@ var startGhostThunk = createAsyncThunk3(
606
891
  "ghost/start",
607
892
  async (config, { dispatch: dispatch2, rejectWithValue }) => {
608
893
  try {
609
- const apiUrl = config.apiUrl || "https://api.forboc.ai";
610
- const data = await dispatch2(sdkApi.endpoints.postGhostRun.initiate({
894
+ const apiUrl = resolveApiUrl(config.apiUrl);
895
+ requireApiKeyGuidance(apiUrl, config.apiKey);
896
+ const data = await dispatch2(api.endpoints.postGhostRun.initiate({
611
897
  request: { testSuite: config.testSuite, duration: config.duration ?? 300 },
612
898
  apiUrl,
613
899
  apiKey: config.apiKey
@@ -616,8 +902,8 @@ var startGhostThunk = createAsyncThunk3(
616
902
  sessionId: data.sessionId,
617
903
  status: data.runStatus
618
904
  };
619
- } catch (e) {
620
- return rejectWithValue(e.message || "Failed to start Ghost");
905
+ } catch (error) {
906
+ return rejectWithValue(extractThunkErrorMessage(error, "Failed to start Ghost"));
621
907
  }
622
908
  }
623
909
  );
@@ -626,10 +912,10 @@ var getGhostStatusThunk = createAsyncThunk3(
626
912
  async ({ sessionId, apiUrl, apiKey }, { dispatch: dispatch2, getState, rejectWithValue }) => {
627
913
  try {
628
914
  const state = getState().ghost;
629
- const targetSession = sessionId || state.activeSessionId;
630
- if (!targetSession) throw new Error("No active Ghost session");
631
- const url = apiUrl || "https://api.forboc.ai";
632
- const data = await dispatch2(sdkApi.endpoints.getGhostStatus.initiate({ sessionId: targetSession, apiUrl: url, apiKey })).unwrap();
915
+ const targetSession = requireJust(fromNullable(sessionId || state.activeSessionId), "No active Ghost session");
916
+ const url = resolveApiUrl(apiUrl);
917
+ requireApiKeyGuidance(url, apiKey);
918
+ const data = await dispatch2(api.endpoints.getGhostStatus.initiate({ sessionId: targetSession, apiUrl: url, apiKey })).unwrap();
633
919
  return {
634
920
  sessionId: data.ghostSessionId,
635
921
  status: data.ghostStatus,
@@ -638,8 +924,8 @@ var getGhostStatusThunk = createAsyncThunk3(
638
924
  duration: data.ghostDuration || 0,
639
925
  errors: data.ghostErrors
640
926
  };
641
- } catch (e) {
642
- return rejectWithValue(e.message || "Failed to get ghost status");
927
+ } catch (error) {
928
+ return rejectWithValue(extractThunkErrorMessage(error, "Failed to get ghost status"));
643
929
  }
644
930
  }
645
931
  );
@@ -648,10 +934,10 @@ var getGhostResultsThunk = createAsyncThunk3(
648
934
  async ({ sessionId, apiUrl, apiKey }, { dispatch: dispatch2, getState, rejectWithValue }) => {
649
935
  try {
650
936
  const state = getState().ghost;
651
- const targetSession = sessionId || state.activeSessionId;
652
- if (!targetSession) throw new Error("No active Ghost session");
653
- const url = apiUrl || "https://api.forboc.ai";
654
- const data = await dispatch2(sdkApi.endpoints.getGhostResults.initiate({ sessionId: targetSession, apiUrl: url, apiKey })).unwrap();
937
+ const targetSession = requireJust(fromNullable(sessionId || state.activeSessionId), "No active Ghost session");
938
+ const url = resolveApiUrl(apiUrl);
939
+ requireApiKeyGuidance(url, apiKey);
940
+ const data = await dispatch2(api.endpoints.getGhostResults.initiate({ sessionId: targetSession, apiUrl: url, apiKey })).unwrap();
655
941
  return {
656
942
  sessionId: data.resultsSessionId,
657
943
  totalTests: data.resultsTotalTests,
@@ -669,8 +955,8 @@ var getGhostResultsThunk = createAsyncThunk3(
669
955
  coverage: data.resultsCoverage,
670
956
  metrics: Object.fromEntries(data.resultsMetrics || [])
671
957
  };
672
- } catch (e) {
673
- return rejectWithValue(e.message || "Failed to get ghost results");
958
+ } catch (error) {
959
+ return rejectWithValue(extractThunkErrorMessage(error, "Failed to get ghost results"));
674
960
  }
675
961
  }
676
962
  );
@@ -679,17 +965,17 @@ var stopGhostThunk = createAsyncThunk3(
679
965
  async ({ sessionId, apiUrl, apiKey }, { dispatch: dispatch2, getState, rejectWithValue }) => {
680
966
  try {
681
967
  const state = getState().ghost;
682
- const targetSession = sessionId || state.activeSessionId;
683
- if (!targetSession) throw new Error("No active Ghost session");
684
- const url = apiUrl || "https://api.forboc.ai";
685
- const data = await dispatch2(sdkApi.endpoints.postGhostStop.initiate({ sessionId: targetSession, apiUrl: url, apiKey })).unwrap();
968
+ const targetSession = requireJust(fromNullable(sessionId || state.activeSessionId), "No active Ghost session");
969
+ const url = resolveApiUrl(apiUrl);
970
+ requireApiKeyGuidance(url, apiKey);
971
+ const data = await dispatch2(api.endpoints.postGhostStop.initiate({ sessionId: targetSession, apiUrl: url, apiKey })).unwrap();
686
972
  return {
687
973
  stopped: data.stopped,
688
974
  status: data.stopStatus,
689
975
  sessionId: data.stopSessionId
690
976
  };
691
- } catch (e) {
692
- return rejectWithValue(e.message || "Failed to stop ghost session");
977
+ } catch (error) {
978
+ return rejectWithValue(extractThunkErrorMessage(error, "Failed to stop ghost session"));
693
979
  }
694
980
  }
695
981
  );
@@ -697,8 +983,9 @@ var getGhostHistoryThunk = createAsyncThunk3(
697
983
  "ghost/history",
698
984
  async ({ limit = 10, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
699
985
  try {
700
- const url = apiUrl || "https://api.forboc.ai";
701
- const data = await dispatch2(sdkApi.endpoints.getGhostHistory.initiate({ limit, apiUrl: url, apiKey })).unwrap();
986
+ const url = resolveApiUrl(apiUrl);
987
+ requireApiKeyGuidance(url, apiKey);
988
+ const data = await dispatch2(api.endpoints.getGhostHistory.initiate({ limit, apiUrl: url, apiKey })).unwrap();
702
989
  return (data.sessions || []).map((s) => ({
703
990
  sessionId: s.sessionId,
704
991
  testSuite: s.testSuite,
@@ -707,8 +994,8 @@ var getGhostHistoryThunk = createAsyncThunk3(
707
994
  status: s.status,
708
995
  passRate: s.passRate
709
996
  }));
710
- } catch (e) {
711
- return rejectWithValue(e.message || "Failed to get ghost history");
997
+ } catch (error) {
998
+ return rejectWithValue(extractThunkErrorMessage(error, "Failed to get ghost history"));
712
999
  }
713
1000
  }
714
1001
  );
@@ -743,7 +1030,7 @@ var ghostSlice = createSlice3({
743
1030
  state.status = "completed";
744
1031
  }).addCase(stopGhostThunk.fulfilled, (state, action) => {
745
1032
  if (action.payload.stopped) {
746
- state.status = "failed";
1033
+ state.status = "completed";
747
1034
  } else {
748
1035
  state.error = action.payload.status || "Ghost stop request did not stop a session";
749
1036
  }
@@ -757,8 +1044,8 @@ var ghostSlice = createSlice3({
757
1044
  var { clearGhostSession } = ghostSlice.actions;
758
1045
  var ghostSlice_default = ghostSlice.reducer;
759
1046
 
760
- // src/utils/sdkVersion.ts
761
- var SDK_VERSION = "0.6.1";
1047
+ // src/utils/version.ts
1048
+ var VERSION = "0.6.4";
762
1049
 
763
1050
  // src/utils/generateNPCId.ts
764
1051
  var generateNPCId = () => `ag_${Date.now().toString(36)}`;
@@ -839,7 +1126,8 @@ var npcSlice = createSlice4({
839
1126
  persona,
840
1127
  state: initialState5 || {},
841
1128
  history: [],
842
- isBlocked: false
1129
+ isBlocked: false,
1130
+ stateLog: [{ timestamp: Date.now(), delta: initialState5 || {}, state: initialState5 || {} }]
843
1131
  });
844
1132
  state.activeNpcId = id;
845
1133
  },
@@ -854,7 +1142,9 @@ var npcSlice = createSlice4({
854
1142
  const { id, delta } = action.payload;
855
1143
  const npc = state.entities[id];
856
1144
  if (npc) {
857
- npc.state = { ...npc.state, ...delta };
1145
+ const newState = { ...npc.state, ...delta };
1146
+ npc.state = newState;
1147
+ npc.stateLog.push({ timestamp: Date.now(), delta, state: newState });
858
1148
  }
859
1149
  },
860
1150
  addToHistory: (state, action) => {
@@ -923,8 +1213,9 @@ var initRemoteCortexThunk = createAsyncThunk4(
923
1213
  "cortex/initRemote",
924
1214
  async ({ model = "api-integrated", authKey, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
925
1215
  try {
926
- const url = apiUrl || "https://api.forboc.ai";
927
- const data = await dispatch2(sdkApi.endpoints.postCortexInit.initiate({
1216
+ const url = resolveApiUrl(apiUrl);
1217
+ requireApiKeyGuidance(url, apiKey);
1218
+ const data = await dispatch2(api.endpoints.postCortexInit.initiate({
928
1219
  request: { requestedModel: model, authKey },
929
1220
  apiUrl: url,
930
1221
  apiKey
@@ -935,8 +1226,8 @@ var initRemoteCortexThunk = createAsyncThunk4(
935
1226
  ready: data.state?.toLowerCase() === "ready",
936
1227
  engine: "remote"
937
1228
  };
938
- } catch (e) {
939
- return rejectWithValue(e.message || "Remote cortex init failed");
1229
+ } catch (error) {
1230
+ return rejectWithValue(extractThunkErrorMessage(error, "Remote cortex init failed"));
940
1231
  }
941
1232
  }
942
1233
  );
@@ -944,10 +1235,11 @@ var listCortexModelsThunk = createAsyncThunk4(
944
1235
  "cortex/listModels",
945
1236
  async ({ apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
946
1237
  try {
947
- const url = apiUrl || "https://api.forboc.ai";
948
- return await dispatch2(sdkApi.endpoints.getCortexModels.initiate({ apiUrl: url, apiKey })).unwrap();
949
- } catch (e) {
950
- return rejectWithValue(e.message || "Failed to list cortex models");
1238
+ const url = resolveApiUrl(apiUrl);
1239
+ requireApiKeyGuidance(url, apiKey);
1240
+ return await dispatch2(api.endpoints.getCortexModels.initiate({ apiUrl: url, apiKey })).unwrap();
1241
+ } catch (error) {
1242
+ return rejectWithValue(extractThunkErrorMessage(error, "Failed to list cortex models"));
951
1243
  }
952
1244
  }
953
1245
  );
@@ -955,7 +1247,8 @@ var completeRemoteThunk = createAsyncThunk4(
955
1247
  "cortex/completeRemote",
956
1248
  async ({ cortexId, prompt, options, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
957
1249
  try {
958
- const data = await dispatch2(sdkApi.endpoints.postCortexComplete.initiate({
1250
+ requireApiKeyGuidance(apiUrl, apiKey);
1251
+ const data = await dispatch2(api.endpoints.postCortexComplete.initiate({
959
1252
  cortexId,
960
1253
  prompt,
961
1254
  options,
@@ -963,8 +1256,8 @@ var completeRemoteThunk = createAsyncThunk4(
963
1256
  apiKey
964
1257
  })).unwrap();
965
1258
  return data.text;
966
- } catch (e) {
967
- return rejectWithValue(e.message || "Remote completing failed");
1259
+ } catch (error) {
1260
+ return rejectWithValue(extractThunkErrorMessage(error, "Remote completing failed"));
968
1261
  }
969
1262
  }
970
1263
  );
@@ -1156,8 +1449,8 @@ var directiveSlice_default = directiveSlice.reducer;
1156
1449
 
1157
1450
  // src/listeners.ts
1158
1451
  import { createListenerMiddleware } from "@reduxjs/toolkit";
1159
- var sdkListenerMiddleware = createListenerMiddleware();
1160
- var startAppListening = sdkListenerMiddleware.startListening.withTypes();
1452
+ var listenerMiddleware = createListenerMiddleware();
1453
+ var startAppListening = listenerMiddleware.startListening.withTypes();
1161
1454
  startAppListening({
1162
1455
  actionCreator: removeNPC,
1163
1456
  effect: async (action, listenerApi) => {
@@ -1174,11 +1467,38 @@ startAppListening({
1174
1467
  }
1175
1468
  });
1176
1469
 
1470
+ // src/runtimeRegistry.ts
1471
+ var createRuntimeRegistry = () => {
1472
+ const _store = {};
1473
+ return {
1474
+ get: (ns, key) => _store[ns]?.[key],
1475
+ set: (ns, key, value) => {
1476
+ if (!_store[ns]) _store[ns] = {};
1477
+ _store[ns][key] = value;
1478
+ },
1479
+ delete: (ns, key) => {
1480
+ if (_store[ns]) {
1481
+ delete _store[ns][key];
1482
+ return true;
1483
+ }
1484
+ return false;
1485
+ },
1486
+ has: (ns, key) => !!(_store[ns]?.[key] !== void 0),
1487
+ clear: (ns) => {
1488
+ if (ns) {
1489
+ delete _store[ns];
1490
+ } else {
1491
+ Object.keys(_store).forEach((k) => delete _store[k]);
1492
+ }
1493
+ }
1494
+ };
1495
+ };
1496
+
1177
1497
  // src/store.ts
1178
- var createSDKStore = (extraReducers = {}) => {
1498
+ var createRuntimeStore = (extraReducers = {}, registry = createRuntimeRegistry()) => {
1179
1499
  return configureStore({
1180
1500
  reducer: {
1181
- [sdkApi.reducerPath]: sdkApi.reducer,
1501
+ [api.reducerPath]: api.reducer,
1182
1502
  npc: npcSlice_default,
1183
1503
  cortex: cortexSlice_default,
1184
1504
  memory: memorySlice_default,
@@ -1189,46 +1509,120 @@ var createSDKStore = (extraReducers = {}) => {
1189
1509
  ...extraReducers
1190
1510
  },
1191
1511
  middleware: (getDefaultMiddleware) => getDefaultMiddleware({
1192
- serializableCheck: false
1193
- // Allow non-serializable for engine refs in specific slices if needed, though we try to keep them external
1194
- }).prepend(sdkListenerMiddleware.middleware).concat(sdkApi.middleware)
1512
+ thunk: { extraArgument: registry },
1513
+ serializableCheck: {
1514
+ ignoredActionPaths: [
1515
+ "meta.arg.cortex",
1516
+ "meta.arg.memory",
1517
+ "meta.arg.onProgress",
1518
+ "meta.baseQueryMeta.request",
1519
+ "meta.baseQueryMeta.response"
1520
+ ]
1521
+ }
1522
+ }).prepend(listenerMiddleware.middleware).concat(api.middleware)
1195
1523
  });
1196
1524
  };
1197
- var store = createSDKStore();
1525
+ var store = createRuntimeStore();
1198
1526
  var dispatch = store.dispatch;
1199
1527
 
1200
1528
  // src/thunks.ts
1201
1529
  import { createAsyncThunk as createAsyncThunk5 } from "@reduxjs/toolkit";
1202
- var extractThunkErrorMessage = (e) => {
1203
- if (typeof e === "string") return e;
1204
- if (e?.data?.message) return String(e.data.message);
1205
- if (e?.error) return String(e.error);
1206
- if (e?.message) return String(e.message);
1207
- return "Protocol processing failed";
1530
+
1531
+ // src/protocolHandlers.ts
1532
+ var persistMemoryRecursively = async (memory, instructions, index = 0) => !memory || index >= instructions.length ? void 0 : memory.store(instructions[index].text, instructions[index].type, instructions[index].importance).then(() => persistMemoryRecursively(memory, instructions, index + 1));
1533
+ var handleIdentifyActor = (ctx, nextTape, turn) => ctx.recurse(nextTape, {
1534
+ type: "IdentifyActorResult",
1535
+ actor: { npcId: ctx.npcId, persona: ctx.persona, data: nextTape.npcState }
1536
+ }, turn + 1);
1537
+ var handleQueryVector = async (ctx, instruction, nextTape, turn) => {
1538
+ ctx.dispatch(directiveReceived({
1539
+ id: ctx.directiveId,
1540
+ response: { memoryRecall: { query: instruction.query, limit: instruction.limit, threshold: instruction.threshold } }
1541
+ }));
1542
+ return ctx.memory ? ctx.memory.recall(instruction.query, instruction.limit, instruction.threshold).then((recalled) => ctx.recurse(nextTape, {
1543
+ type: "QueryVectorResult",
1544
+ memories: recalled.map((m) => ({ text: m.text, type: m.type, importance: m.importance, similarity: m.similarity }))
1545
+ }, turn + 1)) : ctx.rejectWithValue("API requested memory recall, but no memory engine is configured");
1546
+ };
1547
+ var handleExecuteInference = async (ctx, instruction, nextTape, turn) => {
1548
+ ctx.dispatch(contextComposed({ id: ctx.directiveId, prompt: instruction.prompt, constraints: instruction.constraints }));
1549
+ const generatedText = await ctx.cortex.complete(instruction.prompt, {
1550
+ maxTokens: instruction.constraints.maxTokens,
1551
+ temperature: instruction.constraints.temperature,
1552
+ stop: instruction.constraints.stop
1553
+ });
1554
+ return ctx.recurse(nextTape, {
1555
+ type: "ExecuteInferenceResult",
1556
+ generatedOutput: generatedText
1557
+ }, turn + 1);
1558
+ };
1559
+ var handleFinalize = async (ctx, finalize) => {
1560
+ ctx.dispatch(verdictValidated({
1561
+ id: ctx.directiveId,
1562
+ verdict: {
1563
+ valid: finalize.valid,
1564
+ signature: finalize.signature,
1565
+ memoryStore: finalize.memoryStore,
1566
+ stateDelta: finalize.stateTransform,
1567
+ action: finalize.action,
1568
+ dialogue: finalize.dialogue
1569
+ }
1570
+ }));
1571
+ return finalize.valid ? applyFinalizeSuccess(ctx, finalize) : applyFinalizeBlocked(ctx, finalize);
1208
1572
  };
1573
+ var applyFinalizeBlocked = (ctx, finalize) => {
1574
+ ctx.dispatch(blockAction({ id: ctx.npcId, reason: finalize.dialogue || "Validation Failed" }));
1575
+ return { dialogue: finalize.dialogue, action: finalize.action, thought: finalize.dialogue };
1576
+ };
1577
+ var applyFinalizeSuccess = async (ctx, finalize) => {
1578
+ if (finalize.memoryStore?.length && !ctx.memory) {
1579
+ return ctx.rejectWithValue("API returned memoryStore instructions, but no memory engine is configured");
1580
+ }
1581
+ await persistMemoryRecursively(ctx.memory, finalize.memoryStore || []);
1582
+ if (finalize.stateTransform) {
1583
+ ctx.dispatch(updateNPCState({ id: ctx.npcId, delta: finalize.stateTransform }));
1584
+ }
1585
+ ctx.dispatch(setLastAction({ id: ctx.npcId, action: finalize.action }));
1586
+ ctx.dispatch(addToHistory({ id: ctx.npcId, role: "user", content: ctx.text }));
1587
+ ctx.dispatch(addToHistory({ id: ctx.npcId, role: "assistant", content: finalize.dialogue }));
1588
+ return { dialogue: finalize.dialogue, action: finalize.action, thought: finalize.dialogue };
1589
+ };
1590
+ var dispatchInstruction = (ctx, instruction, nextTape, turn) => {
1591
+ const handlers = {
1592
+ "IdentifyActor": () => handleIdentifyActor(ctx, nextTape, turn),
1593
+ "QueryVector": () => handleQueryVector(ctx, instruction, nextTape, turn),
1594
+ "ExecuteInference": () => handleExecuteInference(ctx, instruction, nextTape, turn),
1595
+ "Finalize": () => handleFinalize(ctx, instruction)
1596
+ };
1597
+ const handler = handlers[instruction.type];
1598
+ return handler ? handler() : Promise.resolve(ctx.rejectWithValue("API returned unknown instruction type"));
1599
+ };
1600
+
1601
+ // src/thunks.ts
1602
+ var extractThunkErrorMessage2 = (e) => multiMatch(e, [
1603
+ [(e2) => typeof e2 === "string", (e2) => e2],
1604
+ [(e2) => !!e2?.data?.message, (e2) => String(e2.data.message)],
1605
+ [(e2) => !!e2?.error, (e2) => String(e2.error)],
1606
+ [(e2) => !!e2?.message, (e2) => String(e2.message)],
1607
+ [_, () => "Protocol processing failed"]
1608
+ ]).getOrElse("Protocol processing failed");
1609
+ var safeDispatch = async (promise) => promise.then((v) => right(v)).catch((e) => left(extractThunkErrorMessage2(e)));
1209
1610
  var processNPC = createAsyncThunk5(
1210
1611
  "npc/process",
1211
1612
  async ({ npcId: argNpcId, text, context = {}, apiUrl, apiKey, memory, cortex, persona: argPersona }, { getState, dispatch: dispatch2, rejectWithValue }) => {
1212
1613
  const stateNpcId = selectActiveNpcId(getState());
1213
1614
  const activeNpc = selectActiveNPC(getState());
1214
- const npcId = argNpcId || stateNpcId;
1215
- const persona = argPersona || activeNpc?.persona;
1216
1615
  const currentState = activeNpc?.state || {};
1217
- if (!npcId) {
1218
- return rejectWithValue("No npcId provided and no active NPC selected");
1219
- }
1220
- if (!persona) {
1221
- return rejectWithValue("No persona provided and no active NPC persona available");
1222
- }
1223
- if (!cortex) {
1224
- return rejectWithValue("No local cortex provided. SDK remote cortex fallback is disabled.");
1225
- }
1226
- if (argNpcId && argNpcId !== stateNpcId) {
1227
- dispatch2(setNPCInfo({ id: argNpcId, persona }));
1228
- }
1229
- const directiveId = `${npcId}:${Date.now()}`;
1230
- dispatch2(directiveRunStarted({ id: directiveId, npcId, observation: text }));
1616
+ let directiveId;
1231
1617
  try {
1618
+ const npcId = requireJust(fromNullable(argNpcId || stateNpcId), "No npcId provided and no active NPC selected");
1619
+ const persona = requireJust(fromNullable(argPersona || activeNpc?.persona), "No persona provided and no active NPC persona available");
1620
+ requireJust(fromNullable(cortex), "No local cortex provided. SDK remote cortex fallback is disabled.");
1621
+ if (argNpcId && argNpcId !== stateNpcId) {
1622
+ dispatch2(setNPCInfo({ id: argNpcId, persona }));
1623
+ }
1624
+ directiveId = `${npcId}:${Date.now()}`;
1625
+ dispatch2(directiveRunStarted({ id: directiveId, npcId, observation: text }));
1232
1626
  const initialTape = {
1233
1627
  observation: text,
1234
1628
  context,
@@ -1237,104 +1631,33 @@ var processNPC = createAsyncThunk5(
1237
1631
  memories: [],
1238
1632
  vectorQueried: false
1239
1633
  };
1240
- const maxTurns = 12;
1241
- const persistMemoryInstructionsRecursively = async (instructions, index = 0) => {
1242
- if (!memory || index >= instructions.length) {
1243
- return;
1244
- }
1245
- const inst = instructions[index];
1246
- await memory.store(inst.text, inst.type, inst.importance);
1247
- await persistMemoryInstructionsRecursively(instructions, index + 1);
1248
- };
1249
- const runProtocolRecursively = async (tape, lastResult, turn) => {
1250
- if (turn >= maxTurns) {
1251
- return rejectWithValue(`Protocol loop exceeded max turns (${maxTurns})`);
1634
+ const runProtocol = async (tape, lastResult, turn) => {
1635
+ if (turn >= 12) {
1636
+ return rejectWithValue("Protocol loop exceeded max turns (12)");
1252
1637
  }
1253
1638
  const request = { tape, lastResult };
1254
1639
  const processResult = await dispatch2(
1255
- sdkApi.endpoints.postNpcProcess.initiate({ npcId, request, apiUrl, apiKey })
1640
+ api.endpoints.postNpcProcess.initiate({ npcId, request, apiUrl, apiKey })
1256
1641
  ).unwrap();
1257
- const nextTape = processResult.tape;
1258
- const instruction = processResult.instruction;
1259
- if (instruction.type === "IdentifyActor") {
1260
- return runProtocolRecursively(nextTape, {
1261
- type: "IdentifyActorResult",
1262
- actor: {
1263
- npcId,
1264
- persona,
1265
- data: nextTape.npcState
1266
- }
1267
- }, turn + 1);
1268
- }
1269
- if (instruction.type === "QueryVector") {
1270
- dispatch2(directiveReceived({
1271
- id: directiveId,
1272
- response: { memoryRecall: { query: instruction.query, limit: instruction.limit, threshold: instruction.threshold } }
1273
- }));
1274
- if (!memory) {
1275
- return rejectWithValue("API requested memory recall, but no memory engine is configured");
1276
- }
1277
- const recalled = await memory.recall(instruction.query, instruction.limit, instruction.threshold);
1278
- return runProtocolRecursively(nextTape, {
1279
- type: "QueryVectorResult",
1280
- memories: recalled.map((m) => ({ text: m.text, type: m.type, importance: m.importance, similarity: m.similarity }))
1281
- }, turn + 1);
1282
- }
1283
- if (instruction.type === "ExecuteInference") {
1284
- dispatch2(contextComposed({ id: directiveId, prompt: instruction.prompt, constraints: instruction.constraints }));
1285
- const generatedText = await cortex.complete(instruction.prompt, {
1286
- maxTokens: instruction.constraints.maxTokens,
1287
- temperature: instruction.constraints.temperature,
1288
- stop: instruction.constraints.stop
1289
- });
1290
- return runProtocolRecursively(nextTape, {
1291
- type: "ExecuteInferenceResult",
1292
- generatedOutput: generatedText
1293
- }, turn + 1);
1294
- }
1295
- if (instruction.type === "Finalize") {
1296
- const finalize = instruction;
1297
- dispatch2(verdictValidated({
1298
- id: directiveId,
1299
- verdict: {
1300
- valid: finalize.valid,
1301
- signature: finalize.signature,
1302
- memoryStore: finalize.memoryStore,
1303
- stateDelta: finalize.stateTransform,
1304
- action: finalize.action,
1305
- dialogue: finalize.dialogue
1306
- }
1307
- }));
1308
- if (!finalize.valid) {
1309
- dispatch2(blockAction({ id: npcId, reason: finalize.dialogue || "Validation Failed" }));
1310
- return {
1311
- dialogue: finalize.dialogue,
1312
- action: finalize.action,
1313
- thought: finalize.dialogue
1314
- };
1315
- }
1316
- if (finalize.memoryStore?.length && !memory) {
1317
- return rejectWithValue("API returned memoryStore instructions, but no memory engine is configured");
1318
- }
1319
- await persistMemoryInstructionsRecursively(finalize.memoryStore || []);
1320
- if (finalize.stateTransform) {
1321
- dispatch2(updateNPCState({ id: npcId, delta: finalize.stateTransform }));
1322
- }
1323
- dispatch2(setLastAction({ id: npcId, action: finalize.action }));
1324
- dispatch2(addToHistory({ id: npcId, role: "user", content: text }));
1325
- dispatch2(addToHistory({ id: npcId, role: "assistant", content: finalize.dialogue }));
1326
- return {
1327
- dialogue: finalize.dialogue,
1328
- action: finalize.action,
1329
- thought: finalize.dialogue
1330
- };
1331
- }
1332
- return rejectWithValue("API returned unknown instruction type");
1642
+ const ctx = {
1643
+ npcId,
1644
+ persona,
1645
+ text,
1646
+ directiveId,
1647
+ memory,
1648
+ cortex,
1649
+ dispatch: dispatch2,
1650
+ rejectWithValue,
1651
+ recurse: runProtocol
1652
+ };
1653
+ return dispatchInstruction(ctx, processResult.instruction, processResult.tape, turn);
1333
1654
  };
1334
- return runProtocolRecursively(initialTape, void 0, 0);
1655
+ return runProtocol(initialTape, void 0, 0);
1335
1656
  } catch (e) {
1336
- const message = extractThunkErrorMessage(e);
1337
- dispatch2(directiveRunFailed({ id: directiveId, error: String(message) }));
1657
+ const message = extractThunkErrorMessage2(e);
1658
+ if (directiveId) {
1659
+ dispatch2(directiveRunFailed({ id: directiveId, error: String(message) }));
1660
+ }
1338
1661
  return rejectWithValue(String(message));
1339
1662
  }
1340
1663
  }
@@ -1344,8 +1667,7 @@ var localExportSoulThunk = createAsyncThunk5(
1344
1667
  async ({ id, memory }, { getState }) => {
1345
1668
  const state = getState().npc;
1346
1669
  const npcId = id || state.activeNpcId;
1347
- const npc = state.entities[npcId];
1348
- if (!npc) throw new Error(`NPC ${npcId} not found`);
1670
+ const npc = requireJust(fromNullable(state.entities[npcId]), `NPC ${npcId} not found`);
1349
1671
  const memories = memory ? await memory.export() : [];
1350
1672
  return exportToSoul(npcId, "NPC", npc.persona, npc.state, memories);
1351
1673
  }
@@ -1353,76 +1675,98 @@ var localExportSoulThunk = createAsyncThunk5(
1353
1675
  var checkApiStatusThunk = createAsyncThunk5(
1354
1676
  "system/checkApiStatus",
1355
1677
  async ({ apiUrl }, { dispatch: dispatch2, rejectWithValue }) => {
1356
- try {
1357
- return await dispatch2(sdkApi.endpoints.getApiStatus.initiate({ apiUrl })).unwrap();
1358
- } catch (e) {
1359
- return rejectWithValue(e?.message || "Connection failed");
1360
- }
1678
+ const result = await safeDispatch(dispatch2(api.endpoints.getApiStatus.initiate({ apiUrl })).unwrap());
1679
+ return result.match({
1680
+ left: (e) => rejectWithValue(e),
1681
+ right: (v) => v
1682
+ });
1361
1683
  }
1362
1684
  );
1363
1685
  var listMemoryRemoteThunk = createAsyncThunk5(
1364
1686
  "memory/listRemote",
1365
1687
  async ({ npcId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
1366
- try {
1367
- const data = await dispatch2(sdkApi.endpoints.getMemoryList.initiate({ npcId, apiUrl, apiKey })).unwrap();
1368
- return data || [];
1369
- } catch (e) {
1370
- return rejectWithValue(e?.message || "Failed to list memories");
1371
- }
1688
+ const result = await safeDispatch(dispatch2(api.endpoints.getMemoryList.initiate({ npcId, apiUrl, apiKey })).unwrap());
1689
+ return result.match({
1690
+ left: (e) => rejectWithValue(e),
1691
+ right: (v) => v || []
1692
+ });
1372
1693
  }
1373
1694
  );
1374
1695
  var recallMemoryRemoteThunk = createAsyncThunk5(
1375
1696
  "memory/recallRemote",
1376
1697
  async ({ npcId, query, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
1377
- try {
1378
- const data = await dispatch2(
1379
- sdkApi.endpoints.postMemoryRecall.initiate({
1380
- npcId,
1381
- request: { query },
1382
- apiUrl,
1383
- apiKey
1384
- })
1385
- ).unwrap();
1386
- return data || [];
1387
- } catch (e) {
1388
- return rejectWithValue(e?.message || "Failed to recall memories");
1389
- }
1698
+ const result = await safeDispatch(dispatch2(
1699
+ api.endpoints.postMemoryRecall.initiate({ npcId, request: { query }, apiUrl, apiKey })
1700
+ ).unwrap());
1701
+ return result.match({
1702
+ left: (e) => rejectWithValue(e),
1703
+ right: (v) => v || []
1704
+ });
1390
1705
  }
1391
1706
  );
1392
1707
  var storeMemoryRemoteThunk = createAsyncThunk5(
1393
1708
  "memory/storeRemote",
1394
1709
  async ({ npcId, observation, importance = 0.8, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
1395
- try {
1396
- return await dispatch2(
1397
- sdkApi.endpoints.postMemoryStore.initiate({
1398
- npcId,
1399
- request: { observation, importance },
1400
- apiUrl,
1401
- apiKey
1402
- })
1403
- ).unwrap();
1404
- } catch (e) {
1405
- return rejectWithValue(e?.message || "Failed to store memory");
1406
- }
1710
+ const result = await safeDispatch(dispatch2(
1711
+ api.endpoints.postMemoryStore.initiate({ npcId, request: { observation, importance }, apiUrl, apiKey })
1712
+ ).unwrap());
1713
+ return result.match({
1714
+ left: (e) => rejectWithValue(e),
1715
+ right: (v) => v
1716
+ });
1407
1717
  }
1408
1718
  );
1409
1719
  var clearMemoryRemoteThunk = createAsyncThunk5(
1410
1720
  "memory/clearRemote",
1411
1721
  async ({ npcId, apiUrl, apiKey }, { dispatch: dispatch2, rejectWithValue }) => {
1412
- try {
1413
- return await dispatch2(
1414
- sdkApi.endpoints.deleteMemoryClear.initiate({ npcId, apiUrl, apiKey })
1415
- ).unwrap();
1416
- } catch (e) {
1417
- return rejectWithValue(e?.message || "Failed to clear memories");
1418
- }
1722
+ const result = await safeDispatch(dispatch2(
1723
+ api.endpoints.deleteMemoryClear.initiate({ npcId, apiUrl, apiKey })
1724
+ ).unwrap());
1725
+ return result.match({
1726
+ left: (e) => rejectWithValue(e),
1727
+ right: (v) => v
1728
+ });
1419
1729
  }
1420
1730
  );
1731
+
1732
+ // src/handlers/arweave.ts
1733
+ var handler_ArweaveUpload = async (instruction, maxRetries = 3) => store.dispatch(
1734
+ api.endpoints.postArweaveUpload.initiate({ ...instruction, maxRetries })
1735
+ ).unwrap();
1736
+ var handler_ArweaveDownload = async (instruction) => store.dispatch(
1737
+ api.endpoints.postArweaveDownload.initiate(instruction)
1738
+ ).unwrap();
1739
+
1740
+ // src/configOps.ts
1741
+ var normalizeStatusUrl = (apiUrl) => apiUrl.endsWith("/status") ? apiUrl : `${apiUrl.replace(/\/+$/, "")}/status`;
1742
+ var checkApiConnectivity = async (apiUrl = DEFAULT_API_URL) => {
1743
+ try {
1744
+ const res = await fetch(normalizeStatusUrl(apiUrl), { signal: AbortSignal.timeout(1500) });
1745
+ return res.ok;
1746
+ } catch {
1747
+ return false;
1748
+ }
1749
+ };
1750
+ var resolveReachableApiUrl = async (apiUrl) => {
1751
+ if (apiUrl) return await checkApiConnectivity(apiUrl) ? apiUrl : null;
1752
+ if (await checkApiConnectivity(DEFAULT_API_URL)) return DEFAULT_API_URL;
1753
+ if (await checkApiConnectivity(PRODUCTION_API_URL)) return PRODUCTION_API_URL;
1754
+ return null;
1755
+ };
1756
+ var resolveApiUrlWithFallback = async (apiUrl) => {
1757
+ if (apiUrl) return apiUrl;
1758
+ return await resolveReachableApiUrl() || PRODUCTION_API_URL;
1759
+ };
1421
1760
  export {
1422
- SDK_VERSION,
1761
+ DEFAULT_API_URL,
1762
+ PRODUCTION_API_URL,
1763
+ VERSION,
1764
+ _,
1423
1765
  addToHistory,
1766
+ api,
1424
1767
  blockAction,
1425
1768
  bridgeSlice,
1769
+ checkApiConnectivity,
1426
1770
  checkApiStatusThunk,
1427
1771
  clearBlock,
1428
1772
  clearBridgeValidation,
@@ -1431,13 +1775,17 @@ export {
1431
1775
  clearMemoryRemoteThunk,
1432
1776
  clearSoulState,
1433
1777
  completeRemoteThunk,
1778
+ compose,
1434
1779
  contextComposed,
1435
1780
  cortexInitFailed,
1436
1781
  cortexInitStart,
1437
1782
  cortexInitSuccess,
1438
1783
  cortexSlice,
1784
+ createDispatcher,
1439
1785
  createInitialState,
1440
- createSDKStore,
1786
+ createRuntimeRegistry,
1787
+ createRuntimeStore,
1788
+ curry,
1441
1789
  delay,
1442
1790
  deleteRulesetThunk,
1443
1791
  directiveReceived,
@@ -1445,7 +1793,12 @@ export {
1445
1793
  directiveRunStarted,
1446
1794
  directiveSlice,
1447
1795
  dispatch,
1796
+ ebind,
1797
+ efmap,
1798
+ ematch,
1448
1799
  exportToSoul,
1800
+ fmap,
1801
+ fromNullable,
1449
1802
  generateNPCId,
1450
1803
  getBridgeRulesThunk,
1451
1804
  getGhostHistoryThunk,
@@ -1453,15 +1806,25 @@ export {
1453
1806
  getGhostStatusThunk,
1454
1807
  getSoulListThunk,
1455
1808
  ghostSlice,
1809
+ handler_ArweaveDownload,
1810
+ handler_ArweaveUpload,
1456
1811
  importNpcFromSoulThunk,
1457
1812
  importSoulFromArweaveThunk,
1458
1813
  initRemoteCortexThunk,
1814
+ isJust,
1815
+ isLeft,
1816
+ isNothing,
1817
+ isRight,
1818
+ just,
1819
+ left,
1459
1820
  listCortexModelsThunk,
1460
1821
  listMemoryRemoteThunk,
1461
1822
  listRulePresetsThunk,
1462
1823
  listRulesetsThunk,
1463
1824
  loadBridgePresetThunk,
1464
1825
  localExportSoulThunk,
1826
+ match,
1827
+ mbind,
1465
1828
  memoise,
1466
1829
  memoiseAsync,
1467
1830
  memoryClear,
@@ -1472,14 +1835,21 @@ export {
1472
1835
  memoryStoreFailed,
1473
1836
  memoryStoreStart,
1474
1837
  memoryStoreSuccess,
1838
+ multiMatch,
1839
+ nothing,
1475
1840
  npcSlice,
1841
+ orElse,
1476
1842
  pipe,
1477
1843
  processNPC,
1478
1844
  recallMemoryRemoteThunk,
1479
1845
  registerRulesetThunk,
1480
1846
  remoteExportSoulThunk,
1481
1847
  removeNPC,
1482
- sdkApi,
1848
+ requireJust,
1849
+ resolveApiUrl,
1850
+ resolveApiUrlWithFallback,
1851
+ resolveReachableApiUrl,
1852
+ right,
1483
1853
  selectActiveDirective,
1484
1854
  selectActiveDirectiveId,
1485
1855
  selectActiveNPC,