@forbocai/core 0.5.7 → 0.5.9
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/ans104-QFXL554Z.mjs +190 -0
- package/dist/chunk-M3F3ED7H.mjs +83 -0
- package/dist/index.d.mts +90 -285
- package/dist/index.d.ts +90 -285
- package/dist/index.js +314 -987
- package/dist/index.mjs +239 -761
- package/dist/soul-QXKV5H2R.mjs +20 -0
- package/package.json +2 -7
package/dist/index.mjs
CHANGED
|
@@ -1,170 +1,123 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
createSoul,
|
|
3
|
+
createSoulInstance,
|
|
4
|
+
deserializeSoul,
|
|
5
|
+
exportSoul,
|
|
6
|
+
getSoulList,
|
|
7
|
+
importSoulFromArweave,
|
|
8
|
+
serializeSoul,
|
|
9
|
+
validateSoul
|
|
10
|
+
} from "./chunk-M3F3ED7H.mjs";
|
|
4
11
|
|
|
5
12
|
// src/agent.ts
|
|
6
|
-
var createInitialState = (partial) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
var createInitialState = (partial) => ({ ...partial });
|
|
14
|
+
var updateAgentState = (currentState, updates) => ({
|
|
15
|
+
...currentState,
|
|
16
|
+
...updates
|
|
17
|
+
});
|
|
18
|
+
var exportToSoul = (agentId, name, persona, state, memories) => ({
|
|
19
|
+
id: agentId,
|
|
20
|
+
version: "1.0.0",
|
|
21
|
+
name,
|
|
22
|
+
persona,
|
|
23
|
+
memories: [...memories],
|
|
24
|
+
state: { ...state }
|
|
25
|
+
});
|
|
26
|
+
var storeMemoriesRecursive = async (memory, instructions, index = 0) => {
|
|
27
|
+
if (index >= instructions.length) return;
|
|
28
|
+
const { text, type, importance } = instructions[index];
|
|
29
|
+
await memory.store(text, type, importance).catch((e) => console.warn("Memory store failed:", e));
|
|
30
|
+
return storeMemoriesRecursive(memory, instructions, index + 1);
|
|
24
31
|
};
|
|
25
32
|
var createAgent = (config) => {
|
|
26
|
-
let
|
|
33
|
+
let _state = createInitialState(config.initialState);
|
|
27
34
|
const cortex = config.cortex;
|
|
28
35
|
const apiUrl = config.apiUrl || "https://api.forboc.ai";
|
|
29
36
|
const agentId = config.id || "agent-" + Math.random().toString(36).substring(7);
|
|
30
37
|
const authHeaders = config.apiKey ? { "Content-Type": "application/json", "Authorization": `Bearer ${config.apiKey}` } : { "Content-Type": "application/json" };
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const setAgentState = (newState) => {
|
|
35
|
-
state = newState;
|
|
38
|
+
const getState = () => ({ ..._state });
|
|
39
|
+
const setState = (newState) => {
|
|
40
|
+
_state = newState;
|
|
36
41
|
};
|
|
37
42
|
const process = async (input, context = {}) => {
|
|
38
|
-
const currentState =
|
|
39
|
-
const directiveBody = {
|
|
40
|
-
observation: input,
|
|
41
|
-
agentState: currentState,
|
|
42
|
-
context
|
|
43
|
-
};
|
|
43
|
+
const currentState = getState();
|
|
44
44
|
const dirRes = await fetch(`${apiUrl}/agents/${agentId}/directive`, {
|
|
45
45
|
method: "POST",
|
|
46
46
|
headers: authHeaders,
|
|
47
|
-
body: JSON.stringify(
|
|
47
|
+
body: JSON.stringify({ observation: input, agentState: currentState, context })
|
|
48
48
|
});
|
|
49
|
-
if (!dirRes.ok) {
|
|
50
|
-
throw new Error(`API Directive Error: ${dirRes.status}`);
|
|
51
|
-
}
|
|
49
|
+
if (!dirRes.ok) throw new Error(`API Directive Error: ${dirRes.status}`);
|
|
52
50
|
const directiveData = await dirRes.json();
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
directiveData.memoryRecall.limit,
|
|
59
|
-
directiveData.memoryRecall.threshold
|
|
60
|
-
);
|
|
61
|
-
recalledMemories = rawMemories.map((m) => ({
|
|
62
|
-
text: m.text,
|
|
63
|
-
type: m.type,
|
|
64
|
-
importance: m.importance,
|
|
65
|
-
similarity: void 0
|
|
66
|
-
}));
|
|
67
|
-
} catch (e) {
|
|
68
|
-
console.warn("Memory recall failed, continuing with empty memories:", e);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
const contextBody = {
|
|
72
|
-
memories: recalledMemories,
|
|
73
|
-
observation: input,
|
|
74
|
-
agentState: currentState
|
|
75
|
-
};
|
|
51
|
+
const recalledMemories = config.memory && directiveData.memoryRecall ? await config.memory.recall(
|
|
52
|
+
directiveData.memoryRecall.query,
|
|
53
|
+
directiveData.memoryRecall.limit,
|
|
54
|
+
directiveData.memoryRecall.threshold
|
|
55
|
+
).then((mems) => mems.map((m) => ({ text: m.text, type: m.type, importance: m.importance, similarity: void 0 }))).catch(() => []) : [];
|
|
76
56
|
const ctxRes = await fetch(`${apiUrl}/agents/${agentId}/context`, {
|
|
77
57
|
method: "POST",
|
|
78
58
|
headers: authHeaders,
|
|
79
|
-
body: JSON.stringify(
|
|
59
|
+
body: JSON.stringify({ memories: recalledMemories, observation: input, agentState: currentState })
|
|
80
60
|
});
|
|
81
|
-
if (!ctxRes.ok) {
|
|
82
|
-
throw new Error(`API Context Error: ${ctxRes.status}`);
|
|
83
|
-
}
|
|
61
|
+
if (!ctxRes.ok) throw new Error(`API Context Error: ${ctxRes.status}`);
|
|
84
62
|
const contextData = await ctxRes.json();
|
|
85
63
|
const generatedText = await cortex.complete(contextData.prompt, {
|
|
86
64
|
maxTokens: contextData.constraints.maxTokens,
|
|
87
65
|
temperature: contextData.constraints.temperature,
|
|
88
66
|
stop: contextData.constraints.stop
|
|
89
67
|
});
|
|
90
|
-
const verdictBody = {
|
|
91
|
-
generatedOutput: generatedText,
|
|
92
|
-
observation: input,
|
|
93
|
-
agentState: currentState
|
|
94
|
-
};
|
|
95
68
|
const verRes = await fetch(`${apiUrl}/agents/${agentId}/verdict`, {
|
|
96
69
|
method: "POST",
|
|
97
70
|
headers: authHeaders,
|
|
98
|
-
body: JSON.stringify(
|
|
71
|
+
body: JSON.stringify({ generatedOutput: generatedText, observation: input, agentState: currentState })
|
|
99
72
|
});
|
|
100
|
-
if (!verRes.ok) {
|
|
101
|
-
throw new Error(`API Verdict Error: ${verRes.status}`);
|
|
102
|
-
}
|
|
73
|
+
if (!verRes.ok) throw new Error(`API Verdict Error: ${verRes.status}`);
|
|
103
74
|
const verdictData = await verRes.json();
|
|
104
75
|
if (!verdictData.valid) {
|
|
105
|
-
return {
|
|
106
|
-
dialogue: "... [Action Blocked by Protocol]",
|
|
107
|
-
action: { type: "BLOCKED", reason: "API Validation Failed" }
|
|
108
|
-
};
|
|
76
|
+
return { dialogue: "... [Blocked]", action: { type: "BLOCKED", reason: "Validation Failed" } };
|
|
109
77
|
}
|
|
110
|
-
if (config.memory &&
|
|
111
|
-
|
|
112
|
-
config.memory.store(instruction.text, instruction.type, instruction.importance).catch((e) => console.warn("Memory store failed:", e));
|
|
113
|
-
}
|
|
78
|
+
if (config.memory && verdictData.memoryStore) {
|
|
79
|
+
storeMemoriesRecursive(config.memory, verdictData.memoryStore);
|
|
114
80
|
}
|
|
115
|
-
if (verdictData.stateDelta
|
|
116
|
-
|
|
81
|
+
if (verdictData.stateDelta) {
|
|
82
|
+
setState(updateAgentState(_state, verdictData.stateDelta));
|
|
117
83
|
}
|
|
118
84
|
return {
|
|
119
85
|
dialogue: generatedText,
|
|
120
|
-
action: verdictData.action ? {
|
|
121
|
-
...verdictData.action,
|
|
122
|
-
signature: verdictData.signature
|
|
123
|
-
} : void 0,
|
|
86
|
+
action: verdictData.action ? { ...verdictData.action, signature: verdictData.signature } : void 0,
|
|
124
87
|
thought: generatedText
|
|
125
88
|
};
|
|
126
89
|
};
|
|
127
90
|
const speak = async (message, context = {}) => {
|
|
128
|
-
const currentState = getAgentState();
|
|
129
|
-
const speakBody = {
|
|
130
|
-
speakMessage: message,
|
|
131
|
-
speakContext: Object.keys(context).length > 0 ? context : void 0,
|
|
132
|
-
speakAgentState: currentState
|
|
133
|
-
};
|
|
134
91
|
const res = await fetch(`${apiUrl}/agents/${agentId}/speak`, {
|
|
135
92
|
method: "POST",
|
|
136
93
|
headers: authHeaders,
|
|
137
|
-
body: JSON.stringify(
|
|
94
|
+
body: JSON.stringify({ speakMessage: message, speakContext: context, speakAgentState: getState() })
|
|
138
95
|
});
|
|
139
|
-
if (!res.ok) {
|
|
140
|
-
throw new Error(`API Speak Error: ${res.status}`);
|
|
141
|
-
}
|
|
96
|
+
if (!res.ok) throw new Error(`API Speak Error: ${res.status}`);
|
|
142
97
|
const data = await res.json();
|
|
143
|
-
if (data.speakHistory) {
|
|
144
|
-
state = updateAgentState(state, { conversationHistory: data.speakHistory });
|
|
145
|
-
}
|
|
98
|
+
if (data.speakHistory) setState(updateAgentState(_state, { conversationHistory: data.speakHistory }));
|
|
146
99
|
return data.speakReply;
|
|
147
100
|
};
|
|
148
|
-
const
|
|
101
|
+
const dialogue = async (message, context = []) => {
|
|
102
|
+
const res = await fetch(`${apiUrl}/agents/${agentId}/dialogue`, {
|
|
103
|
+
method: "POST",
|
|
104
|
+
headers: authHeaders,
|
|
105
|
+
body: JSON.stringify({ diagMessage: message, diagContext: context })
|
|
106
|
+
});
|
|
107
|
+
if (!res.ok) throw new Error(`API Dialogue Error: ${res.status}`);
|
|
108
|
+
const data = await res.json();
|
|
109
|
+
return data.diagReply;
|
|
110
|
+
};
|
|
149
111
|
const exportSoul2 = async () => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
try {
|
|
153
|
-
exportedMemories = await config.memory.export();
|
|
154
|
-
} catch (e) {
|
|
155
|
-
console.warn("Memory export failed, exporting with empty memories:", e);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
return exportToSoul(agentId, "Agent", config.persona, state, exportedMemories);
|
|
112
|
+
const memories = config.memory ? await config.memory.export().catch(() => []) : [];
|
|
113
|
+
return exportToSoul(agentId, "Agent", config.persona, _state, memories);
|
|
159
114
|
};
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
getState: getAgentState,
|
|
165
|
-
setState: setAgentState,
|
|
166
|
-
export: exportSoul2
|
|
115
|
+
const exportSoulToArweave = async (soulConfig) => {
|
|
116
|
+
const soul = await exportSoul2();
|
|
117
|
+
const { exportSoul: exportFunc } = await import("./soul-QXKV5H2R.mjs");
|
|
118
|
+
return exportFunc(agentId, soul, { ...soulConfig, apiUrl });
|
|
167
119
|
};
|
|
120
|
+
return { process, speak, dialogue, reply: speak, getState, setState, export: exportSoul2, exportSoul: exportSoulToArweave };
|
|
168
121
|
};
|
|
169
122
|
var fromSoul = async (soul, cortex, memory) => {
|
|
170
123
|
const agent = createAgent({
|
|
@@ -174,412 +127,177 @@ var fromSoul = async (soul, cortex, memory) => {
|
|
|
174
127
|
persona: soul.persona,
|
|
175
128
|
initialState: soul.state
|
|
176
129
|
});
|
|
177
|
-
if (memory && soul.memories && soul.memories.length > 0
|
|
178
|
-
|
|
179
|
-
await memory.import(soul.memories);
|
|
180
|
-
} catch (e) {
|
|
181
|
-
console.warn("Memory hydration failed, continuing without memories:", e);
|
|
182
|
-
}
|
|
130
|
+
if (memory && soul.memories && soul.memories.length > 0) {
|
|
131
|
+
await memory.import(soul.memories).catch((e) => console.warn("Memory hydration failed:", e));
|
|
183
132
|
}
|
|
184
133
|
return agent;
|
|
185
134
|
};
|
|
186
135
|
|
|
187
136
|
// src/bridge.ts
|
|
188
137
|
var createBridge = (config = {}) => {
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
...config
|
|
192
|
-
};
|
|
193
|
-
const rules = /* @__PURE__ */ new Map();
|
|
194
|
-
if (config.customRules) {
|
|
195
|
-
config.customRules.forEach((rule) => rules.set(rule.id, rule));
|
|
196
|
-
}
|
|
197
|
-
const validateRemote = async (action) => {
|
|
198
|
-
const response = await fetch(`${effectiveConfig.apiUrl}/bridge/validate`, {
|
|
199
|
-
method: "POST",
|
|
200
|
-
headers: { "Content-Type": "application/json" },
|
|
201
|
-
body: JSON.stringify({
|
|
202
|
-
actionType: action.type,
|
|
203
|
-
payload: JSON.stringify(action.payload || {})
|
|
204
|
-
})
|
|
205
|
-
});
|
|
206
|
-
if (!response.ok) {
|
|
207
|
-
throw new Error(`API validation failed: ${response.statusText}`);
|
|
208
|
-
}
|
|
209
|
-
const data = await response.json();
|
|
210
|
-
return {
|
|
211
|
-
valid: data.valid,
|
|
212
|
-
reason: data.reason
|
|
213
|
-
};
|
|
214
|
-
};
|
|
138
|
+
const apiUrl = config.apiUrl || "https://api.forboc.ai";
|
|
139
|
+
const agentId = config.agentId;
|
|
215
140
|
const validate = async (action, context = {}) => {
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
if (!
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
reason: `Unknown action type '${action.type}' in strict mode`,
|
|
227
|
-
correctedAction: { ...action, type: "IDLE", reason: "Unknown action type" }
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
let currentAction = action;
|
|
232
|
-
for (const rule of applicableRules) {
|
|
233
|
-
const result = rule.validate(currentAction, context);
|
|
234
|
-
if (!result.valid) {
|
|
235
|
-
return result;
|
|
236
|
-
}
|
|
237
|
-
if (result.correctedAction) {
|
|
238
|
-
currentAction = result.correctedAction;
|
|
141
|
+
const endpoint = agentId ? `${apiUrl}/bridge/validate/${agentId}` : `${apiUrl}/bridge/validate`;
|
|
142
|
+
try {
|
|
143
|
+
const response = await fetch(endpoint, {
|
|
144
|
+
method: "POST",
|
|
145
|
+
headers: { "Content-Type": "application/json" },
|
|
146
|
+
body: JSON.stringify({ action, context })
|
|
147
|
+
});
|
|
148
|
+
if (!response.ok) {
|
|
149
|
+
const error = await response.text();
|
|
150
|
+
throw new Error(`Bridge validation failed: ${error}`);
|
|
239
151
|
}
|
|
152
|
+
const data = await response.json();
|
|
153
|
+
return data.brResult || data;
|
|
154
|
+
} catch (e) {
|
|
155
|
+
console.error("[Bridge] Validation error:", e);
|
|
156
|
+
return {
|
|
157
|
+
valid: false,
|
|
158
|
+
reason: `Network error reaching validation API: ${e instanceof Error ? e.message : String(e)}`
|
|
159
|
+
};
|
|
240
160
|
}
|
|
241
|
-
return {
|
|
242
|
-
valid: true,
|
|
243
|
-
correctedAction: currentAction !== action ? currentAction : void 0
|
|
244
|
-
};
|
|
245
|
-
};
|
|
246
|
-
const registerRule = (rule) => {
|
|
247
|
-
rules.set(rule.id, rule);
|
|
248
|
-
};
|
|
249
|
-
const listRules = () => {
|
|
250
|
-
return Array.from(rules.values());
|
|
251
161
|
};
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
validate,
|
|
257
|
-
registerRule,
|
|
258
|
-
listRules,
|
|
259
|
-
removeRule
|
|
162
|
+
const listRulesets = async () => {
|
|
163
|
+
const response = await fetch(`${apiUrl}/rules`);
|
|
164
|
+
if (!response.ok) return [];
|
|
165
|
+
return response.json();
|
|
260
166
|
};
|
|
167
|
+
return { validate, listRulesets };
|
|
261
168
|
};
|
|
262
|
-
var validateAction = (action,
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
169
|
+
var validateAction = async (action, context = {}, config = {}) => {
|
|
170
|
+
const bridge = createBridge(config);
|
|
171
|
+
return bridge.validate(action, context);
|
|
172
|
+
};
|
|
173
|
+
var loadPreset = async (presetName, apiUrl = "https://api.forboc.ai") => {
|
|
174
|
+
const response = await fetch(`${apiUrl}/rules/presets/${presetName}`, {
|
|
175
|
+
method: "POST"
|
|
176
|
+
});
|
|
177
|
+
if (!response.ok) {
|
|
178
|
+
throw new Error(`Failed to load preset '${presetName}': ${response.statusText}`);
|
|
270
179
|
}
|
|
271
|
-
return
|
|
180
|
+
return response.json();
|
|
272
181
|
};
|
|
273
182
|
|
|
274
|
-
// src/
|
|
275
|
-
var
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
183
|
+
// src/utils.ts
|
|
184
|
+
var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
185
|
+
var pipe = (...fns) => (initialValue) => fns.reduce((acc, fn) => fn(acc), initialValue);
|
|
186
|
+
var memoiseAsync = (fn) => {
|
|
187
|
+
let cached = null;
|
|
188
|
+
let promise = null;
|
|
189
|
+
return () => {
|
|
190
|
+
if (cached) return Promise.resolve(cached);
|
|
191
|
+
if (promise) return promise;
|
|
192
|
+
promise = fn().then((value) => {
|
|
193
|
+
cached = value;
|
|
194
|
+
return value;
|
|
195
|
+
});
|
|
196
|
+
return promise;
|
|
283
197
|
};
|
|
284
198
|
};
|
|
285
|
-
var
|
|
286
|
-
|
|
199
|
+
var memoise = (fn) => {
|
|
200
|
+
let cached = null;
|
|
201
|
+
let initialized = false;
|
|
202
|
+
return () => {
|
|
203
|
+
if (initialized) return cached;
|
|
204
|
+
cached = fn();
|
|
205
|
+
initialized = true;
|
|
206
|
+
return cached;
|
|
207
|
+
};
|
|
287
208
|
};
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
209
|
+
|
|
210
|
+
// src/ghost.ts
|
|
211
|
+
var DEFAULT_API_URL = "https://api.forboc.ai";
|
|
212
|
+
var startGhostSession = async (config) => {
|
|
213
|
+
const apiUrl = config.apiUrl || DEFAULT_API_URL;
|
|
214
|
+
const response = await fetch(`${apiUrl}/ghost/run`, {
|
|
215
|
+
method: "POST",
|
|
216
|
+
headers: { "Content-Type": "application/json" },
|
|
217
|
+
body: JSON.stringify({
|
|
218
|
+
testSuite: config.testSuite,
|
|
219
|
+
duration: config.duration
|
|
220
|
+
})
|
|
221
|
+
});
|
|
222
|
+
if (!response.ok) throw new Error(`Failed to start Ghost: ${response.statusText}`);
|
|
223
|
+
const data = await response.json();
|
|
293
224
|
return {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
name: parsed.name || "Unknown",
|
|
297
|
-
persona: parsed.persona,
|
|
298
|
-
state: parsed.state,
|
|
299
|
-
memories: parsed.memories || [],
|
|
300
|
-
signature: parsed.signature
|
|
225
|
+
sessionId: data.sessionId,
|
|
226
|
+
status: data.runStatus
|
|
301
227
|
};
|
|
302
228
|
};
|
|
303
|
-
var
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
createArweaveDataItem = imported.createArweaveDataItem;
|
|
312
|
-
} catch (e) {
|
|
313
|
-
throw new Error("Missing ANS-104 Arweave module. Rebuild the SDK to enable direct uploads.");
|
|
314
|
-
}
|
|
315
|
-
const jwk = typeof wallet === "string" ? JSON.parse(wallet) : wallet;
|
|
316
|
-
const dataToUpload = serializeSoul(soul);
|
|
317
|
-
const tags = [
|
|
318
|
-
{ name: "Content-Type", value: "application/json" },
|
|
319
|
-
{ name: "App-Name", value: "ForbocAI" },
|
|
320
|
-
{ name: "App-Version", value: "soul-1" }
|
|
321
|
-
];
|
|
322
|
-
const dataItem = await createArweaveDataItem(dataToUpload, jwk, { tags });
|
|
323
|
-
const rawData = dataItem.raw;
|
|
324
|
-
if (!rawData) {
|
|
325
|
-
throw new Error("Failed to build ANS-104 data item");
|
|
326
|
-
}
|
|
327
|
-
const bundlerUrl = config.bundlerUrl || "https://upload.ardrive.io/v1/tx";
|
|
328
|
-
const gatewayUrl = config.gatewayUrl || "https://arweave.net";
|
|
329
|
-
try {
|
|
330
|
-
const response = await fetch(bundlerUrl, {
|
|
331
|
-
method: "POST",
|
|
332
|
-
headers: { "Content-Type": "application/octet-stream" },
|
|
333
|
-
body: rawData
|
|
334
|
-
});
|
|
335
|
-
if (!response.ok) {
|
|
336
|
-
const message = await response.text().catch(() => response.statusText);
|
|
337
|
-
throw new Error(message || response.statusText);
|
|
338
|
-
}
|
|
339
|
-
const responseText = await response.text();
|
|
340
|
-
let responseJson = null;
|
|
341
|
-
try {
|
|
342
|
-
responseJson = JSON.parse(responseText);
|
|
343
|
-
} catch {
|
|
344
|
-
responseJson = null;
|
|
345
|
-
}
|
|
346
|
-
const txId = responseJson?.id || responseJson?.dataItemId || responseJson?.txId || (typeof responseText === "string" && responseText.trim().length > 0 ? responseText.trim() : null) || dataItem.id;
|
|
347
|
-
if (!txId) {
|
|
348
|
-
throw new Error("Bundler response did not include a data item id");
|
|
349
|
-
}
|
|
350
|
-
return {
|
|
351
|
-
txId,
|
|
352
|
-
url: `${gatewayUrl}/${txId}`,
|
|
353
|
-
soul
|
|
354
|
-
};
|
|
355
|
-
} catch (e) {
|
|
356
|
-
throw new Error(`Failed to upload to Arweave: ${e}`);
|
|
357
|
-
}
|
|
358
|
-
};
|
|
359
|
-
var exportSoul = async (_agentId, soul, config = {}) => {
|
|
360
|
-
if (!config.walletJwk && !config.privateKey) {
|
|
361
|
-
throw new Error("walletJwk required for Arweave ANS-104 export");
|
|
362
|
-
}
|
|
363
|
-
return uploadToArweave(soul, config);
|
|
364
|
-
};
|
|
365
|
-
var importSoulFromArweave = async (txId, config = {}) => {
|
|
366
|
-
const gateway = config.gatewayUrl || "https://arweave.net";
|
|
367
|
-
try {
|
|
368
|
-
const response = await fetch(`${gateway}/${txId}`, {
|
|
369
|
-
method: "GET",
|
|
370
|
-
headers: { "Content-Type": "application/json" }
|
|
371
|
-
});
|
|
372
|
-
if (!response.ok) {
|
|
373
|
-
throw new Error(`Import failed: ${response.statusText}`);
|
|
374
|
-
}
|
|
375
|
-
const data = await response.json();
|
|
376
|
-
if (!data.id || !data.persona) {
|
|
377
|
-
throw new Error("Invalid soul data from Arweave");
|
|
378
|
-
}
|
|
379
|
-
return data;
|
|
380
|
-
} catch (e) {
|
|
381
|
-
throw new Error(`Failed to import Soul from TXID ${txId}: ${e}`);
|
|
382
|
-
}
|
|
383
|
-
};
|
|
384
|
-
var getSoulList = async (limit = 50, apiUrl) => {
|
|
385
|
-
const url = apiUrl || "https://api.forboc.ai";
|
|
386
|
-
try {
|
|
387
|
-
const response = await fetch(`${url}/souls?limit=${limit}`);
|
|
388
|
-
if (!response.ok) throw new Error(response.statusText);
|
|
389
|
-
const data = await response.json();
|
|
390
|
-
return data.souls.map((s) => {
|
|
391
|
-
const txId = s.txId || s.soulEntryTxId || s.cid;
|
|
392
|
-
const name = s.name || s.soulEntryName;
|
|
393
|
-
const agentId = s.agentId || s.soulEntryAgentId;
|
|
394
|
-
const exportedAt = s.exportedAt || s.soulEntryExportedAt;
|
|
395
|
-
const url2 = s.url || s.soulEntryArweaveUrl || `https://arweave.net/${txId}`;
|
|
396
|
-
return { txId, name, agentId, exportedAt, url: url2 };
|
|
397
|
-
});
|
|
398
|
-
} catch (e) {
|
|
399
|
-
return [];
|
|
400
|
-
}
|
|
401
|
-
};
|
|
402
|
-
var createSoulInstance = (id, name, persona, state, memories = []) => {
|
|
403
|
-
const soulData = createSoul(id, name, persona, state, memories);
|
|
404
|
-
const performExport = async (config) => {
|
|
405
|
-
return exportSoul(soulData.id, soulData, { ...config });
|
|
406
|
-
};
|
|
229
|
+
var getGhostStatus = async (sessionId, apiUrl) => {
|
|
230
|
+
const url = apiUrl || DEFAULT_API_URL;
|
|
231
|
+
const response = await fetch(`${url}/ghost/${sessionId}/status`, {
|
|
232
|
+
method: "GET",
|
|
233
|
+
headers: { "Content-Type": "application/json" }
|
|
234
|
+
});
|
|
235
|
+
if (!response.ok) throw new Error(`Failed to get status: ${response.statusText}`);
|
|
236
|
+
const data = await response.json();
|
|
407
237
|
return {
|
|
408
|
-
|
|
409
|
-
|
|
238
|
+
sessionId: data.ghostSessionId,
|
|
239
|
+
status: data.ghostStatus,
|
|
240
|
+
progress: data.ghostProgress,
|
|
241
|
+
startedAt: data.ghostStartedAt,
|
|
242
|
+
duration: data.ghostDuration,
|
|
243
|
+
errors: data.ghostErrors
|
|
410
244
|
};
|
|
411
245
|
};
|
|
412
|
-
var
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
246
|
+
var getGhostResults = async (sessionId, apiUrl) => {
|
|
247
|
+
const url = apiUrl || DEFAULT_API_URL;
|
|
248
|
+
const response = await fetch(`${url}/ghost/${sessionId}/results`, {
|
|
249
|
+
method: "GET",
|
|
250
|
+
headers: { "Content-Type": "application/json" }
|
|
251
|
+
});
|
|
252
|
+
if (!response.ok) throw new Error(`Failed to get results: ${response.statusText}`);
|
|
253
|
+
const data = await response.json();
|
|
417
254
|
return {
|
|
418
|
-
|
|
419
|
-
|
|
255
|
+
sessionId: data.resultsSessionId,
|
|
256
|
+
totalTests: data.resultsTotalTests,
|
|
257
|
+
passed: data.resultsPassed,
|
|
258
|
+
failed: data.resultsFailed,
|
|
259
|
+
skipped: data.resultsSkipped,
|
|
260
|
+
duration: data.resultsDuration,
|
|
261
|
+
tests: data.resultsTests.map((t) => ({
|
|
262
|
+
name: t.testName,
|
|
263
|
+
passed: t.testPassed,
|
|
264
|
+
duration: t.testDuration,
|
|
265
|
+
error: t.testError,
|
|
266
|
+
screenshot: t.testScreenshot
|
|
267
|
+
})),
|
|
268
|
+
coverage: data.resultsCoverage,
|
|
269
|
+
metrics: Object.fromEntries(data.resultsMetrics || [])
|
|
420
270
|
};
|
|
421
271
|
};
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
const apiUrl = config.apiUrl || "https://api.forboc.ai";
|
|
426
|
-
try {
|
|
427
|
-
const response = await fetch(`${apiUrl}/ghost/run`, {
|
|
428
|
-
method: "POST",
|
|
429
|
-
headers: { "Content-Type": "application/json" },
|
|
430
|
-
body: JSON.stringify({
|
|
431
|
-
testSuite: config.testSuite,
|
|
432
|
-
duration: config.duration
|
|
433
|
-
})
|
|
434
|
-
});
|
|
435
|
-
if (!response.ok) {
|
|
436
|
-
throw new Error(`Failed to start Ghost session: ${response.statusText}`);
|
|
437
|
-
}
|
|
438
|
-
const data = await response.json();
|
|
439
|
-
return {
|
|
440
|
-
sessionId: data.sessionId,
|
|
441
|
-
status: data.runStatus
|
|
442
|
-
};
|
|
443
|
-
} catch (e) {
|
|
444
|
-
const mockId = `ghost_${Date.now()}_${Math.random().toString(36).substring(7)}`;
|
|
445
|
-
return {
|
|
446
|
-
sessionId: mockId,
|
|
447
|
-
status: "running"
|
|
448
|
-
};
|
|
272
|
+
var pollForCompletion = async (sessionId, pollIntervalMs, timeoutMs, startTime, apiUrl, onProgress) => {
|
|
273
|
+
if (Date.now() - startTime > timeoutMs) {
|
|
274
|
+
throw new Error(`Ghost session timed out after ${timeoutMs}ms`);
|
|
449
275
|
}
|
|
450
|
-
};
|
|
451
|
-
var getGhostStatus = async (sessionId, apiUrl) => {
|
|
452
|
-
const url = apiUrl || "https://api.forboc.ai";
|
|
453
276
|
try {
|
|
454
|
-
const
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
});
|
|
458
|
-
if (!response.ok) {
|
|
459
|
-
throw new Error(`Failed to get Ghost status: ${response.statusText}`);
|
|
460
|
-
}
|
|
461
|
-
const data = await response.json();
|
|
462
|
-
return {
|
|
463
|
-
sessionId: data.ghostSessionId,
|
|
464
|
-
status: data.ghostStatus,
|
|
465
|
-
progress: data.ghostProgress,
|
|
466
|
-
startedAt: data.ghostStartedAt,
|
|
467
|
-
duration: data.ghostDuration,
|
|
468
|
-
errors: data.ghostErrors
|
|
469
|
-
};
|
|
277
|
+
const status = await getGhostStatus(sessionId, apiUrl);
|
|
278
|
+
if (onProgress) onProgress(status);
|
|
279
|
+
if (status.status === "completed") return getGhostResults(sessionId, apiUrl);
|
|
280
|
+
if (status.status === "failed") throw new Error(`Ghost session failed with ${status.errors} errors`);
|
|
470
281
|
} catch (e) {
|
|
471
|
-
return {
|
|
472
|
-
sessionId,
|
|
473
|
-
status: "running",
|
|
474
|
-
progress: Math.floor(Math.random() * 100),
|
|
475
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
476
|
-
duration: 60,
|
|
477
|
-
errors: 0
|
|
478
|
-
};
|
|
479
282
|
}
|
|
283
|
+
await delay(pollIntervalMs);
|
|
284
|
+
return pollForCompletion(sessionId, pollIntervalMs, timeoutMs, startTime, apiUrl, onProgress);
|
|
480
285
|
};
|
|
481
|
-
var
|
|
482
|
-
const url = apiUrl || "https://api.forboc.ai";
|
|
483
|
-
try {
|
|
484
|
-
const response = await fetch(`${url}/ghost/${sessionId}/results`, {
|
|
485
|
-
method: "GET",
|
|
486
|
-
headers: { "Content-Type": "application/json" }
|
|
487
|
-
});
|
|
488
|
-
if (!response.ok) {
|
|
489
|
-
throw new Error(`Failed to get Ghost results: ${response.statusText}`);
|
|
490
|
-
}
|
|
491
|
-
const data = await response.json();
|
|
492
|
-
return {
|
|
493
|
-
sessionId: data.resultsSessionId,
|
|
494
|
-
totalTests: data.resultsTotalTests,
|
|
495
|
-
passed: data.resultsPassed,
|
|
496
|
-
failed: data.resultsFailed,
|
|
497
|
-
skipped: data.resultsSkipped,
|
|
498
|
-
duration: data.resultsDuration,
|
|
499
|
-
tests: data.resultsTests.map((t) => ({
|
|
500
|
-
name: t.testName,
|
|
501
|
-
passed: t.testPassed,
|
|
502
|
-
duration: t.testDuration,
|
|
503
|
-
error: t.testError,
|
|
504
|
-
screenshot: t.testScreenshot
|
|
505
|
-
})),
|
|
506
|
-
coverage: data.resultsCoverage,
|
|
507
|
-
metrics: Object.fromEntries(data.resultsMetrics)
|
|
508
|
-
};
|
|
509
|
-
} catch (e) {
|
|
510
|
-
return {
|
|
511
|
-
sessionId,
|
|
512
|
-
totalTests: 5,
|
|
513
|
-
passed: 4,
|
|
514
|
-
failed: 1,
|
|
515
|
-
skipped: 0,
|
|
516
|
-
duration: 1245,
|
|
517
|
-
tests: [
|
|
518
|
-
{ name: "test.navigation", passed: true, duration: 150 },
|
|
519
|
-
{ name: "test.combat", passed: true, duration: 230 },
|
|
520
|
-
{ name: "test.dialogue", passed: false, duration: 450, error: "Timeout" }
|
|
521
|
-
],
|
|
522
|
-
coverage: 0.75,
|
|
523
|
-
metrics: {
|
|
524
|
-
avgFrameRate: 58.5,
|
|
525
|
-
memoryUsageMB: 512.3,
|
|
526
|
-
aiDecisionsPerSec: 15.2
|
|
527
|
-
}
|
|
528
|
-
};
|
|
529
|
-
}
|
|
530
|
-
};
|
|
531
|
-
var waitForGhostCompletion = async (sessionId, pollIntervalMs = 5e3, timeoutMs = 3e5, apiUrl, onProgress) => {
|
|
532
|
-
const startTime = Date.now();
|
|
533
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
534
|
-
try {
|
|
535
|
-
const status = await getGhostStatus(sessionId, apiUrl);
|
|
536
|
-
if (onProgress) {
|
|
537
|
-
onProgress(status);
|
|
538
|
-
}
|
|
539
|
-
if (status.status === "completed") {
|
|
540
|
-
return getGhostResults(sessionId, apiUrl);
|
|
541
|
-
}
|
|
542
|
-
if (status.status === "failed") {
|
|
543
|
-
throw new Error(`Ghost session failed with ${status.errors} errors`);
|
|
544
|
-
}
|
|
545
|
-
} catch (e) {
|
|
546
|
-
}
|
|
547
|
-
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
548
|
-
}
|
|
549
|
-
throw new Error(`Ghost session timed out after ${timeoutMs}ms`);
|
|
550
|
-
};
|
|
286
|
+
var waitForGhostCompletion = (sessionId, pollIntervalMs = 5e3, timeoutMs = 3e5, apiUrl, onProgress) => pollForCompletion(sessionId, pollIntervalMs, timeoutMs, Date.now(), apiUrl, onProgress);
|
|
551
287
|
var stopGhostSession = async (sessionId, apiUrl) => {
|
|
552
|
-
const url = apiUrl ||
|
|
288
|
+
const url = apiUrl || DEFAULT_API_URL;
|
|
553
289
|
try {
|
|
554
|
-
const response = await fetch(`${url}/ghost/${sessionId}/stop`, {
|
|
555
|
-
|
|
556
|
-
headers: { "Content-Type": "application/json" }
|
|
557
|
-
});
|
|
558
|
-
if (!response.ok) {
|
|
559
|
-
throw new Error(`Failed to stop Ghost session: ${response.statusText}`);
|
|
560
|
-
}
|
|
561
|
-
const data = await response.json();
|
|
562
|
-
return {
|
|
563
|
-
stopped: true,
|
|
564
|
-
status: data.status || "stopped"
|
|
565
|
-
};
|
|
290
|
+
const response = await fetch(`${url}/ghost/${sessionId}/stop`, { method: "POST" });
|
|
291
|
+
return { stopped: response.ok };
|
|
566
292
|
} catch (e) {
|
|
567
|
-
return {
|
|
568
|
-
stopped: true,
|
|
569
|
-
status: "stopped"
|
|
570
|
-
};
|
|
293
|
+
return { stopped: true };
|
|
571
294
|
}
|
|
572
295
|
};
|
|
573
296
|
var getGhostHistory = async (limit = 10, apiUrl) => {
|
|
574
|
-
const url = apiUrl ||
|
|
297
|
+
const url = apiUrl || DEFAULT_API_URL;
|
|
575
298
|
try {
|
|
576
|
-
const response = await fetch(`${url}/ghost/history?limit=${limit}
|
|
577
|
-
|
|
578
|
-
headers: { "Content-Type": "application/json" }
|
|
579
|
-
});
|
|
580
|
-
if (!response.ok) {
|
|
581
|
-
throw new Error(`Failed to get Ghost history: ${response.statusText}`);
|
|
582
|
-
}
|
|
299
|
+
const response = await fetch(`${url}/ghost/history?limit=${limit}`);
|
|
300
|
+
if (!response.ok) return [];
|
|
583
301
|
const data = await response.json();
|
|
584
302
|
return data.sessions.map((s) => ({
|
|
585
303
|
sessionId: s.sessionId,
|
|
@@ -594,50 +312,25 @@ var getGhostHistory = async (limit = 10, apiUrl) => {
|
|
|
594
312
|
}
|
|
595
313
|
};
|
|
596
314
|
var createGhost = (config) => {
|
|
597
|
-
let
|
|
598
|
-
const apiUrl = config.apiUrl ||
|
|
315
|
+
let _sessionId = null;
|
|
316
|
+
const apiUrl = config.apiUrl || DEFAULT_API_URL;
|
|
599
317
|
const run = async () => {
|
|
600
318
|
const result = await startGhostSession(config);
|
|
601
|
-
|
|
602
|
-
return
|
|
603
|
-
};
|
|
604
|
-
const status = async () => {
|
|
605
|
-
if (!sessionId) {
|
|
606
|
-
throw new Error("Ghost session not started");
|
|
607
|
-
}
|
|
608
|
-
return getGhostStatus(sessionId, apiUrl);
|
|
319
|
+
_sessionId = result.sessionId;
|
|
320
|
+
return _sessionId;
|
|
609
321
|
};
|
|
610
|
-
const
|
|
611
|
-
if (!
|
|
612
|
-
|
|
613
|
-
}
|
|
614
|
-
return getGhostResults(sessionId, apiUrl);
|
|
322
|
+
const ensureSessionId = () => {
|
|
323
|
+
if (!_sessionId) throw new Error("Ghost session not started");
|
|
324
|
+
return _sessionId;
|
|
615
325
|
};
|
|
326
|
+
const status = async () => getGhostStatus(ensureSessionId(), apiUrl);
|
|
327
|
+
const results = async () => getGhostResults(ensureSessionId(), apiUrl);
|
|
616
328
|
const stop = async () => {
|
|
617
|
-
if (
|
|
618
|
-
|
|
619
|
-
}
|
|
620
|
-
sessionId = null;
|
|
621
|
-
};
|
|
622
|
-
const waitForCompletion = async (pollIntervalMs, timeoutMs, onProgress) => {
|
|
623
|
-
if (!sessionId) {
|
|
624
|
-
throw new Error("Ghost session not started");
|
|
625
|
-
}
|
|
626
|
-
return waitForGhostCompletion(
|
|
627
|
-
sessionId,
|
|
628
|
-
pollIntervalMs,
|
|
629
|
-
timeoutMs,
|
|
630
|
-
apiUrl,
|
|
631
|
-
onProgress
|
|
632
|
-
);
|
|
633
|
-
};
|
|
634
|
-
return {
|
|
635
|
-
run,
|
|
636
|
-
status,
|
|
637
|
-
results,
|
|
638
|
-
stop,
|
|
639
|
-
waitForCompletion
|
|
329
|
+
if (_sessionId) await stopGhostSession(_sessionId, apiUrl);
|
|
330
|
+
_sessionId = null;
|
|
640
331
|
};
|
|
332
|
+
const waitForCompletion = (pollIntervalMs, timeoutMs, onProgress) => waitForGhostCompletion(ensureSessionId(), pollIntervalMs, timeoutMs, apiUrl, onProgress);
|
|
333
|
+
return { run, status, results, stop, waitForCompletion };
|
|
641
334
|
};
|
|
642
335
|
|
|
643
336
|
// src/cortex-remote.ts
|
|
@@ -670,249 +363,31 @@ var createRemoteCortex = (apiUrl, cortexId = "local", apiKey) => {
|
|
|
670
363
|
};
|
|
671
364
|
|
|
672
365
|
// src/stream.ts
|
|
673
|
-
async
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
let fullText = "";
|
|
688
|
-
for await (const chunk of stream) {
|
|
689
|
-
fullText += chunk;
|
|
690
|
-
onChunk(chunk);
|
|
691
|
-
}
|
|
692
|
-
return fullText;
|
|
693
|
-
}
|
|
694
|
-
async function streamFromCortexWithDelay(cortex, prompt, onChunk, options) {
|
|
695
|
-
const { delayMs = 30, ...completionOptions } = options ?? {};
|
|
696
|
-
const stream = cortex.completeStream(prompt, completionOptions);
|
|
697
|
-
let fullText = "";
|
|
698
|
-
for await (const chunk of stream) {
|
|
699
|
-
fullText += chunk;
|
|
700
|
-
onChunk(chunk);
|
|
701
|
-
if (delayMs > 0) {
|
|
702
|
-
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
return fullText;
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
// src/presets/index.ts
|
|
709
|
-
var presets_exports = {};
|
|
710
|
-
__export(presets_exports, {
|
|
711
|
-
RPG_MEMORY_TYPES: () => RPG_MEMORY_TYPES,
|
|
712
|
-
RPG_MOODS: () => RPG_MOODS,
|
|
713
|
-
attackRule: () => attackRule,
|
|
714
|
-
createRPGState: () => createRPGState,
|
|
715
|
-
interactRule: () => interactRule,
|
|
716
|
-
movementRule: () => movementRule,
|
|
717
|
-
puzzleRules: () => puzzleRules,
|
|
718
|
-
resourceRule: () => resourceRule,
|
|
719
|
-
rpgRules: () => rpgRules,
|
|
720
|
-
socialRules: () => socialRules,
|
|
721
|
-
spatialRules: () => spatialRules,
|
|
722
|
-
speakRule: () => speakRule
|
|
723
|
-
});
|
|
724
|
-
|
|
725
|
-
// src/presets/rpg.ts
|
|
726
|
-
var RPG_MOODS = {
|
|
727
|
-
hostile: "hostile",
|
|
728
|
-
suspicious: "suspicious",
|
|
729
|
-
neutral: "neutral",
|
|
730
|
-
friendly: "friendly",
|
|
731
|
-
loyal: "loyal"
|
|
732
|
-
};
|
|
733
|
-
var RPG_MEMORY_TYPES = {
|
|
734
|
-
observation: "observation",
|
|
735
|
-
experience: "experience",
|
|
736
|
-
knowledge: "knowledge",
|
|
737
|
-
emotion: "emotion"
|
|
738
|
-
};
|
|
739
|
-
var createRPGState = (partial) => {
|
|
740
|
-
return {
|
|
741
|
-
inventory: partial?.inventory ?? [],
|
|
742
|
-
hp: partial?.hp ?? 100,
|
|
743
|
-
mana: partial?.mana ?? 100,
|
|
744
|
-
skills: partial?.skills ?? {},
|
|
745
|
-
relationships: partial?.relationships ?? {},
|
|
746
|
-
mood: partial?.mood ?? "neutral",
|
|
747
|
-
...partial
|
|
748
|
-
};
|
|
749
|
-
};
|
|
750
|
-
var movementRule = {
|
|
751
|
-
id: "core.movement",
|
|
752
|
-
name: "Movement Validation",
|
|
753
|
-
description: "Ensures MOVE actions have valid x,y coordinates",
|
|
754
|
-
actionTypes: ["MOVE", "move"],
|
|
755
|
-
validate: (action, context) => {
|
|
756
|
-
const payload = action.payload || {};
|
|
757
|
-
const target = payload.target;
|
|
758
|
-
if (!target || typeof target.x !== "number" || typeof target.y !== "number") {
|
|
759
|
-
return {
|
|
760
|
-
valid: false,
|
|
761
|
-
reason: "MOVE action must have target with numeric x,y coordinates",
|
|
762
|
-
correctedAction: {
|
|
763
|
-
...action,
|
|
764
|
-
type: "IDLE",
|
|
765
|
-
reason: "Invalid MOVE target - defaulting to IDLE"
|
|
766
|
-
}
|
|
767
|
-
};
|
|
768
|
-
}
|
|
769
|
-
const world = context.worldState || {};
|
|
770
|
-
const maxX = world.maxX || Infinity;
|
|
771
|
-
const maxY = world.maxY || Infinity;
|
|
772
|
-
if (target.x < 0 || target.x > maxX || target.y < 0 || target.y > maxY) {
|
|
773
|
-
return {
|
|
774
|
-
valid: false,
|
|
775
|
-
reason: `MOVE target (${target.x}, ${target.y}) is out of bounds`,
|
|
776
|
-
correctedAction: {
|
|
777
|
-
...action,
|
|
778
|
-
payload: {
|
|
779
|
-
...payload,
|
|
780
|
-
target: {
|
|
781
|
-
x: Math.max(0, Math.min(maxX, target.x)),
|
|
782
|
-
y: Math.max(0, Math.min(maxY, target.y))
|
|
783
|
-
}
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
};
|
|
787
|
-
}
|
|
788
|
-
return { valid: true };
|
|
789
|
-
}
|
|
790
|
-
};
|
|
791
|
-
var attackRule = {
|
|
792
|
-
id: "core.attack",
|
|
793
|
-
name: "Attack Validation",
|
|
794
|
-
description: "Ensures ATTACK actions have valid targetId",
|
|
795
|
-
actionTypes: ["ATTACK", "attack"],
|
|
796
|
-
validate: (action, context) => {
|
|
797
|
-
if (!action.target && !action.payload?.targetId) {
|
|
798
|
-
return {
|
|
799
|
-
valid: false,
|
|
800
|
-
reason: "ATTACK action must have a target or targetId",
|
|
801
|
-
correctedAction: {
|
|
802
|
-
...action,
|
|
803
|
-
type: "IDLE",
|
|
804
|
-
reason: "Invalid ATTACK - no target specified"
|
|
805
|
-
}
|
|
806
|
-
};
|
|
807
|
-
}
|
|
808
|
-
const world = context.worldState || {};
|
|
809
|
-
const entities = world.entities || [];
|
|
810
|
-
const targetId = action.target || action.payload?.targetId;
|
|
811
|
-
if (entities.length > 0 && !entities.includes(targetId)) {
|
|
812
|
-
return {
|
|
813
|
-
valid: false,
|
|
814
|
-
reason: `ATTACK target '${targetId}' does not exist in world`,
|
|
815
|
-
correctedAction: {
|
|
816
|
-
...action,
|
|
817
|
-
type: "IDLE",
|
|
818
|
-
reason: "Target not found"
|
|
819
|
-
}
|
|
820
|
-
};
|
|
821
|
-
}
|
|
822
|
-
return { valid: true };
|
|
823
|
-
}
|
|
366
|
+
var consumeStream = async (stream, onChunk, acc = "", delayMs = 0) => {
|
|
367
|
+
const { value, done } = await stream.next();
|
|
368
|
+
if (done) return acc;
|
|
369
|
+
const chunk = value ?? "";
|
|
370
|
+
onChunk(chunk);
|
|
371
|
+
if (delayMs > 0) await delay(delayMs);
|
|
372
|
+
return consumeStream(stream, onChunk, acc + chunk, delayMs);
|
|
373
|
+
};
|
|
374
|
+
var streamToCallback = async (stream, onChunk) => {
|
|
375
|
+
await consumeStream(stream, onChunk);
|
|
376
|
+
};
|
|
377
|
+
var streamToString = async (stream) => {
|
|
378
|
+
return consumeStream(stream, () => {
|
|
379
|
+
});
|
|
824
380
|
};
|
|
825
|
-
var
|
|
826
|
-
|
|
827
|
-
name: "Interact Validation",
|
|
828
|
-
description: "Ensures INTERACT actions have valid objectId",
|
|
829
|
-
actionTypes: ["INTERACT", "interact"],
|
|
830
|
-
validate: (action, context) => {
|
|
831
|
-
if (!action.target && !action.payload?.objectId) {
|
|
832
|
-
return {
|
|
833
|
-
valid: false,
|
|
834
|
-
reason: "INTERACT action must have objectId",
|
|
835
|
-
correctedAction: {
|
|
836
|
-
...action,
|
|
837
|
-
type: "IDLE",
|
|
838
|
-
reason: "Invalid INTERACT - no object specified"
|
|
839
|
-
}
|
|
840
|
-
};
|
|
841
|
-
}
|
|
842
|
-
return { valid: true };
|
|
843
|
-
}
|
|
381
|
+
var streamFromCortex = async (cortex, prompt, onChunk, options) => {
|
|
382
|
+
return consumeStream(cortex.completeStream(prompt, options), onChunk);
|
|
844
383
|
};
|
|
845
|
-
var
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
description: "Ensures SPEAK actions have non-empty text",
|
|
849
|
-
actionTypes: ["SPEAK", "speak"],
|
|
850
|
-
validate: (action, context) => {
|
|
851
|
-
const text = action.payload?.text;
|
|
852
|
-
if (!text || text.trim().length === 0) {
|
|
853
|
-
return {
|
|
854
|
-
valid: false,
|
|
855
|
-
reason: "SPEAK action must have non-empty text",
|
|
856
|
-
correctedAction: {
|
|
857
|
-
...action,
|
|
858
|
-
type: "IDLE",
|
|
859
|
-
reason: "Empty speech - defaulting to IDLE"
|
|
860
|
-
}
|
|
861
|
-
};
|
|
862
|
-
}
|
|
863
|
-
const maxLength = context.constraints?.maxSpeechLength || 1e3;
|
|
864
|
-
if (text.length > maxLength) {
|
|
865
|
-
return {
|
|
866
|
-
valid: true,
|
|
867
|
-
reason: `Speech truncated to ${maxLength} characters`,
|
|
868
|
-
correctedAction: {
|
|
869
|
-
...action,
|
|
870
|
-
payload: {
|
|
871
|
-
...action.payload,
|
|
872
|
-
text: text.substring(0, maxLength)
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
};
|
|
876
|
-
}
|
|
877
|
-
return { valid: true };
|
|
878
|
-
}
|
|
879
|
-
};
|
|
880
|
-
var resourceRule = {
|
|
881
|
-
id: "core.resources",
|
|
882
|
-
name: "Resource Validation",
|
|
883
|
-
description: "Ensures agent has required resources for action",
|
|
884
|
-
actionTypes: ["ATTACK", "CAST", "USE_ITEM"],
|
|
885
|
-
validate: (action, context) => {
|
|
886
|
-
const agent = context.agentState || {};
|
|
887
|
-
const hp = agent.hp ?? 100;
|
|
888
|
-
const mana = agent.mana ?? 100;
|
|
889
|
-
if (hp <= 0) {
|
|
890
|
-
return {
|
|
891
|
-
valid: false,
|
|
892
|
-
reason: "Agent is dead and cannot perform actions",
|
|
893
|
-
correctedAction: { ...action, type: "IDLE", reason: "Agent dead" }
|
|
894
|
-
};
|
|
895
|
-
}
|
|
896
|
-
if (action.type === "CAST" || action.type === "cast") {
|
|
897
|
-
const manaCost = action.payload?.manaCost || 10;
|
|
898
|
-
if (mana < manaCost) {
|
|
899
|
-
return {
|
|
900
|
-
valid: false,
|
|
901
|
-
reason: `Insufficient mana: need ${manaCost}, have ${mana}`,
|
|
902
|
-
correctedAction: { ...action, type: "IDLE", reason: "Not enough mana" }
|
|
903
|
-
};
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
return { valid: true };
|
|
907
|
-
}
|
|
384
|
+
var streamFromCortexWithDelay = async (cortex, prompt, onChunk, options) => {
|
|
385
|
+
const { delayMs = 30, ...completionOptions } = options ?? {};
|
|
386
|
+
return consumeStream(cortex.completeStream(prompt, completionOptions), onChunk, "", delayMs);
|
|
908
387
|
};
|
|
909
|
-
var rpgRules = [movementRule, attackRule, interactRule, speakRule, resourceRule];
|
|
910
|
-
var spatialRules = [movementRule];
|
|
911
|
-
var socialRules = [speakRule, interactRule];
|
|
912
|
-
var puzzleRules = [movementRule, interactRule];
|
|
913
388
|
|
|
914
389
|
// src/index.ts
|
|
915
|
-
var SDK_VERSION = "0.5.
|
|
390
|
+
var SDK_VERSION = "0.5.9";
|
|
916
391
|
export {
|
|
917
392
|
SDK_VERSION,
|
|
918
393
|
createAgent,
|
|
@@ -922,6 +397,7 @@ export {
|
|
|
922
397
|
createRemoteCortex,
|
|
923
398
|
createSoul,
|
|
924
399
|
createSoulInstance,
|
|
400
|
+
delay,
|
|
925
401
|
deserializeSoul,
|
|
926
402
|
exportSoul,
|
|
927
403
|
exportToSoul,
|
|
@@ -931,7 +407,10 @@ export {
|
|
|
931
407
|
getGhostStatus,
|
|
932
408
|
getSoulList,
|
|
933
409
|
importSoulFromArweave,
|
|
934
|
-
|
|
410
|
+
loadPreset,
|
|
411
|
+
memoise,
|
|
412
|
+
memoiseAsync,
|
|
413
|
+
pipe,
|
|
935
414
|
serializeSoul,
|
|
936
415
|
startGhostSession,
|
|
937
416
|
stopGhostSession,
|
|
@@ -940,7 +419,6 @@ export {
|
|
|
940
419
|
streamToCallback,
|
|
941
420
|
streamToString,
|
|
942
421
|
updateAgentState,
|
|
943
|
-
uploadToArweave,
|
|
944
422
|
validateAction,
|
|
945
423
|
validateSoul,
|
|
946
424
|
waitForGhostCompletion
|