clawlet 0.5.0 → 0.5.1
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/package.json +1 -1
- package/src/agent.ts +70 -70
package/package.json
CHANGED
package/src/agent.ts
CHANGED
|
@@ -289,86 +289,86 @@ export class Agent {
|
|
|
289
289
|
if (!this.initialized) await this.init();
|
|
290
290
|
this.processing = true;
|
|
291
291
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
292
|
+
while (true) {
|
|
293
|
+
const queuedItem = await this.memory.queue.pop("main-session");
|
|
294
|
+
if (!queuedItem) {
|
|
295
|
+
this.processing = false;
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const { text, label } = queuedItem;
|
|
298
299
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
300
|
+
for (const out of this.outputAdapters) {
|
|
301
|
+
out.onAgentStart(label);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
this.messages = await this.memory.compactHistory("main-session", this.model);
|
|
302
305
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
break;
|
|
306
|
+
// Bootstrap: if bootstrapPrompt is set, run it instead of normal chat
|
|
307
|
+
// until the required files (SOUL.md, IDENTITY.md, USER.md) are created
|
|
308
|
+
const isFirstMessage = this.messages.length === 0;
|
|
309
|
+
let input: string;
|
|
310
|
+
if (this.bootstrapPrompt && isFirstMessage) {
|
|
311
|
+
input = `[BOOTSTRAP MODE] The workspace is not yet set up.\n\n` +
|
|
312
|
+
`${this.bootstrapPrompt}\n\n` +
|
|
313
|
+
`Use fs.writeFile to create each file in the workspace when the user provides the information.\n\n` +
|
|
314
|
+
`--- USER MESSAGE ---\n${text}`;
|
|
315
|
+
} else if (this.bootstrapPrompt) {
|
|
316
|
+
// Still in bootstrap mode (subsequent messages) — check if bootstrap is complete
|
|
317
|
+
const workspaceDir = path.join(process.cwd(), 'workspace');
|
|
318
|
+
const requiredFiles = ['SOUL.md', 'IDENTITY.md', 'USER.md'];
|
|
319
|
+
let allExist = true;
|
|
320
|
+
for (const file of requiredFiles) {
|
|
321
|
+
try {
|
|
322
|
+
await access(path.join(workspaceDir, file));
|
|
323
|
+
} catch {
|
|
324
|
+
allExist = false;
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
325
327
|
}
|
|
328
|
+
if (allExist) {
|
|
329
|
+
this.bootstrapPrompt = null;
|
|
330
|
+
console.log(` ✅ Bootstrap complete! SOUL.md, IDENTITY.md, and USER.md are now present.`);
|
|
331
|
+
}
|
|
332
|
+
input = text;
|
|
333
|
+
} else if (isFirstMessage) {
|
|
334
|
+
input = `[SYSTEM BOOT] This is a fresh session. Before responding to the user, you MUST execute the "Every Session" protocol from AGENTS.md NOW using your tools:\n` +
|
|
335
|
+
`1. Call fs.readFile for SOUL.md\n` +
|
|
336
|
+
`2. Call fs.readFile for USER.md\n` +
|
|
337
|
+
`3. Call fs.readFile for memory:${getTodayString()}.md (create it with fs.writeFile if it doesn't exist)\n` +
|
|
338
|
+
`4. Call fs.readFile for MEMORY.md\n` +
|
|
339
|
+
`Execute ALL of these tool calls first, then respond to the user's message below.\n\n` +
|
|
340
|
+
`--- USER MESSAGE ---\n${text}`;
|
|
341
|
+
} else {
|
|
342
|
+
input = text;
|
|
326
343
|
}
|
|
327
|
-
if (allExist) {
|
|
328
|
-
this.bootstrapPrompt = null;
|
|
329
|
-
console.log(` ✅ Bootstrap complete! SOUL.md, IDENTITY.md, and USER.md are now present.`);
|
|
330
|
-
}
|
|
331
|
-
input = text;
|
|
332
|
-
} else if (isFirstMessage) {
|
|
333
|
-
input = `[SYSTEM BOOT] This is a fresh session. Before responding to the user, you MUST execute the "Every Session" protocol from AGENTS.md NOW using your tools:\n` +
|
|
334
|
-
`1. Call fs.readFile for SOUL.md\n` +
|
|
335
|
-
`2. Call fs.readFile for USER.md\n` +
|
|
336
|
-
`3. Call fs.readFile for memory:${getTodayString()}.md (create it with fs.writeFile if it doesn't exist)\n` +
|
|
337
|
-
`4. Call fs.readFile for MEMORY.md\n` +
|
|
338
|
-
`Execute ALL of these tool calls first, then respond to the user's message below.\n\n` +
|
|
339
|
-
`--- USER MESSAGE ---\n${text}`;
|
|
340
|
-
} else {
|
|
341
|
-
input = text;
|
|
342
|
-
}
|
|
343
344
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
345
|
+
let fullResponse = "";
|
|
346
|
+
try {
|
|
347
|
+
const newMessages = await runAgent(input, this.memory, this.model, this.messages, this.tools, (chunk) => {
|
|
348
|
+
fullResponse += chunk;
|
|
349
|
+
for (const out of this.outputAdapters) {
|
|
350
|
+
out.onResponseChunk(chunk);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
for (const msg of newMessages) {
|
|
355
|
+
if (typeof msg.content !== "string") {
|
|
356
|
+
msg.content = msg.content.filter((part) => part.type !== 'reasoning');
|
|
357
|
+
}
|
|
358
|
+
await this.memory.history.push("main-session", msg);
|
|
350
359
|
}
|
|
351
|
-
});
|
|
352
360
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
msg.content = msg.content.filter((part) => part.type !== 'reasoning');
|
|
361
|
+
for (const out of this.outputAdapters) {
|
|
362
|
+
out.onResponseEnd(fullResponse);
|
|
356
363
|
}
|
|
357
|
-
await this.memory.history.push("main-session", msg);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
for (const out of this.outputAdapters) {
|
|
361
|
-
out.onResponseEnd(fullResponse);
|
|
362
|
-
}
|
|
363
364
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
365
|
+
// Compact history if it's grown past the threshold
|
|
366
|
+
this.messages = await this.memory.compactHistory("main-session", this.model);
|
|
367
|
+
} catch (error: any) {
|
|
368
|
+
for (const out of this.outputAdapters) {
|
|
369
|
+
out.onError(error);
|
|
370
|
+
}
|
|
369
371
|
}
|
|
370
372
|
}
|
|
371
|
-
|
|
372
|
-
this.processing = false;
|
|
373
373
|
}
|
|
374
374
|
}
|