@noopolis/daimon 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -10
- package/dist/core/siblingBuildFreshness.d.ts +21 -0
- package/dist/core/siblingBuildFreshness.d.ts.map +1 -0
- package/dist/core/siblingBuildFreshness.js +25 -0
- package/dist/core/types.d.ts +10 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/examples/exampleCausalId.d.ts +3 -0
- package/dist/examples/exampleCausalId.d.ts.map +1 -0
- package/dist/examples/exampleCausalId.js +8 -0
- package/dist/examples/jungian-play-org.js +3 -2
- package/dist/examples/jungian-triad-org.js +3 -2
- package/dist/examples/jungianPlayAgent.d.ts +1 -1
- package/dist/examples/jungianPlayAgent.d.ts.map +1 -1
- package/dist/examples/jungianPlayAgent.js +1 -1
- package/dist/examples/jungianProfiles.d.ts +1 -1
- package/dist/examples/jungianProfiles.d.ts.map +1 -1
- package/dist/examples/jungianTriadProfiles.d.ts +1 -1
- package/dist/examples/jungianTriadProfiles.d.ts.map +1 -1
- package/dist/examples/pi-agent.js +3 -2
- package/dist/examples/pi-memory-org.js +6 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/mcp/toolServer.d.ts +14 -0
- package/dist/mcp/toolServer.d.ts.map +1 -0
- package/dist/mcp/toolServer.js +105 -0
- package/dist/observability/causalEvents.d.ts +118 -0
- package/dist/observability/causalEvents.d.ts.map +1 -0
- package/dist/observability/causalEvents.js +135 -0
- package/dist/observability/controlCausal.d.ts +117 -0
- package/dist/observability/controlCausal.d.ts.map +1 -0
- package/dist/observability/controlCausal.js +107 -0
- package/dist/observability/emitCausalFixture.d.ts +25 -0
- package/dist/observability/emitCausalFixture.d.ts.map +1 -0
- package/dist/observability/emitCausalFixture.js +98 -0
- package/dist/observability/index.d.ts +2 -0
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +2 -0
- package/dist/pi/cliSession.d.ts +46 -0
- package/dist/pi/cliSession.d.ts.map +1 -0
- package/dist/pi/cliSession.js +224 -0
- package/dist/pi/index.d.ts +5 -0
- package/dist/pi/index.d.ts.map +1 -1
- package/dist/pi/index.js +5 -0
- package/dist/pi/memoryTools.d.ts +55 -1
- package/dist/pi/memoryTools.d.ts.map +1 -1
- package/dist/pi/memoryTools.js +144 -24
- package/dist/pi/modelRegistry.d.ts +13 -0
- package/dist/pi/modelRegistry.d.ts.map +1 -0
- package/dist/pi/modelRegistry.js +19 -0
- package/dist/pi/piAgentHandle.d.ts +45 -0
- package/dist/pi/piAgentHandle.d.ts.map +1 -0
- package/dist/pi/piAgentHandle.js +324 -0
- package/dist/pi/piAgentWakeSupport.d.ts +68 -0
- package/dist/pi/piAgentWakeSupport.d.ts.map +1 -0
- package/dist/pi/piAgentWakeSupport.js +147 -0
- package/dist/pi/piHarness.d.ts +30 -4
- package/dist/pi/piHarness.d.ts.map +1 -1
- package/dist/pi/piHarness.js +97 -255
- package/dist/pi/prompts.d.ts +9 -0
- package/dist/pi/prompts.d.ts.map +1 -0
- package/dist/pi/prompts.js +39 -0
- package/dist/pi/rawTrainingCapture.d.ts +59 -0
- package/dist/pi/rawTrainingCapture.d.ts.map +1 -0
- package/dist/pi/rawTrainingCapture.js +175 -0
- package/dist/pi/turnCausal.d.ts +73 -0
- package/dist/pi/turnCausal.d.ts.map +1 -0
- package/dist/pi/turnCausal.js +75 -0
- package/dist/pi/turnTrace.d.ts +128 -0
- package/dist/pi/turnTrace.d.ts.map +1 -0
- package/dist/pi/turnTrace.js +141 -0
- package/dist/pi/wakeAcceptance.d.ts +49 -0
- package/dist/pi/wakeAcceptance.d.ts.map +1 -0
- package/dist/pi/wakeAcceptance.js +281 -0
- package/dist/pi/wakeAcceptanceFs.d.ts +44 -0
- package/dist/pi/wakeAcceptanceFs.d.ts.map +1 -0
- package/dist/pi/wakeAcceptanceFs.js +318 -0
- package/dist/pi/wakeAcceptanceSchema.d.ts +75 -0
- package/dist/pi/wakeAcceptanceSchema.d.ts.map +1 -0
- package/dist/pi/wakeAcceptanceSchema.js +265 -0
- package/dist/pi/wakeModes.d.ts +9 -0
- package/dist/pi/wakeModes.d.ts.map +1 -0
- package/dist/pi/wakeModes.js +19 -0
- package/dist/pi/worldNudge.d.ts +22 -0
- package/dist/pi/worldNudge.d.ts.map +1 -0
- package/dist/pi/worldNudge.js +62 -0
- package/dist/pi/worldToolProtocol.d.ts +13 -0
- package/dist/pi/worldToolProtocol.d.ts.map +1 -0
- package/dist/pi/worldToolProtocol.js +49 -0
- package/dist/pi/worldTools.d.ts +32 -0
- package/dist/pi/worldTools.d.ts.map +1 -0
- package/dist/pi/worldTools.js +373 -0
- package/dist/pi/worldTrajectory.d.ts +52 -0
- package/dist/pi/worldTrajectory.d.ts.map +1 -0
- package/dist/pi/worldTrajectory.js +131 -0
- package/package.json +10 -13
- package/dist/examples/mixed-engine-org.d.ts +0 -2
- package/dist/examples/mixed-engine-org.d.ts.map +0 -1
- package/dist/examples/mixed-engine-org.js +0 -351
- package/dist/examples/mixedEngineCli.d.ts +0 -15
- package/dist/examples/mixedEngineCli.d.ts.map +0 -1
- package/dist/examples/mixedEngineCli.js +0 -174
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { createMemoryRuntime } from "@noopolis/mneme";
|
|
5
|
-
import { JsonlMemoryStore } from "@noopolis/mneme";
|
|
6
|
-
import { OrgObserver } from "../observability/index.js";
|
|
7
|
-
import { runEngineDetailed } from "./mixedEngineCli.js";
|
|
8
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
-
const daimonRoot = path.resolve(__dirname, "../..");
|
|
10
|
-
const runtimeRoot = path.join(daimonRoot, ".runtime", "mixed-engine-org");
|
|
11
|
-
const observer = new OrgObserver({
|
|
12
|
-
orgId: "mixed-engine-org",
|
|
13
|
-
runId: `run-${Date.now().toString(36)}`
|
|
14
|
-
});
|
|
15
|
-
const maxMemoryChars = 1800;
|
|
16
|
-
const maxTranscriptLines = 3;
|
|
17
|
-
class MixedEngineAgent {
|
|
18
|
-
config;
|
|
19
|
-
runtimeHomePath;
|
|
20
|
-
workspacePath;
|
|
21
|
-
memory;
|
|
22
|
-
constructor(config) {
|
|
23
|
-
this.config = config;
|
|
24
|
-
this.workspacePath = path.join(runtimeRoot, "agents", config.id, "workspace");
|
|
25
|
-
this.runtimeHomePath = path.join(runtimeRoot, "agents", config.id, "runtime");
|
|
26
|
-
this.memory = createMemoryRuntime({
|
|
27
|
-
agentId: config.id,
|
|
28
|
-
runtimeHomePath: this.runtimeHomePath,
|
|
29
|
-
source: `daimon/mixed-engine/${config.engine}`,
|
|
30
|
-
tokenBudget: 2200
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
async prepare() {
|
|
34
|
-
await mkdir(this.workspacePath, { recursive: true });
|
|
35
|
-
await mkdir(this.runtimeHomePath, { recursive: true });
|
|
36
|
-
await writeFile(path.join(this.workspacePath, "AGENTS.md"), [
|
|
37
|
-
`# ${this.config.name}`,
|
|
38
|
-
"",
|
|
39
|
-
`Engine: ${this.config.engine}`,
|
|
40
|
-
"This workspace belongs to the mixed-engine Daimon org E2E.",
|
|
41
|
-
"The test uses real CLI engines and Daimon's persisted memory."
|
|
42
|
-
].join("\n"));
|
|
43
|
-
}
|
|
44
|
-
async wake(event) {
|
|
45
|
-
const startedAt = Date.now();
|
|
46
|
-
const prepareStartedAt = Date.now();
|
|
47
|
-
const prepared = await this.memory.prepareTurn({
|
|
48
|
-
eventId: event.id,
|
|
49
|
-
kind: event.kind,
|
|
50
|
-
text: event.text,
|
|
51
|
-
from: event.from,
|
|
52
|
-
context: event.context ?? {}
|
|
53
|
-
});
|
|
54
|
-
const memoryPrepareMs = Date.now() - prepareStartedAt;
|
|
55
|
-
const rawMemoryText = prepared.packet.sections.length === 0
|
|
56
|
-
? "(no recalled memories)"
|
|
57
|
-
: prepared.packet.sections
|
|
58
|
-
.map((section) => `- ${section.heading}: ${section.text}`)
|
|
59
|
-
.join("\n");
|
|
60
|
-
const memoryText = rawMemoryText.length <= maxMemoryChars
|
|
61
|
-
? rawMemoryText
|
|
62
|
-
: `${rawMemoryText.slice(0, maxMemoryChars).trim()}\n[truncated memory]`;
|
|
63
|
-
const prompt = [
|
|
64
|
-
`${this.config.name} (${this.config.id}) running on ${this.config.engine}.`,
|
|
65
|
-
"Use recalled Daimon memory as authoritative context.",
|
|
66
|
-
"Answer only the requested final line.",
|
|
67
|
-
"Memory:",
|
|
68
|
-
memoryText,
|
|
69
|
-
"",
|
|
70
|
-
"Task:",
|
|
71
|
-
event.text
|
|
72
|
-
].join("\n");
|
|
73
|
-
const engineResult = await runEngineDetailed(this.config.engine, prompt, {
|
|
74
|
-
runtimeHomePath: this.runtimeHomePath,
|
|
75
|
-
workspacePath: this.workspacePath
|
|
76
|
-
});
|
|
77
|
-
const recordStartedAt = Date.now();
|
|
78
|
-
await this.memory.recordTurn({
|
|
79
|
-
principal: prepared.principal,
|
|
80
|
-
prompt: prepared.packet,
|
|
81
|
-
request: {
|
|
82
|
-
eventId: event.id,
|
|
83
|
-
kind: event.kind,
|
|
84
|
-
text: event.text,
|
|
85
|
-
from: event.from,
|
|
86
|
-
context: event.context ?? {}
|
|
87
|
-
},
|
|
88
|
-
recall: prepared.recall,
|
|
89
|
-
result: "completed",
|
|
90
|
-
outputText: engineResult.text
|
|
91
|
-
});
|
|
92
|
-
const memoryRecordMs = Date.now() - recordStartedAt;
|
|
93
|
-
observer.recordTurn({
|
|
94
|
-
agent: this.config.id,
|
|
95
|
-
engine: this.config.engine,
|
|
96
|
-
event: event.id,
|
|
97
|
-
eventText: event.text,
|
|
98
|
-
totalMs: Date.now() - startedAt,
|
|
99
|
-
memoryPrepareMs,
|
|
100
|
-
engineMs: engineResult.durationMs,
|
|
101
|
-
memoryRecordMs,
|
|
102
|
-
promptChars: engineResult.promptChars,
|
|
103
|
-
outputChars: engineResult.outputChars,
|
|
104
|
-
outputText: engineResult.text,
|
|
105
|
-
recall: prepared.recall
|
|
106
|
-
});
|
|
107
|
-
return {
|
|
108
|
-
agentId: this.config.id,
|
|
109
|
-
durationMs: Date.now() - startedAt,
|
|
110
|
-
text: engineResult.text
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
const agents = [
|
|
115
|
-
new MixedEngineAgent({
|
|
116
|
-
id: "navigator",
|
|
117
|
-
name: "Navigator",
|
|
118
|
-
engine: "codex",
|
|
119
|
-
signalPrefix: "COD"
|
|
120
|
-
}),
|
|
121
|
-
new MixedEngineAgent({
|
|
122
|
-
id: "cartographer",
|
|
123
|
-
name: "Cartographer",
|
|
124
|
-
engine: "grok",
|
|
125
|
-
signalPrefix: "GRK"
|
|
126
|
-
}),
|
|
127
|
-
new MixedEngineAgent({
|
|
128
|
-
id: "sentinel",
|
|
129
|
-
name: "Sentinel",
|
|
130
|
-
engine: "agy",
|
|
131
|
-
signalPrefix: "AGY"
|
|
132
|
-
})
|
|
133
|
-
];
|
|
134
|
-
const roomContext = {
|
|
135
|
-
networkId: "mixed-engine-lab",
|
|
136
|
-
roomId: "workbench",
|
|
137
|
-
teamId: "mixed-engine-org",
|
|
138
|
-
participants: agents.map((agent) => agent.config.id)
|
|
139
|
-
};
|
|
140
|
-
const assertIncludes = (label, actual, expected, event) => {
|
|
141
|
-
const passed = actual.includes(expected);
|
|
142
|
-
if (event) {
|
|
143
|
-
observer.recordAssertion({
|
|
144
|
-
detail: `${label} should include ${expected}`,
|
|
145
|
-
event,
|
|
146
|
-
kind: "recall",
|
|
147
|
-
passed
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
if (!passed) {
|
|
151
|
-
throw new Error(`${label} did not include ${expected}.\nActual:\n${actual}`);
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
const assertNoSignalLeak = (event, signals) => {
|
|
155
|
-
let passed = true;
|
|
156
|
-
for (const signal of signals) {
|
|
157
|
-
if (event.text.includes(signal)) {
|
|
158
|
-
passed = false;
|
|
159
|
-
observer.recordAssertion({
|
|
160
|
-
detail: `wake text must not contain ${signal}`,
|
|
161
|
-
event: event.id,
|
|
162
|
-
kind: "no-leak",
|
|
163
|
-
passed
|
|
164
|
-
});
|
|
165
|
-
throw new Error(`wake ${event.id} leaked ${signal} in the current prompt`);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
observer.recordAssertion({
|
|
169
|
-
detail: `wake text does not contain ${signals.length} known signal(s)`,
|
|
170
|
-
event: event.id,
|
|
171
|
-
kind: "no-leak",
|
|
172
|
-
passed
|
|
173
|
-
});
|
|
174
|
-
};
|
|
175
|
-
const transcriptTail = (transcript) => {
|
|
176
|
-
if (transcript.length === 0) {
|
|
177
|
-
return "(empty)";
|
|
178
|
-
}
|
|
179
|
-
const tail = transcript.slice(-maxTranscriptLines);
|
|
180
|
-
const prefix = transcript.length > tail.length
|
|
181
|
-
? `(${transcript.length - tail.length} earlier room line(s) omitted)\n`
|
|
182
|
-
: "";
|
|
183
|
-
return `${prefix}${tail.join("\n")}`;
|
|
184
|
-
};
|
|
185
|
-
const extractSignal = (agent, text) => {
|
|
186
|
-
const match = text.match(/SIGNAL\s*[:=]\s*`?([A-Z0-9_-]{6,80})`?/i);
|
|
187
|
-
if (!match) {
|
|
188
|
-
throw new Error(`Could not extract signal from ${agent.config.id} output:\n${text}`);
|
|
189
|
-
}
|
|
190
|
-
const signal = match[1].toUpperCase();
|
|
191
|
-
if (!signal.startsWith(`${agent.config.signalPrefix}-`)) {
|
|
192
|
-
throw new Error(`${agent.config.id} signal ${signal} does not start with ${agent.config.signalPrefix}-`);
|
|
193
|
-
}
|
|
194
|
-
return signal;
|
|
195
|
-
};
|
|
196
|
-
const seedSignals = async () => {
|
|
197
|
-
console.log("\n== Live seed phase ==");
|
|
198
|
-
const signals = new Map();
|
|
199
|
-
const results = await Promise.all(agents.map(async (agent) => {
|
|
200
|
-
const result = await agent.wake({
|
|
201
|
-
id: `seed-${agent.config.id}`,
|
|
202
|
-
kind: "manual",
|
|
203
|
-
text: [
|
|
204
|
-
"Invent a private signal token for yourself.",
|
|
205
|
-
`The token must start with ${agent.config.signalPrefix}- and use only uppercase letters, numbers, and hyphens.`,
|
|
206
|
-
"Do not use spaces inside the token.",
|
|
207
|
-
"Do not copy examples. Do not mention any other agent.",
|
|
208
|
-
"Reply in one line only: SIGNAL=<token> NOTE=<six words or fewer>"
|
|
209
|
-
].join("\n")
|
|
210
|
-
});
|
|
211
|
-
const signal = extractSignal(agent, result.text);
|
|
212
|
-
return { agent, result, signal };
|
|
213
|
-
}));
|
|
214
|
-
for (const { agent, result, signal } of results) {
|
|
215
|
-
signals.set(agent.config.id, signal);
|
|
216
|
-
observer.recordSignal({
|
|
217
|
-
agent: agent.config.id,
|
|
218
|
-
engine: agent.config.engine,
|
|
219
|
-
signal
|
|
220
|
-
});
|
|
221
|
-
console.log(`${agent.config.id} (${agent.config.engine}) -> ${result.text}`);
|
|
222
|
-
}
|
|
223
|
-
return signals;
|
|
224
|
-
};
|
|
225
|
-
const runRoom = async (signals) => {
|
|
226
|
-
console.log("\n== Mixed-engine room ==");
|
|
227
|
-
const transcript = [];
|
|
228
|
-
const navigatorSignal = signals.get("navigator");
|
|
229
|
-
const cartographerSignal = signals.get("cartographer");
|
|
230
|
-
const sentinelSignal = signals.get("sentinel");
|
|
231
|
-
const navigatorEvent = {
|
|
232
|
-
id: "room-navigator-1",
|
|
233
|
-
kind: "manual",
|
|
234
|
-
context: roomContext,
|
|
235
|
-
text: [
|
|
236
|
-
"Room transcript so far:",
|
|
237
|
-
transcriptTail(transcript),
|
|
238
|
-
"Recall your own private SIGNAL from Daimon memory.",
|
|
239
|
-
"Reply in one line: @cartographer navigator=<your signal> asks cartographer to answer."
|
|
240
|
-
].join("\n")
|
|
241
|
-
};
|
|
242
|
-
assertNoSignalLeak(navigatorEvent, [...signals.values()]);
|
|
243
|
-
const navigator = await agents[0].wake(navigatorEvent);
|
|
244
|
-
assertIncludes("navigator reply", navigator.text, navigatorSignal, navigatorEvent.id);
|
|
245
|
-
observer.recordConsultation({
|
|
246
|
-
event: navigatorEvent.id,
|
|
247
|
-
from: "navigator",
|
|
248
|
-
outputText: navigator.text,
|
|
249
|
-
to: "cartographer"
|
|
250
|
-
});
|
|
251
|
-
transcript.push(`navigator: ${navigator.text}`);
|
|
252
|
-
console.log(transcript.at(-1));
|
|
253
|
-
const cartographerEvent = {
|
|
254
|
-
id: "room-cartographer-1",
|
|
255
|
-
kind: "manual",
|
|
256
|
-
context: roomContext,
|
|
257
|
-
text: [
|
|
258
|
-
"Room transcript so far:",
|
|
259
|
-
transcriptTail(transcript),
|
|
260
|
-
"Recall your own private SIGNAL from Daimon memory.",
|
|
261
|
-
"Reply in one line: @sentinel cartographer=<your signal> observed navigator=<navigator signal>."
|
|
262
|
-
].join("\n")
|
|
263
|
-
};
|
|
264
|
-
assertNoSignalLeak(cartographerEvent, [cartographerSignal, sentinelSignal]);
|
|
265
|
-
const cartographer = await agents[1].wake(cartographerEvent);
|
|
266
|
-
assertIncludes("cartographer reply", cartographer.text, navigatorSignal, cartographerEvent.id);
|
|
267
|
-
assertIncludes("cartographer reply", cartographer.text, cartographerSignal, cartographerEvent.id);
|
|
268
|
-
observer.recordConsultation({
|
|
269
|
-
event: cartographerEvent.id,
|
|
270
|
-
from: "cartographer",
|
|
271
|
-
outputText: cartographer.text,
|
|
272
|
-
to: "sentinel"
|
|
273
|
-
});
|
|
274
|
-
transcript.push(`cartographer: ${cartographer.text}`);
|
|
275
|
-
console.log(transcript.at(-1));
|
|
276
|
-
const sentinelEvent = {
|
|
277
|
-
id: "room-sentinel-1",
|
|
278
|
-
kind: "manual",
|
|
279
|
-
context: roomContext,
|
|
280
|
-
text: [
|
|
281
|
-
"Room transcript so far:",
|
|
282
|
-
transcriptTail(transcript),
|
|
283
|
-
"Recall your own private SIGNAL from Daimon memory.",
|
|
284
|
-
"Reply in one line: sentinel=<your signal> observed navigator=<navigator signal> cartographer=<cartographer signal>."
|
|
285
|
-
].join("\n")
|
|
286
|
-
};
|
|
287
|
-
assertNoSignalLeak(sentinelEvent, [sentinelSignal]);
|
|
288
|
-
const sentinel = await agents[2].wake(sentinelEvent);
|
|
289
|
-
assertIncludes("sentinel reply", sentinel.text, navigatorSignal, sentinelEvent.id);
|
|
290
|
-
assertIncludes("sentinel reply", sentinel.text, cartographerSignal, sentinelEvent.id);
|
|
291
|
-
assertIncludes("sentinel reply", sentinel.text, sentinelSignal, sentinelEvent.id);
|
|
292
|
-
transcript.push(`sentinel: ${sentinel.text}`);
|
|
293
|
-
console.log(transcript.at(-1));
|
|
294
|
-
return transcript;
|
|
295
|
-
};
|
|
296
|
-
const runFinalRecall = async (signals) => {
|
|
297
|
-
console.log("\n== Fresh CLI final recall ==");
|
|
298
|
-
const event = {
|
|
299
|
-
id: "room-sentinel-2",
|
|
300
|
-
kind: "manual",
|
|
301
|
-
context: roomContext,
|
|
302
|
-
text: [
|
|
303
|
-
"There is no room transcript in this wake.",
|
|
304
|
-
"Use only Daimon memory recalled into this fresh CLI turn.",
|
|
305
|
-
"Report all three remembered signals in one line:",
|
|
306
|
-
"final navigator=<token> cartographer=<token> sentinel=<token>"
|
|
307
|
-
].join("\n")
|
|
308
|
-
};
|
|
309
|
-
assertNoSignalLeak(event, [...signals.values()]);
|
|
310
|
-
const result = await agents[2].wake(event);
|
|
311
|
-
for (const signal of signals.values()) {
|
|
312
|
-
assertIncludes("final recall", result.text, signal, event.id);
|
|
313
|
-
}
|
|
314
|
-
console.log(`sentinel (${agents[2].config.engine}) -> ${result.text}`);
|
|
315
|
-
};
|
|
316
|
-
const printMemoryCounts = async () => {
|
|
317
|
-
console.log("\nMemory event counts:");
|
|
318
|
-
for (const agent of agents) {
|
|
319
|
-
const events = await new JsonlMemoryStore(agent.runtimeHomePath).read();
|
|
320
|
-
const counts = events.reduce((memo, event) => {
|
|
321
|
-
memo[event.type] = (memo[event.type] ?? 0) + 1;
|
|
322
|
-
return memo;
|
|
323
|
-
}, {});
|
|
324
|
-
console.log(`${agent.config.id}: ${JSON.stringify(counts)}`);
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
const printBench = async () => {
|
|
328
|
-
console.log("\nBench rows:");
|
|
329
|
-
console.table(observer.benchRows());
|
|
330
|
-
const summary = observer.summary();
|
|
331
|
-
console.log("Bench summary:");
|
|
332
|
-
for (const [engine, row] of Object.entries(summary)) {
|
|
333
|
-
console.log(`${engine}: avg_engine_ms=${Math.round(row.engineMs / row.count)} avg_total_ms=${Math.round(row.totalMs / row.count)} avg_prompt_chars=${Math.round(row.promptChars / row.count)}`);
|
|
334
|
-
}
|
|
335
|
-
await observer.write(runtimeRoot);
|
|
336
|
-
};
|
|
337
|
-
const run = async () => {
|
|
338
|
-
await rm(runtimeRoot, { recursive: true, force: true });
|
|
339
|
-
await Promise.all(agents.map((agent) => agent.prepare()));
|
|
340
|
-
await writeFile(path.join(runtimeRoot, "org.json"), JSON.stringify(agents.map((agent) => agent.config), null, 2));
|
|
341
|
-
const signals = await seedSignals();
|
|
342
|
-
await runRoom(signals);
|
|
343
|
-
await runFinalRecall(signals);
|
|
344
|
-
await printMemoryCounts();
|
|
345
|
-
await printBench();
|
|
346
|
-
console.log("\ne2e:mixed-engine-org ok");
|
|
347
|
-
};
|
|
348
|
-
run().catch((error) => {
|
|
349
|
-
console.error(error instanceof Error ? error.stack ?? error.message : String(error));
|
|
350
|
-
process.exitCode = 1;
|
|
351
|
-
});
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export type EngineKind = "agy" | "codex" | "grok";
|
|
2
|
-
export interface EngineRunResult {
|
|
3
|
-
durationMs: number;
|
|
4
|
-
outputChars: number;
|
|
5
|
-
promptChars: number;
|
|
6
|
-
text: string;
|
|
7
|
-
}
|
|
8
|
-
interface EnginePaths {
|
|
9
|
-
runtimeHomePath: string;
|
|
10
|
-
workspacePath: string;
|
|
11
|
-
}
|
|
12
|
-
export declare const runEngine: (engine: EngineKind, prompt: string, paths: EnginePaths) => Promise<string>;
|
|
13
|
-
export declare const runEngineDetailed: (engine: EngineKind, prompt: string, paths: EnginePaths) => Promise<EngineRunResult>;
|
|
14
|
-
export {};
|
|
15
|
-
//# sourceMappingURL=mixedEngineCli.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mixedEngineCli.d.ts","sourceRoot":"","sources":["../../src/examples/mixedEngineCli.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,WAAW;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;CACvB;AAuKD,eAAO,MAAM,SAAS,GACpB,QAAQ,UAAU,EAClB,QAAQ,MAAM,EACd,OAAO,WAAW,KACjB,OAAO,CAAC,MAAM,CAGhB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,UAAU,EAClB,QAAQ,MAAM,EACd,OAAO,WAAW,KACjB,OAAO,CAAC,eAAe,CAgBzB,CAAC"}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { execFile, spawn } from "node:child_process";
|
|
2
|
-
import { closeSync, openSync } from "node:fs";
|
|
3
|
-
import { readFile, stat, unlink } from "node:fs/promises";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { promisify } from "node:util";
|
|
6
|
-
const execFileAsync = promisify(execFile);
|
|
7
|
-
const maxCapturedOutputBytes = 1024 * 256;
|
|
8
|
-
const outputOptions = {
|
|
9
|
-
maxBuffer: 1024 * 1024 * 8,
|
|
10
|
-
timeout: 180_000
|
|
11
|
-
};
|
|
12
|
-
const stripAnsi = (value) => value.replace(/\u001B\[[0-?]*[ -/]*[@-~]/g, "").trim();
|
|
13
|
-
const pushCapped = (chunks, chunk, state) => {
|
|
14
|
-
if (state.bytes >= maxCapturedOutputBytes) {
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
const remaining = maxCapturedOutputBytes - state.bytes;
|
|
18
|
-
const next = chunk.length > remaining ? chunk.subarray(0, remaining) : chunk;
|
|
19
|
-
chunks.push(next);
|
|
20
|
-
state.bytes += next.length;
|
|
21
|
-
};
|
|
22
|
-
const readBounded = async (filePath) => {
|
|
23
|
-
const stats = await stat(filePath);
|
|
24
|
-
if (stats.size <= maxCapturedOutputBytes) {
|
|
25
|
-
return readFile(filePath, "utf8");
|
|
26
|
-
}
|
|
27
|
-
const content = await readFile(filePath);
|
|
28
|
-
const head = content.subarray(0, maxCapturedOutputBytes).toString("utf8");
|
|
29
|
-
return `${head}\n[truncated ${stats.size - maxCapturedOutputBytes} bytes]`;
|
|
30
|
-
};
|
|
31
|
-
const spawnWithInput = (command, args, input, cwd) => new Promise((resolve, reject) => {
|
|
32
|
-
const child = spawn(command, args, { cwd, stdio: ["pipe", "pipe", "pipe"] });
|
|
33
|
-
const timer = setTimeout(() => {
|
|
34
|
-
child.kill("SIGTERM");
|
|
35
|
-
reject(new Error(`${command} timed out after ${outputOptions.timeout}ms`));
|
|
36
|
-
}, outputOptions.timeout);
|
|
37
|
-
const stdout = [];
|
|
38
|
-
const stderr = [];
|
|
39
|
-
const stdoutState = { bytes: 0 };
|
|
40
|
-
const stderrState = { bytes: 0 };
|
|
41
|
-
child.stdout.on("data", (chunk) => pushCapped(stdout, chunk, stdoutState));
|
|
42
|
-
child.stderr.on("data", (chunk) => pushCapped(stderr, chunk, stderrState));
|
|
43
|
-
child.on("error", (error) => {
|
|
44
|
-
clearTimeout(timer);
|
|
45
|
-
reject(error);
|
|
46
|
-
});
|
|
47
|
-
child.on("close", (code, signal) => {
|
|
48
|
-
clearTimeout(timer);
|
|
49
|
-
const output = {
|
|
50
|
-
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
51
|
-
stderr: Buffer.concat(stderr).toString("utf8")
|
|
52
|
-
};
|
|
53
|
-
if (code === 0) {
|
|
54
|
-
resolve(output);
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
reject(new Error(`${command} exited ${code ?? signal}: ${output.stderr || output.stdout}`));
|
|
58
|
-
});
|
|
59
|
-
child.stdin.end(input);
|
|
60
|
-
});
|
|
61
|
-
const spawnToFiles = (command, args, input) => new Promise((resolve, reject) => {
|
|
62
|
-
const stdoutFd = openSync(input.stdoutPath, "w");
|
|
63
|
-
const stderrFd = openSync(input.stderrPath, "w");
|
|
64
|
-
const closeFiles = () => {
|
|
65
|
-
closeSync(stdoutFd);
|
|
66
|
-
closeSync(stderrFd);
|
|
67
|
-
};
|
|
68
|
-
const child = spawn(command, args, { cwd: input.cwd, stdio: ["ignore", stdoutFd, stderrFd] });
|
|
69
|
-
const timer = setTimeout(() => {
|
|
70
|
-
child.kill("SIGTERM");
|
|
71
|
-
closeFiles();
|
|
72
|
-
reject(new Error(`${command} timed out after ${outputOptions.timeout}ms; stderr=${input.stderrPath}`));
|
|
73
|
-
}, outputOptions.timeout);
|
|
74
|
-
child.on("error", (error) => {
|
|
75
|
-
clearTimeout(timer);
|
|
76
|
-
closeFiles();
|
|
77
|
-
reject(error);
|
|
78
|
-
});
|
|
79
|
-
child.on("close", (code, signal) => {
|
|
80
|
-
clearTimeout(timer);
|
|
81
|
-
closeFiles();
|
|
82
|
-
if (code === 0) {
|
|
83
|
-
resolve();
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
reject(new Error(`${command} exited ${code ?? signal}; stderr=${input.stderrPath}; stdout=${input.stdoutPath}`));
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
const runCodex = async (prompt, paths) => {
|
|
90
|
-
const outputPath = `${paths.runtimeHomePath}/codex-${Date.now()}.txt`;
|
|
91
|
-
const args = [
|
|
92
|
-
"exec",
|
|
93
|
-
"--sandbox",
|
|
94
|
-
"read-only",
|
|
95
|
-
"--ephemeral",
|
|
96
|
-
"--skip-git-repo-check",
|
|
97
|
-
"--ignore-rules",
|
|
98
|
-
"--color",
|
|
99
|
-
"never",
|
|
100
|
-
"-C",
|
|
101
|
-
paths.workspacePath,
|
|
102
|
-
"--output-last-message",
|
|
103
|
-
outputPath
|
|
104
|
-
];
|
|
105
|
-
args.push("-m", process.env.DAIMON_CODEX_MODEL ?? "gpt-5.4-mini");
|
|
106
|
-
args.push("-");
|
|
107
|
-
const { stdout, stderr } = await spawnWithInput("codex", args, prompt, paths.workspacePath);
|
|
108
|
-
try {
|
|
109
|
-
return stripAnsi(await readFile(outputPath, "utf8"));
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
return stripAnsi([stdout, stderr].filter(Boolean).join("\n"));
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
const runGrok = async (prompt, paths) => {
|
|
116
|
-
const { stdout } = await execFileAsync("grok", [
|
|
117
|
-
"--single",
|
|
118
|
-
prompt,
|
|
119
|
-
"--max-turns",
|
|
120
|
-
process.env.DAIMON_GROK_MAX_TURNS ?? "2",
|
|
121
|
-
"--no-memory",
|
|
122
|
-
"--disable-web-search",
|
|
123
|
-
"--cwd",
|
|
124
|
-
paths.workspacePath,
|
|
125
|
-
"--output-format",
|
|
126
|
-
"plain"
|
|
127
|
-
], { ...outputOptions, cwd: paths.workspacePath });
|
|
128
|
-
return stripAnsi(stdout);
|
|
129
|
-
};
|
|
130
|
-
const runAgy = async (prompt, paths) => {
|
|
131
|
-
const outputPath = path.resolve(paths.runtimeHomePath, `agy-output-${Date.now()}.txt`);
|
|
132
|
-
const errorPath = path.resolve(paths.runtimeHomePath, `agy-error-${Date.now()}.txt`);
|
|
133
|
-
await spawnToFiles("agy", [
|
|
134
|
-
"--print",
|
|
135
|
-
prompt,
|
|
136
|
-
"--print-timeout",
|
|
137
|
-
process.env.DAIMON_AGY_TIMEOUT ?? "300s",
|
|
138
|
-
"--model",
|
|
139
|
-
process.env.DAIMON_AGY_MODEL ?? "Gemini 3.5 Flash (Low)",
|
|
140
|
-
"--new-project",
|
|
141
|
-
"--add-dir",
|
|
142
|
-
paths.workspacePath
|
|
143
|
-
], {
|
|
144
|
-
cwd: paths.workspacePath,
|
|
145
|
-
stderrPath: errorPath,
|
|
146
|
-
stdoutPath: outputPath
|
|
147
|
-
});
|
|
148
|
-
const text = stripAnsi(await readBounded(outputPath));
|
|
149
|
-
await Promise.all([unlink(outputPath), unlink(errorPath)].map((promise) => promise.catch(() => undefined)));
|
|
150
|
-
return text;
|
|
151
|
-
};
|
|
152
|
-
export const runEngine = async (engine, prompt, paths) => {
|
|
153
|
-
const result = await runEngineDetailed(engine, prompt, paths);
|
|
154
|
-
return result.text;
|
|
155
|
-
};
|
|
156
|
-
export const runEngineDetailed = async (engine, prompt, paths) => {
|
|
157
|
-
const startedAt = Date.now();
|
|
158
|
-
let text;
|
|
159
|
-
if (engine === "codex") {
|
|
160
|
-
text = await runCodex(prompt, paths);
|
|
161
|
-
}
|
|
162
|
-
else if (engine === "grok") {
|
|
163
|
-
text = await runGrok(prompt, paths);
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
text = await runAgy(prompt, paths);
|
|
167
|
-
}
|
|
168
|
-
return {
|
|
169
|
-
durationMs: Date.now() - startedAt,
|
|
170
|
-
outputChars: text.length,
|
|
171
|
-
promptChars: prompt.length,
|
|
172
|
-
text
|
|
173
|
-
};
|
|
174
|
-
};
|