@openape/ape-agent 2.3.0 → 2.5.0
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/bridge.mjs +72 -16
- package/package.json +1 -1
package/dist/bridge.mjs
CHANGED
|
@@ -1366,6 +1366,19 @@ var ChatApi = class {
|
|
|
1366
1366
|
});
|
|
1367
1367
|
return result;
|
|
1368
1368
|
}
|
|
1369
|
+
/**
|
|
1370
|
+
* Fetch the most recent `limit` messages in a thread, oldest-first.
|
|
1371
|
+
* Used by ThreadSession to seed `history` so the agent has the
|
|
1372
|
+
* full conversation context after a bridge restart — otherwise it
|
|
1373
|
+
* only sees messages that arrived via WS since the process boot.
|
|
1374
|
+
*/
|
|
1375
|
+
async listMessages(roomId, threadId, limit = 50) {
|
|
1376
|
+
const url = `${this.endpoint}/api/rooms/${encodeURIComponent(roomId)}/messages?thread_id=${encodeURIComponent(threadId)}&limit=${limit}`;
|
|
1377
|
+
return await ofetch5(url, {
|
|
1378
|
+
method: "GET",
|
|
1379
|
+
headers: { Authorization: await this.bearer() }
|
|
1380
|
+
});
|
|
1381
|
+
}
|
|
1369
1382
|
async requestContact(peerEmail) {
|
|
1370
1383
|
const url = `${this.endpoint}/api/contacts`;
|
|
1371
1384
|
return await ofetch5(url, {
|
|
@@ -4041,14 +4054,22 @@ var PATCH_INTERVAL_MS = 300;
|
|
|
4041
4054
|
var ThreadSession = class {
|
|
4042
4055
|
constructor(deps) {
|
|
4043
4056
|
this.deps = deps;
|
|
4044
|
-
this.resolvedTools = taskTools(deps.tools);
|
|
4045
4057
|
}
|
|
4046
4058
|
active;
|
|
4047
4059
|
queue = [];
|
|
4048
4060
|
history = [];
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
*
|
|
4061
|
+
/**
|
|
4062
|
+
* Whether we've already backfilled history from the chat server.
|
|
4063
|
+
* Done lazily on the first turn so a freshly-created ThreadSession
|
|
4064
|
+
* (e.g. after a bridge restart) sees the full conversation context,
|
|
4065
|
+
* not just the message that woke it up. We skip the message that
|
|
4066
|
+
* triggered the turn — runLoop adds it via `userMessage`.
|
|
4067
|
+
*/
|
|
4068
|
+
backfilled = false;
|
|
4069
|
+
/**
|
|
4070
|
+
* No-op placeholder kept for API compatibility with the previous
|
|
4071
|
+
* RPC-listener model where dispose() detached the listener.
|
|
4072
|
+
*/
|
|
4052
4073
|
dispose() {
|
|
4053
4074
|
}
|
|
4054
4075
|
/** Forward an inbound chat message to the runtime. Queues if a turn is in flight. */
|
|
@@ -4088,12 +4109,14 @@ var ThreadSession = class {
|
|
|
4088
4109
|
this.deps.log(`status patch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4089
4110
|
}
|
|
4090
4111
|
};
|
|
4112
|
+
const { systemPrompt, tools } = this.deps.resolveConfig();
|
|
4113
|
+
await this.backfillHistoryOnce(replyToMessageId, body);
|
|
4091
4114
|
try {
|
|
4092
4115
|
const result = await runLoop({
|
|
4093
4116
|
config: this.deps.runtimeConfig,
|
|
4094
|
-
systemPrompt
|
|
4117
|
+
systemPrompt,
|
|
4095
4118
|
userMessage: body,
|
|
4096
|
-
tools:
|
|
4119
|
+
tools: taskTools(tools),
|
|
4097
4120
|
maxSteps: this.deps.maxSteps,
|
|
4098
4121
|
history: this.history,
|
|
4099
4122
|
handlers: {
|
|
@@ -4130,6 +4153,33 @@ var ThreadSession = class {
|
|
|
4130
4153
|
await this.failTurn(`(runtime error: ${message})`);
|
|
4131
4154
|
}
|
|
4132
4155
|
}
|
|
4156
|
+
/**
|
|
4157
|
+
* Fetch recent chat history for this thread and seed `this.history`.
|
|
4158
|
+
* Idempotent — only runs once per ThreadSession instance. Skips the
|
|
4159
|
+
* placeholder we just posted plus the inbound message that triggered
|
|
4160
|
+
* this turn (runLoop's `userMessage` handles that one).
|
|
4161
|
+
*
|
|
4162
|
+
* Failures are non-fatal: we log and continue with empty history.
|
|
4163
|
+
* That preserves the pre-backfill behaviour rather than failing the
|
|
4164
|
+
* turn over a transient chat-server hiccup.
|
|
4165
|
+
*/
|
|
4166
|
+
async backfillHistoryOnce(currentMessageId, currentBody) {
|
|
4167
|
+
if (this.backfilled) return;
|
|
4168
|
+
this.backfilled = true;
|
|
4169
|
+
try {
|
|
4170
|
+
const rows = await this.deps.chat.listMessages(this.deps.roomId, this.deps.threadId, 50);
|
|
4171
|
+
for (const row of rows) {
|
|
4172
|
+
if (row.id === currentMessageId) continue;
|
|
4173
|
+
if (!row.body || row.body.length === 0) continue;
|
|
4174
|
+
if (row.body === currentBody && row.senderEmail !== this.deps.selfEmail) continue;
|
|
4175
|
+
const role = row.senderEmail === this.deps.selfEmail ? "assistant" : "user";
|
|
4176
|
+
this.history.push({ role, content: row.body });
|
|
4177
|
+
}
|
|
4178
|
+
this.deps.log(`[${this.deps.roomId}/${this.deps.threadId.slice(0, 8)}] backfilled ${this.history.length} message(s) from chat history`);
|
|
4179
|
+
} catch (err) {
|
|
4180
|
+
this.deps.log(`[${this.deps.roomId}/${this.deps.threadId.slice(0, 8)}] backfill failed (continuing with empty history): ${err instanceof Error ? err.message : String(err)}`);
|
|
4181
|
+
}
|
|
4182
|
+
}
|
|
4133
4183
|
/**
|
|
4134
4184
|
* Stream-end: flush any pending throttled body PATCH, then mark the
|
|
4135
4185
|
* message as no-longer-streaming. The combined call also triggers
|
|
@@ -4365,16 +4415,22 @@ var Bridge = class {
|
|
|
4365
4415
|
threadId,
|
|
4366
4416
|
chat: this.chat,
|
|
4367
4417
|
runtimeConfig: this.runtimeConfig(),
|
|
4368
|
-
//
|
|
4369
|
-
//
|
|
4370
|
-
// effect
|
|
4371
|
-
// SOUL.md + skills
|
|
4372
|
-
//
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4418
|
+
// Resolve tools + systemPrompt on every turn from agent.json
|
|
4419
|
+
// (latest sync from troop). Owner edits in the troop UI thus
|
|
4420
|
+
// take effect on the very next message in an existing thread —
|
|
4421
|
+
// not just on a freshly-opened one. SOUL.md + skills get merged
|
|
4422
|
+
// into the system prompt the same way.
|
|
4423
|
+
resolveConfig: () => {
|
|
4424
|
+
const tools = resolveTools(this.cfg.tools);
|
|
4425
|
+
return {
|
|
4426
|
+
tools,
|
|
4427
|
+
systemPrompt: composeSystemPrompt({
|
|
4428
|
+
base: resolveSystemPrompt(this.cfg.systemPrompt),
|
|
4429
|
+
enabledTools: tools
|
|
4430
|
+
})
|
|
4431
|
+
};
|
|
4432
|
+
},
|
|
4433
|
+
selfEmail: this.selfEmail,
|
|
4378
4434
|
maxSteps: this.cfg.maxSteps,
|
|
4379
4435
|
log
|
|
4380
4436
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openape/ape-agent",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "OpenApe agent runtime: per-agent process that connects to chat.openape.ai, runs the LLM loop with tools + cron tasks, and streams replies back to owners.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|