@openape/ape-agent 2.2.0 → 2.3.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 +68 -13
- package/package.json +1 -1
package/dist/bridge.mjs
CHANGED
|
@@ -1353,11 +1353,12 @@ var ChatApi = class {
|
|
|
1353
1353
|
this.bearer = bearer;
|
|
1354
1354
|
}
|
|
1355
1355
|
async postMessage(roomId, body, opts = {}) {
|
|
1356
|
-
const
|
|
1356
|
+
const bodyForServer = opts.streaming ? body : clamp(body, MAX_BODY);
|
|
1357
1357
|
const url = `${this.endpoint}/api/rooms/${encodeURIComponent(roomId)}/messages`;
|
|
1358
|
-
const payload = { body:
|
|
1358
|
+
const payload = { body: bodyForServer };
|
|
1359
1359
|
if (opts.replyTo) payload.reply_to = opts.replyTo;
|
|
1360
1360
|
if (opts.threadId) payload.thread_id = opts.threadId;
|
|
1361
|
+
if (opts.streaming) payload.streaming = true;
|
|
1361
1362
|
const result = await ofetch5(url, {
|
|
1362
1363
|
method: "POST",
|
|
1363
1364
|
headers: { Authorization: await this.bearer() },
|
|
@@ -1401,13 +1402,32 @@ var ChatApi = class {
|
|
|
1401
1402
|
body: { name: name.slice(0, 100) }
|
|
1402
1403
|
});
|
|
1403
1404
|
}
|
|
1404
|
-
|
|
1405
|
-
|
|
1405
|
+
/**
|
|
1406
|
+
* Update an in-flight or completed message. The server differentiates
|
|
1407
|
+
* three modes via the message's current `streaming` state and the
|
|
1408
|
+
* `streaming` field in this call:
|
|
1409
|
+
*
|
|
1410
|
+
* - Stream tick: pass `body` only (current accumulated text).
|
|
1411
|
+
* Server keeps streaming=true and does NOT bump edited_at.
|
|
1412
|
+
* - Stream end: pass `body` + `streaming: false`. Server clears
|
|
1413
|
+
* the streaming flag and triggers the user-facing push.
|
|
1414
|
+
* - Tool-call status: pass `streamingStatus` only (no body).
|
|
1415
|
+
* Renders as "🔧 time.now" in the typing-subtitle.
|
|
1416
|
+
* - Tool-call cleared: pass `streamingStatus: null`.
|
|
1417
|
+
*/
|
|
1418
|
+
async patchMessage(messageId, opts = {}) {
|
|
1406
1419
|
const url = `${this.endpoint}/api/messages/${encodeURIComponent(messageId)}`;
|
|
1420
|
+
const payload = {};
|
|
1421
|
+
if (opts.body !== void 0) {
|
|
1422
|
+
payload.body = opts.streaming === false && opts.body.trim().length === 0 ? clamp(opts.body, MAX_BODY) : opts.body.length <= MAX_BODY ? opts.body : `${opts.body.slice(0, MAX_BODY - 1)}\u2026`;
|
|
1423
|
+
}
|
|
1424
|
+
if (opts.streaming !== void 0) payload.streaming = opts.streaming;
|
|
1425
|
+
if (opts.streamingStatus !== void 0) payload.streaming_status = opts.streamingStatus;
|
|
1426
|
+
if (Object.keys(payload).length === 0) return;
|
|
1407
1427
|
await ofetch5(url, {
|
|
1408
1428
|
method: "PATCH",
|
|
1409
1429
|
headers: { Authorization: await this.bearer() },
|
|
1410
|
-
body:
|
|
1430
|
+
body: payload
|
|
1411
1431
|
});
|
|
1412
1432
|
}
|
|
1413
1433
|
};
|
|
@@ -4040,9 +4060,10 @@ var ThreadSession = class {
|
|
|
4040
4060
|
void this.startTurn(body, replyToMessageId);
|
|
4041
4061
|
}
|
|
4042
4062
|
async startTurn(body, replyToMessageId) {
|
|
4043
|
-
const placeholder = await this.deps.chat.postMessage(this.deps.roomId, "
|
|
4063
|
+
const placeholder = await this.deps.chat.postMessage(this.deps.roomId, "", {
|
|
4044
4064
|
replyTo: replyToMessageId,
|
|
4045
|
-
threadId: this.deps.threadId
|
|
4065
|
+
threadId: this.deps.threadId,
|
|
4066
|
+
streaming: true
|
|
4046
4067
|
});
|
|
4047
4068
|
const turn = {
|
|
4048
4069
|
placeholderId: placeholder.id,
|
|
@@ -4050,15 +4071,23 @@ var ThreadSession = class {
|
|
|
4050
4071
|
replyToMessageId,
|
|
4051
4072
|
throttle: createThrottle(async () => {
|
|
4052
4073
|
if (!this.active || this.active.placeholderId !== placeholder.id) return;
|
|
4053
|
-
const text = this.active.accumulated
|
|
4074
|
+
const text = this.active.accumulated;
|
|
4075
|
+
if (text.length === 0) return;
|
|
4054
4076
|
try {
|
|
4055
|
-
await this.deps.chat.patchMessage(placeholder.id, text);
|
|
4077
|
+
await this.deps.chat.patchMessage(placeholder.id, { body: text });
|
|
4056
4078
|
} catch (err) {
|
|
4057
4079
|
this.deps.log(`patch failed (room=${this.deps.roomId} thread=${this.deps.threadId}): ${err instanceof Error ? err.message : String(err)}`);
|
|
4058
4080
|
}
|
|
4059
4081
|
}, PATCH_INTERVAL_MS)
|
|
4060
4082
|
};
|
|
4061
4083
|
this.active = turn;
|
|
4084
|
+
const setStatus = async (status) => {
|
|
4085
|
+
try {
|
|
4086
|
+
await this.deps.chat.patchMessage(placeholder.id, { streamingStatus: status });
|
|
4087
|
+
} catch (err) {
|
|
4088
|
+
this.deps.log(`status patch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4089
|
+
}
|
|
4090
|
+
};
|
|
4062
4091
|
try {
|
|
4063
4092
|
const result = await runLoop({
|
|
4064
4093
|
config: this.deps.runtimeConfig,
|
|
@@ -4075,12 +4104,15 @@ var ThreadSession = class {
|
|
|
4075
4104
|
},
|
|
4076
4105
|
onToolCall: ({ name }) => {
|
|
4077
4106
|
this.deps.log(`[${this.deps.roomId}/${this.deps.threadId.slice(0, 8)}] tool_call: ${name}`);
|
|
4107
|
+
void setStatus(`\u{1F527} ${name}`);
|
|
4078
4108
|
},
|
|
4079
4109
|
onToolResult: ({ name }) => {
|
|
4080
4110
|
this.deps.log(`[${this.deps.roomId}/${this.deps.threadId.slice(0, 8)}] tool_result: ${name}`);
|
|
4111
|
+
void setStatus(null);
|
|
4081
4112
|
},
|
|
4082
4113
|
onToolError: ({ name, error }) => {
|
|
4083
4114
|
this.deps.log(`[${this.deps.roomId}/${this.deps.threadId.slice(0, 8)}] tool_error: ${name} \u2192 ${error}`);
|
|
4115
|
+
void setStatus(null);
|
|
4084
4116
|
}
|
|
4085
4117
|
}
|
|
4086
4118
|
});
|
|
@@ -4091,28 +4123,51 @@ var ThreadSession = class {
|
|
|
4091
4123
|
if (result.status === "error") {
|
|
4092
4124
|
this.deps.log(`runtime done with status=error (room=${this.deps.roomId} thread=${this.deps.threadId})`);
|
|
4093
4125
|
}
|
|
4094
|
-
this.endTurn();
|
|
4126
|
+
await this.endTurn();
|
|
4095
4127
|
} catch (err) {
|
|
4096
4128
|
const message = err instanceof Error ? err.message : String(err);
|
|
4097
4129
|
this.deps.log(`runtime error (room=${this.deps.roomId} thread=${this.deps.threadId}): ${message}`);
|
|
4098
|
-
this.failTurn(`(runtime error: ${message})`);
|
|
4130
|
+
await this.failTurn(`(runtime error: ${message})`);
|
|
4099
4131
|
}
|
|
4100
4132
|
}
|
|
4101
|
-
|
|
4133
|
+
/**
|
|
4134
|
+
* Stream-end: flush any pending throttled body PATCH, then mark the
|
|
4135
|
+
* message as no-longer-streaming. The combined call also triggers
|
|
4136
|
+
* the user-facing push (the placeholder POST suppressed it).
|
|
4137
|
+
*/
|
|
4138
|
+
async endTurn() {
|
|
4102
4139
|
const turn = this.active;
|
|
4103
4140
|
if (!turn) return;
|
|
4104
4141
|
turn.throttle.flush();
|
|
4142
|
+
try {
|
|
4143
|
+
await this.deps.chat.patchMessage(turn.placeholderId, {
|
|
4144
|
+
body: turn.accumulated || "(empty response)",
|
|
4145
|
+
streaming: false,
|
|
4146
|
+
streamingStatus: null
|
|
4147
|
+
});
|
|
4148
|
+
} catch (err) {
|
|
4149
|
+
this.deps.log(`stream-end patch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4150
|
+
}
|
|
4105
4151
|
this.active = void 0;
|
|
4106
4152
|
const next = this.queue.shift();
|
|
4107
4153
|
if (next) {
|
|
4108
4154
|
void this.startTurn(next.body, next.replyToMessageId);
|
|
4109
4155
|
}
|
|
4110
4156
|
}
|
|
4111
|
-
failTurn(message) {
|
|
4157
|
+
async failTurn(message) {
|
|
4112
4158
|
const turn = this.active;
|
|
4113
4159
|
if (!turn) return;
|
|
4114
4160
|
turn.accumulated = message;
|
|
4115
4161
|
turn.throttle.flush();
|
|
4162
|
+
try {
|
|
4163
|
+
await this.deps.chat.patchMessage(turn.placeholderId, {
|
|
4164
|
+
body: message,
|
|
4165
|
+
streaming: false,
|
|
4166
|
+
streamingStatus: null
|
|
4167
|
+
});
|
|
4168
|
+
} catch (err) {
|
|
4169
|
+
this.deps.log(`fail-turn patch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4170
|
+
}
|
|
4116
4171
|
this.active = void 0;
|
|
4117
4172
|
const next = this.queue.shift();
|
|
4118
4173
|
if (next) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openape/ape-agent",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.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",
|