@openape/ape-agent 2.8.12 → 2.8.14
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 +379 -178
- package/package.json +3 -3
package/dist/bridge.mjs
CHANGED
|
@@ -1053,6 +1053,7 @@ import { ofetch as ofetch2 } from "ofetch";
|
|
|
1053
1053
|
import { Buffer as Buffer3 } from "buffer";
|
|
1054
1054
|
import { createPrivateKey } from "crypto";
|
|
1055
1055
|
import { ofetch as ofetch4 } from "ofetch";
|
|
1056
|
+
import { ofetch as ofetch5 } from "ofetch";
|
|
1056
1057
|
function getConfigDir() {
|
|
1057
1058
|
const override = process.env.OPENAPE_CLI_AUTH_HOME;
|
|
1058
1059
|
if (override) return override;
|
|
@@ -1398,7 +1399,7 @@ import { decodeJwt } from "jose";
|
|
|
1398
1399
|
import WebSocket from "ws";
|
|
1399
1400
|
|
|
1400
1401
|
// src/chat-api.ts
|
|
1401
|
-
import { ofetch as
|
|
1402
|
+
import { ofetch as ofetch6 } from "ofetch";
|
|
1402
1403
|
var MAX_BODY = 1e4;
|
|
1403
1404
|
var ChatApi = class {
|
|
1404
1405
|
constructor(endpoint, bearer) {
|
|
@@ -1414,7 +1415,7 @@ var ChatApi = class {
|
|
|
1414
1415
|
if (opts.replyTo) payload.reply_to = opts.replyTo;
|
|
1415
1416
|
if (opts.threadId) payload.thread_id = opts.threadId;
|
|
1416
1417
|
if (opts.streaming) payload.streaming = true;
|
|
1417
|
-
const result = await
|
|
1418
|
+
const result = await ofetch6(url, {
|
|
1418
1419
|
method: "POST",
|
|
1419
1420
|
headers: { Authorization: await this.bearer() },
|
|
1420
1421
|
body: payload
|
|
@@ -1429,14 +1430,14 @@ var ChatApi = class {
|
|
|
1429
1430
|
*/
|
|
1430
1431
|
async listMessages(roomId, threadId, limit = 50) {
|
|
1431
1432
|
const url = `${this.endpoint}/api/rooms/${encodeURIComponent(roomId)}/messages?thread_id=${encodeURIComponent(threadId)}&limit=${limit}`;
|
|
1432
|
-
return await
|
|
1433
|
+
return await ofetch6(url, {
|
|
1433
1434
|
method: "GET",
|
|
1434
1435
|
headers: { Authorization: await this.bearer() }
|
|
1435
1436
|
});
|
|
1436
1437
|
}
|
|
1437
1438
|
async requestContact(peerEmail) {
|
|
1438
1439
|
const url = `${this.endpoint}/api/contacts`;
|
|
1439
|
-
return await
|
|
1440
|
+
return await ofetch6(url, {
|
|
1440
1441
|
method: "POST",
|
|
1441
1442
|
headers: { Authorization: await this.bearer() },
|
|
1442
1443
|
body: { email: peerEmail }
|
|
@@ -1444,14 +1445,14 @@ var ChatApi = class {
|
|
|
1444
1445
|
}
|
|
1445
1446
|
async listContacts() {
|
|
1446
1447
|
const url = `${this.endpoint}/api/contacts`;
|
|
1447
|
-
return await
|
|
1448
|
+
return await ofetch6(url, {
|
|
1448
1449
|
method: "GET",
|
|
1449
1450
|
headers: { Authorization: await this.bearer() }
|
|
1450
1451
|
});
|
|
1451
1452
|
}
|
|
1452
1453
|
async acceptContact(peerEmail) {
|
|
1453
1454
|
const url = `${this.endpoint}/api/contacts/${encodeURIComponent(peerEmail)}/accept`;
|
|
1454
|
-
return await
|
|
1455
|
+
return await ofetch6(url, {
|
|
1455
1456
|
method: "POST",
|
|
1456
1457
|
headers: { Authorization: await this.bearer() }
|
|
1457
1458
|
});
|
|
@@ -1464,7 +1465,7 @@ var ChatApi = class {
|
|
|
1464
1465
|
*/
|
|
1465
1466
|
async createThread(roomId, name) {
|
|
1466
1467
|
const url = `${this.endpoint}/api/rooms/${encodeURIComponent(roomId)}/threads`;
|
|
1467
|
-
return await
|
|
1468
|
+
return await ofetch6(url, {
|
|
1468
1469
|
method: "POST",
|
|
1469
1470
|
headers: { Authorization: await this.bearer() },
|
|
1470
1471
|
body: { name: name.slice(0, 100) }
|
|
@@ -1492,7 +1493,7 @@ var ChatApi = class {
|
|
|
1492
1493
|
if (opts.streaming !== void 0) payload.streaming = opts.streaming;
|
|
1493
1494
|
if (opts.streamingStatus !== void 0) payload.streaming_status = opts.streamingStatus;
|
|
1494
1495
|
if (Object.keys(payload).length === 0) return;
|
|
1495
|
-
await
|
|
1496
|
+
await ofetch6(url, {
|
|
1496
1497
|
method: "PATCH",
|
|
1497
1498
|
headers: { Authorization: await this.bearer() },
|
|
1498
1499
|
body: payload
|
|
@@ -1505,12 +1506,133 @@ function clamp(s2, max) {
|
|
|
1505
1506
|
return `${s2.slice(0, max - 1)}\u2026`;
|
|
1506
1507
|
}
|
|
1507
1508
|
|
|
1509
|
+
// src/troop-chat-api.ts
|
|
1510
|
+
import { ofetch as ofetch7 } from "ofetch";
|
|
1511
|
+
var MAX_BODY2 = 64 * 1024;
|
|
1512
|
+
var SYNTHETIC_THREAD_ID = "main";
|
|
1513
|
+
function asHistory(msg, agentEmail, ownerEmail) {
|
|
1514
|
+
return {
|
|
1515
|
+
id: msg.id,
|
|
1516
|
+
roomId: msg.chatId,
|
|
1517
|
+
threadId: SYNTHETIC_THREAD_ID,
|
|
1518
|
+
senderEmail: msg.role === "agent" ? agentEmail : ownerEmail,
|
|
1519
|
+
senderAct: msg.role,
|
|
1520
|
+
body: msg.body,
|
|
1521
|
+
replyTo: msg.replyTo,
|
|
1522
|
+
createdAt: msg.createdAt
|
|
1523
|
+
};
|
|
1524
|
+
}
|
|
1525
|
+
function asPosted(msg) {
|
|
1526
|
+
return {
|
|
1527
|
+
id: msg.id,
|
|
1528
|
+
roomId: msg.chatId,
|
|
1529
|
+
threadId: SYNTHETIC_THREAD_ID,
|
|
1530
|
+
body: msg.body,
|
|
1531
|
+
createdAt: msg.createdAt
|
|
1532
|
+
};
|
|
1533
|
+
}
|
|
1534
|
+
var TroopChatApi = class {
|
|
1535
|
+
constructor(endpoint, bearer) {
|
|
1536
|
+
this.endpoint = endpoint;
|
|
1537
|
+
this.bearer = bearer;
|
|
1538
|
+
}
|
|
1539
|
+
endpoint;
|
|
1540
|
+
bearer;
|
|
1541
|
+
bootstrap = null;
|
|
1542
|
+
/** Resolve + cache the agent's chat row (lazy fetch on first use). */
|
|
1543
|
+
async getBootstrap() {
|
|
1544
|
+
if (this.bootstrap) return this.bootstrap;
|
|
1545
|
+
this.bootstrap = await ofetch7(`${this.endpoint}/api/agents/me/chat`, {
|
|
1546
|
+
method: "GET",
|
|
1547
|
+
headers: { Authorization: await this.bearer() }
|
|
1548
|
+
});
|
|
1549
|
+
return this.bootstrap;
|
|
1550
|
+
}
|
|
1551
|
+
/** chat.id + (lazy-fetched) ownerEmail for the bridge's frame-translation path. */
|
|
1552
|
+
async getChatContext() {
|
|
1553
|
+
const b2 = await this.getBootstrap();
|
|
1554
|
+
return { chatId: b2.chat.id, ownerEmail: b2.chat.ownerEmail, agentEmail: b2.chat.agentEmail };
|
|
1555
|
+
}
|
|
1556
|
+
async postMessage(roomId, body, opts = {}) {
|
|
1557
|
+
void roomId;
|
|
1558
|
+
void opts.threadId;
|
|
1559
|
+
const payload = {
|
|
1560
|
+
body: body.length > MAX_BODY2 ? `${body.slice(0, MAX_BODY2 - 1)}\u2026` : body
|
|
1561
|
+
};
|
|
1562
|
+
if (opts.replyTo) payload.reply_to = opts.replyTo;
|
|
1563
|
+
if (opts.streaming) payload.streaming = true;
|
|
1564
|
+
const msg = await ofetch7(`${this.endpoint}/api/agents/me/chat/messages`, {
|
|
1565
|
+
method: "POST",
|
|
1566
|
+
headers: { Authorization: await this.bearer() },
|
|
1567
|
+
body: payload
|
|
1568
|
+
});
|
|
1569
|
+
return asPosted(msg);
|
|
1570
|
+
}
|
|
1571
|
+
async listMessages(roomId, threadId, limit = 50) {
|
|
1572
|
+
void roomId;
|
|
1573
|
+
void threadId;
|
|
1574
|
+
void limit;
|
|
1575
|
+
const fresh = await ofetch7(`${this.endpoint}/api/agents/me/chat`, {
|
|
1576
|
+
method: "GET",
|
|
1577
|
+
headers: { Authorization: await this.bearer() }
|
|
1578
|
+
});
|
|
1579
|
+
this.bootstrap = fresh;
|
|
1580
|
+
return fresh.messages.map((m2) => asHistory(m2, fresh.chat.agentEmail, fresh.chat.ownerEmail));
|
|
1581
|
+
}
|
|
1582
|
+
async patchMessage(messageId, opts = {}) {
|
|
1583
|
+
const payload = {};
|
|
1584
|
+
if (opts.body !== void 0) {
|
|
1585
|
+
payload.body = opts.body.length > MAX_BODY2 ? `${opts.body.slice(0, MAX_BODY2 - 1)}\u2026` : opts.body;
|
|
1586
|
+
}
|
|
1587
|
+
if (opts.streaming !== void 0) payload.streaming = opts.streaming;
|
|
1588
|
+
if (opts.streamingStatus !== void 0) payload.streaming_status = opts.streamingStatus;
|
|
1589
|
+
if (Object.keys(payload).length === 0) return;
|
|
1590
|
+
await ofetch7(`${this.endpoint}/api/agents/me/chat/messages/${encodeURIComponent(messageId)}`, {
|
|
1591
|
+
method: "PATCH",
|
|
1592
|
+
headers: { Authorization: await this.bearer() },
|
|
1593
|
+
body: payload
|
|
1594
|
+
});
|
|
1595
|
+
}
|
|
1596
|
+
/**
|
|
1597
|
+
* Troop's chat doesn't have contacts — synthesize a single
|
|
1598
|
+
* always-connected entry pointing at the owner so the bridge's
|
|
1599
|
+
* initial-contact + allowlist flows are no-ops.
|
|
1600
|
+
*/
|
|
1601
|
+
async listContacts() {
|
|
1602
|
+
const b2 = await this.getBootstrap();
|
|
1603
|
+
return [{
|
|
1604
|
+
peerEmail: b2.chat.ownerEmail,
|
|
1605
|
+
myStatus: "accepted",
|
|
1606
|
+
theirStatus: "accepted",
|
|
1607
|
+
connected: true,
|
|
1608
|
+
roomId: b2.chat.id
|
|
1609
|
+
}];
|
|
1610
|
+
}
|
|
1611
|
+
async requestContact(peerEmail) {
|
|
1612
|
+
void peerEmail;
|
|
1613
|
+
return (await this.listContacts())[0];
|
|
1614
|
+
}
|
|
1615
|
+
async acceptContact(peerEmail) {
|
|
1616
|
+
void peerEmail;
|
|
1617
|
+
return (await this.listContacts())[0];
|
|
1618
|
+
}
|
|
1619
|
+
/**
|
|
1620
|
+
* Troop has no threads — return a synthetic one. The bridge's
|
|
1621
|
+
* cron-runner falls back to the main thread on createThread
|
|
1622
|
+
* failure already, so a stable "main" stand-in is the right shape.
|
|
1623
|
+
*/
|
|
1624
|
+
async createThread(roomId, name) {
|
|
1625
|
+
void roomId;
|
|
1626
|
+
return { id: SYNTHETIC_THREAD_ID, name: name.slice(0, 100) };
|
|
1627
|
+
}
|
|
1628
|
+
};
|
|
1629
|
+
|
|
1508
1630
|
// src/cron-runner.ts
|
|
1509
1631
|
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
1510
1632
|
import { homedir as homedir6 } from "os";
|
|
1511
1633
|
import { join as join6 } from "path";
|
|
1512
1634
|
|
|
1513
|
-
// ../../packages/apes/dist/chunk-
|
|
1635
|
+
// ../../packages/apes/dist/chunk-ZEUSCNCH.js
|
|
1514
1636
|
import { spawn } from "child_process";
|
|
1515
1637
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
1516
1638
|
import { homedir as homedir3 } from "os";
|
|
@@ -1530,8 +1652,10 @@ function capStdio(s2) {
|
|
|
1530
1652
|
[truncated to ${MAX_STDIO_BYTES} bytes]`;
|
|
1531
1653
|
}
|
|
1532
1654
|
function runApeShell(cmd, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
1655
|
+
const bypass = process.env.OPENAPE_BYPASS_APE_SHELL === "1";
|
|
1656
|
+
const [execBin, execArgs] = bypass ? ["/bin/bash", ["-c", cmd]] : [BIN, ["-c", cmd]];
|
|
1533
1657
|
return new Promise((resolveResult) => {
|
|
1534
|
-
const child = spawn(
|
|
1658
|
+
const child = spawn(execBin, execArgs, {
|
|
1535
1659
|
env: { ...process.env, APE_WAIT: "1" },
|
|
1536
1660
|
stdio: ["ignore", "pipe", "pipe"]
|
|
1537
1661
|
});
|
|
@@ -1566,7 +1690,7 @@ function runApeShell(cmd, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
|
1566
1690
|
stderr: "",
|
|
1567
1691
|
exit_code: -1,
|
|
1568
1692
|
error: spawnError.message,
|
|
1569
|
-
hint: `Could not exec '${
|
|
1693
|
+
hint: `Could not exec '${execBin}'. The agent host needs @openape/apes installed globally so ape-shell is on PATH (or set OPENAPE_BYPASS_APE_SHELL=1 to skip the gated shell entirely \u2014 meant for the OpenApe pod where the container IS the sandbox).`
|
|
1570
1694
|
});
|
|
1571
1695
|
return;
|
|
1572
1696
|
}
|
|
@@ -2324,6 +2448,52 @@ function previewJson(value, max = 500) {
|
|
|
2324
2448
|
}
|
|
2325
2449
|
return s2.length > max ? `${s2.slice(0, max)}\u2026` : s2;
|
|
2326
2450
|
}
|
|
2451
|
+
async function aggregateChatStream(res) {
|
|
2452
|
+
if (!res.body) throw new Error("LiteLLM streaming response had no body");
|
|
2453
|
+
const reader = res.body.getReader();
|
|
2454
|
+
const decoder = new TextDecoder();
|
|
2455
|
+
let buf = "";
|
|
2456
|
+
let content = "";
|
|
2457
|
+
const toolCalls = /* @__PURE__ */ new Map();
|
|
2458
|
+
let finishReason;
|
|
2459
|
+
while (true) {
|
|
2460
|
+
const { value, done } = await reader.read();
|
|
2461
|
+
if (done) break;
|
|
2462
|
+
buf += decoder.decode(value, { stream: true });
|
|
2463
|
+
while (true) {
|
|
2464
|
+
const nl = buf.indexOf("\n");
|
|
2465
|
+
if (nl === -1) break;
|
|
2466
|
+
const line = buf.slice(0, nl).trim();
|
|
2467
|
+
buf = buf.slice(nl + 1);
|
|
2468
|
+
if (!line.startsWith("data:")) continue;
|
|
2469
|
+
const payload = line.slice(5).trim();
|
|
2470
|
+
if (!payload || payload === "[DONE]") continue;
|
|
2471
|
+
let chunk;
|
|
2472
|
+
try {
|
|
2473
|
+
chunk = JSON.parse(payload);
|
|
2474
|
+
} catch {
|
|
2475
|
+
continue;
|
|
2476
|
+
}
|
|
2477
|
+
const ch0 = chunk.choices?.[0];
|
|
2478
|
+
const delta = ch0?.delta;
|
|
2479
|
+
if (delta?.content) content += delta.content;
|
|
2480
|
+
if (delta?.tool_calls) {
|
|
2481
|
+
for (const tc of delta.tool_calls) {
|
|
2482
|
+
const idx = tc.index ?? 0;
|
|
2483
|
+
const existing = toolCalls.get(idx) ?? { id: "", type: "function", function: { name: "", arguments: "" } };
|
|
2484
|
+
if (tc.id) existing.id = tc.id;
|
|
2485
|
+
if (tc.function?.name) existing.function.name = tc.function.name;
|
|
2486
|
+
if (tc.function?.arguments) existing.function.arguments += tc.function.arguments;
|
|
2487
|
+
toolCalls.set(idx, existing);
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
if (ch0?.finish_reason) finishReason = ch0.finish_reason;
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
const message = { role: "assistant", content: content || null };
|
|
2494
|
+
if (toolCalls.size > 0) message.tool_calls = Array.from(toolCalls.values());
|
|
2495
|
+
return { choices: [{ message, finish_reason: finishReason }] };
|
|
2496
|
+
}
|
|
2327
2497
|
async function runLoop(opts) {
|
|
2328
2498
|
const fetchFn = opts.fetchImpl ?? fetch;
|
|
2329
2499
|
const trace = [];
|
|
@@ -2334,23 +2504,25 @@ async function runLoop(opts) {
|
|
|
2334
2504
|
];
|
|
2335
2505
|
const tools = asOpenAiTools(opts.tools);
|
|
2336
2506
|
for (let step = 1; step <= opts.maxSteps; step++) {
|
|
2507
|
+
const requestBody = {
|
|
2508
|
+
model: opts.config.model,
|
|
2509
|
+
messages,
|
|
2510
|
+
...tools.length > 0 ? { tools, tool_choice: "auto" } : {},
|
|
2511
|
+
...opts.streamAggregate ? { stream: true } : {}
|
|
2512
|
+
};
|
|
2337
2513
|
const res = await fetchFn(`${opts.config.apiBase}/chat/completions`, {
|
|
2338
2514
|
method: "POST",
|
|
2339
2515
|
headers: {
|
|
2340
2516
|
"authorization": `Bearer ${opts.config.apiKey}`,
|
|
2341
2517
|
"content-type": "application/json"
|
|
2342
2518
|
},
|
|
2343
|
-
body: JSON.stringify(
|
|
2344
|
-
model: opts.config.model,
|
|
2345
|
-
messages,
|
|
2346
|
-
...tools.length > 0 ? { tools, tool_choice: "auto" } : {}
|
|
2347
|
-
})
|
|
2519
|
+
body: JSON.stringify(requestBody)
|
|
2348
2520
|
});
|
|
2349
2521
|
if (!res.ok) {
|
|
2350
2522
|
const text = await res.text().catch(() => "");
|
|
2351
2523
|
throw new Error(`LiteLLM ${res.status}: ${text.slice(0, 500)}`);
|
|
2352
2524
|
}
|
|
2353
|
-
const data = await res.json();
|
|
2525
|
+
const data = opts.streamAggregate ? await aggregateChatStream(res) : await res.json();
|
|
2354
2526
|
const choice = data.choices?.[0];
|
|
2355
2527
|
if (!choice) throw new Error("LiteLLM response had no choices");
|
|
2356
2528
|
const assistant = choice.message;
|
|
@@ -2422,7 +2594,7 @@ async function runLoop(opts) {
|
|
|
2422
2594
|
}
|
|
2423
2595
|
var RPC_SESSION_TTL_MS = 60 * 60 * 1e3;
|
|
2424
2596
|
|
|
2425
|
-
// ../../packages/apes/dist/chunk-
|
|
2597
|
+
// ../../packages/apes/dist/chunk-PEA2RDWK.js
|
|
2426
2598
|
init_chunk_OBF7IMQ2();
|
|
2427
2599
|
import { createHash } from "crypto";
|
|
2428
2600
|
import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync4 } from "fs";
|
|
@@ -2460,6 +2632,149 @@ async function computeArgvHash(argv2) {
|
|
|
2460
2632
|
const digest2 = Array.from(hashArray).map((b2) => b2.toString(16).padStart(2, "0")).join("");
|
|
2461
2633
|
return `SHA-256:${digest2}`;
|
|
2462
2634
|
}
|
|
2635
|
+
function parseOptionArgs(tokens, valueOptions) {
|
|
2636
|
+
const options = {};
|
|
2637
|
+
const positionals = [];
|
|
2638
|
+
const takesValue = new Set(valueOptions ?? []);
|
|
2639
|
+
for (let index = 0; index < tokens.length; index += 1) {
|
|
2640
|
+
const token = tokens[index];
|
|
2641
|
+
if (token.startsWith("--")) {
|
|
2642
|
+
const stripped = token.slice(2);
|
|
2643
|
+
const eqIndex = stripped.indexOf("=");
|
|
2644
|
+
if (eqIndex >= 0) {
|
|
2645
|
+
options[stripped.slice(0, eqIndex)] = stripped.slice(eqIndex + 1);
|
|
2646
|
+
continue;
|
|
2647
|
+
}
|
|
2648
|
+
const next = tokens[index + 1];
|
|
2649
|
+
if (next && !next.startsWith("-")) {
|
|
2650
|
+
options[stripped] = next;
|
|
2651
|
+
index += 1;
|
|
2652
|
+
continue;
|
|
2653
|
+
}
|
|
2654
|
+
options[stripped] = "true";
|
|
2655
|
+
} else if (token.startsWith("-") && token.length > 1 && !/^-\d/.test(token)) {
|
|
2656
|
+
const key = token.slice(1);
|
|
2657
|
+
if (key.length === 1 && !takesValue.has(key)) {
|
|
2658
|
+
options[key] = "true";
|
|
2659
|
+
} else {
|
|
2660
|
+
const next = tokens[index + 1];
|
|
2661
|
+
if (next && !next.startsWith("-")) {
|
|
2662
|
+
options[key] = next;
|
|
2663
|
+
index += 1;
|
|
2664
|
+
} else {
|
|
2665
|
+
options[key] = "true";
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
} else {
|
|
2669
|
+
positionals.push(token);
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
return { options, positionals };
|
|
2673
|
+
}
|
|
2674
|
+
function resolveBindingToken(binding, bindings) {
|
|
2675
|
+
const match = binding.match(/^\{([^}|]+)(?:\|([^}]+))?\}$/);
|
|
2676
|
+
if (!match) return binding;
|
|
2677
|
+
const [, name, transform] = match;
|
|
2678
|
+
const value = bindings[name];
|
|
2679
|
+
if (!value) throw new Error(`Missing binding: ${name}`);
|
|
2680
|
+
if (!transform) return value;
|
|
2681
|
+
if (transform === "owner" || transform === "name") {
|
|
2682
|
+
const [owner, repo] = value.split("/");
|
|
2683
|
+
if (!owner || !repo) throw new Error(`Binding ${name} must be in owner/name form`);
|
|
2684
|
+
return transform === "owner" ? owner : repo;
|
|
2685
|
+
}
|
|
2686
|
+
throw new Error(`Unsupported binding transform: ${transform}`);
|
|
2687
|
+
}
|
|
2688
|
+
function renderTemplate(template, bindings) {
|
|
2689
|
+
return template.replace(/\{([^}]+)\}/g, (_3, expression) => resolveBindingToken(`{${expression}}`, bindings));
|
|
2690
|
+
}
|
|
2691
|
+
function parseResourceChain(chain, bindings) {
|
|
2692
|
+
return chain.map((entry) => {
|
|
2693
|
+
const [resource, selectorSpec = "*"] = entry.split(":", 2);
|
|
2694
|
+
if (!resource) throw new Error(`Invalid resource chain entry: ${entry}`);
|
|
2695
|
+
if (selectorSpec === "*") return { resource };
|
|
2696
|
+
const selector = Object.fromEntries(
|
|
2697
|
+
selectorSpec.split(",").map((segment) => {
|
|
2698
|
+
const [key, rawValue] = segment.split("=", 2);
|
|
2699
|
+
if (!key || !rawValue) throw new Error(`Invalid selector segment: ${segment}`);
|
|
2700
|
+
return [key, renderTemplate(rawValue, bindings)];
|
|
2701
|
+
})
|
|
2702
|
+
);
|
|
2703
|
+
return { resource, selector };
|
|
2704
|
+
});
|
|
2705
|
+
}
|
|
2706
|
+
function matchOperation(operation, argv2) {
|
|
2707
|
+
if (argv2.length < operation.command.length) return null;
|
|
2708
|
+
const prefix = argv2.slice(0, operation.command.length);
|
|
2709
|
+
if (prefix.join("\0") !== operation.command.join("\0")) return null;
|
|
2710
|
+
const remainder = argv2.slice(operation.command.length);
|
|
2711
|
+
const { options, positionals } = parseOptionArgs(remainder, operation.required_options);
|
|
2712
|
+
const expectedPositionals = operation.positionals ?? [];
|
|
2713
|
+
if (positionals.length !== expectedPositionals.length) return null;
|
|
2714
|
+
for (const option of operation.required_options ?? []) {
|
|
2715
|
+
if (!options[option]) return null;
|
|
2716
|
+
}
|
|
2717
|
+
const bindings = { ...options };
|
|
2718
|
+
for (let index = 0; index < expectedPositionals.length; index += 1) {
|
|
2719
|
+
const name = expectedPositionals[index];
|
|
2720
|
+
const value = positionals[index];
|
|
2721
|
+
if (name.startsWith("=")) {
|
|
2722
|
+
if (value !== name.slice(1)) return null;
|
|
2723
|
+
continue;
|
|
2724
|
+
}
|
|
2725
|
+
bindings[name] = value;
|
|
2726
|
+
}
|
|
2727
|
+
return bindings;
|
|
2728
|
+
}
|
|
2729
|
+
function expandCombinedFlags(argv2) {
|
|
2730
|
+
return argv2.flatMap((token) => {
|
|
2731
|
+
if (token.startsWith("-") && !token.startsWith("--") && token.length > 2 && /^-[a-z]+$/i.test(token)) {
|
|
2732
|
+
return Array.from(token.slice(1), (c3) => `-${c3}`);
|
|
2733
|
+
}
|
|
2734
|
+
return [token];
|
|
2735
|
+
});
|
|
2736
|
+
}
|
|
2737
|
+
function tryMatch(operations, argv2) {
|
|
2738
|
+
return operations.flatMap((operation) => {
|
|
2739
|
+
try {
|
|
2740
|
+
const bindings = matchOperation(operation, argv2);
|
|
2741
|
+
return bindings ? [{ operation, bindings }] : [];
|
|
2742
|
+
} catch {
|
|
2743
|
+
return [];
|
|
2744
|
+
}
|
|
2745
|
+
});
|
|
2746
|
+
}
|
|
2747
|
+
function matchArgvToOperation(operations, commandArgv) {
|
|
2748
|
+
let matches = tryMatch(operations, commandArgv);
|
|
2749
|
+
if (matches.length === 0) {
|
|
2750
|
+
const expanded = expandCombinedFlags(commandArgv);
|
|
2751
|
+
if (expanded.length !== commandArgv.length) {
|
|
2752
|
+
matches = tryMatch(operations, expanded);
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
if (matches.length === 0) return null;
|
|
2756
|
+
if (matches.length > 1) {
|
|
2757
|
+
matches.sort((a2, b2) => b2.operation.command.length - a2.operation.command.length);
|
|
2758
|
+
matches = [matches[0]];
|
|
2759
|
+
}
|
|
2760
|
+
return matches[0];
|
|
2761
|
+
}
|
|
2762
|
+
function buildCliAuthDetail(cliId, operation, bindings) {
|
|
2763
|
+
const resource_chain = parseResourceChain(operation.resource_chain, bindings);
|
|
2764
|
+
const detail = {
|
|
2765
|
+
type: "openape_cli",
|
|
2766
|
+
cli_id: cliId,
|
|
2767
|
+
operation_id: operation.id,
|
|
2768
|
+
resource_chain,
|
|
2769
|
+
action: operation.action,
|
|
2770
|
+
permission: "",
|
|
2771
|
+
display: renderTemplate(operation.display, bindings),
|
|
2772
|
+
risk: operation.risk,
|
|
2773
|
+
...operation.exact_command ? { constraints: { exact_command: true } } : {}
|
|
2774
|
+
};
|
|
2775
|
+
detail.permission = canonicalizeCliPermission(detail);
|
|
2776
|
+
return detail;
|
|
2777
|
+
}
|
|
2463
2778
|
|
|
2464
2779
|
// ../../node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/core.mjs
|
|
2465
2780
|
var LogLevels = {
|
|
@@ -3562,7 +3877,7 @@ function _getDefaultLogLevel() {
|
|
|
3562
3877
|
}
|
|
3563
3878
|
var consola = createConsola2();
|
|
3564
3879
|
|
|
3565
|
-
// ../../packages/apes/dist/chunk-
|
|
3880
|
+
// ../../packages/apes/dist/chunk-PEA2RDWK.js
|
|
3566
3881
|
var import_shell_quote = __toESM(require_shell_quote(), 1);
|
|
3567
3882
|
|
|
3568
3883
|
// ../../node_modules/.pnpm/citty@0.2.2/node_modules/citty/dist/index.mjs
|
|
@@ -3571,7 +3886,7 @@ function defineCommand(def) {
|
|
|
3571
3886
|
return def;
|
|
3572
3887
|
}
|
|
3573
3888
|
|
|
3574
|
-
// ../../packages/apes/dist/chunk-
|
|
3889
|
+
// ../../packages/apes/dist/chunk-PEA2RDWK.js
|
|
3575
3890
|
import { homedir as homedir52 } from "os";
|
|
3576
3891
|
import { join as join5 } from "path";
|
|
3577
3892
|
function parseKeyValue(line) {
|
|
@@ -3744,131 +4059,6 @@ function loadAdapter(cliId, explicitPath) {
|
|
|
3744
4059
|
}
|
|
3745
4060
|
var REGISTRY_URL = process.env.SHAPES_REGISTRY_URL ?? "https://raw.githubusercontent.com/openape-ai/shapes-registry/main/registry.json";
|
|
3746
4061
|
var CACHE_TTL_MS = 60 * 60 * 1e3;
|
|
3747
|
-
function parseOptionArgs(tokens, valueOptions) {
|
|
3748
|
-
const options = {};
|
|
3749
|
-
const positionals = [];
|
|
3750
|
-
const takesValue = new Set(valueOptions ?? []);
|
|
3751
|
-
for (let index = 0; index < tokens.length; index += 1) {
|
|
3752
|
-
const token = tokens[index];
|
|
3753
|
-
if (token.startsWith("--")) {
|
|
3754
|
-
const stripped = token.slice(2);
|
|
3755
|
-
const eqIndex = stripped.indexOf("=");
|
|
3756
|
-
if (eqIndex >= 0) {
|
|
3757
|
-
options[stripped.slice(0, eqIndex)] = stripped.slice(eqIndex + 1);
|
|
3758
|
-
continue;
|
|
3759
|
-
}
|
|
3760
|
-
const next = tokens[index + 1];
|
|
3761
|
-
if (next && !next.startsWith("-")) {
|
|
3762
|
-
options[stripped] = next;
|
|
3763
|
-
index += 1;
|
|
3764
|
-
continue;
|
|
3765
|
-
}
|
|
3766
|
-
options[stripped] = "true";
|
|
3767
|
-
} else if (token.startsWith("-") && token.length > 1 && !/^-\d/.test(token)) {
|
|
3768
|
-
const key = token.slice(1);
|
|
3769
|
-
if (key.length === 1 && !takesValue.has(key)) {
|
|
3770
|
-
options[key] = "true";
|
|
3771
|
-
} else {
|
|
3772
|
-
const next = tokens[index + 1];
|
|
3773
|
-
if (next && !next.startsWith("-")) {
|
|
3774
|
-
options[key] = next;
|
|
3775
|
-
index += 1;
|
|
3776
|
-
} else {
|
|
3777
|
-
options[key] = "true";
|
|
3778
|
-
}
|
|
3779
|
-
}
|
|
3780
|
-
} else {
|
|
3781
|
-
positionals.push(token);
|
|
3782
|
-
}
|
|
3783
|
-
}
|
|
3784
|
-
return { options, positionals };
|
|
3785
|
-
}
|
|
3786
|
-
function resolveBindingToken(binding, bindings) {
|
|
3787
|
-
const match = binding.match(/^\{([^}|]+)(?:\|([^}]+))?\}$/);
|
|
3788
|
-
if (!match)
|
|
3789
|
-
return binding;
|
|
3790
|
-
const [, name, transform] = match;
|
|
3791
|
-
const value = bindings[name];
|
|
3792
|
-
if (!value)
|
|
3793
|
-
throw new Error(`Missing binding: ${name}`);
|
|
3794
|
-
if (!transform)
|
|
3795
|
-
return value;
|
|
3796
|
-
if (transform === "owner" || transform === "name") {
|
|
3797
|
-
const [owner, repo] = value.split("/");
|
|
3798
|
-
if (!owner || !repo)
|
|
3799
|
-
throw new Error(`Binding ${name} must be in owner/name form`);
|
|
3800
|
-
return transform === "owner" ? owner : repo;
|
|
3801
|
-
}
|
|
3802
|
-
throw new Error(`Unsupported binding transform: ${transform}`);
|
|
3803
|
-
}
|
|
3804
|
-
function renderTemplate(template, bindings) {
|
|
3805
|
-
return template.replace(/\{([^}]+)\}/g, (_3, expression) => resolveBindingToken(`{${expression}}`, bindings));
|
|
3806
|
-
}
|
|
3807
|
-
function parseResourceChain(chain, bindings) {
|
|
3808
|
-
return chain.map((entry) => {
|
|
3809
|
-
const [resource, selectorSpec = "*"] = entry.split(":", 2);
|
|
3810
|
-
if (!resource)
|
|
3811
|
-
throw new Error(`Invalid resource chain entry: ${entry}`);
|
|
3812
|
-
if (selectorSpec === "*") {
|
|
3813
|
-
return { resource };
|
|
3814
|
-
}
|
|
3815
|
-
const selector = Object.fromEntries(
|
|
3816
|
-
selectorSpec.split(",").map((segment) => {
|
|
3817
|
-
const [key, rawValue] = segment.split("=", 2);
|
|
3818
|
-
if (!key || !rawValue)
|
|
3819
|
-
throw new Error(`Invalid selector segment: ${segment}`);
|
|
3820
|
-
return [key, renderTemplate(rawValue, bindings)];
|
|
3821
|
-
})
|
|
3822
|
-
);
|
|
3823
|
-
return { resource, selector };
|
|
3824
|
-
});
|
|
3825
|
-
}
|
|
3826
|
-
function matchOperation(operation, argv2) {
|
|
3827
|
-
if (argv2.length < operation.command.length)
|
|
3828
|
-
return null;
|
|
3829
|
-
const prefix = argv2.slice(0, operation.command.length);
|
|
3830
|
-
if (prefix.join("\0") !== operation.command.join("\0"))
|
|
3831
|
-
return null;
|
|
3832
|
-
const remainder = argv2.slice(operation.command.length);
|
|
3833
|
-
const { options, positionals } = parseOptionArgs(remainder, operation.required_options);
|
|
3834
|
-
const expectedPositionals = operation.positionals ?? [];
|
|
3835
|
-
if (positionals.length !== expectedPositionals.length)
|
|
3836
|
-
return null;
|
|
3837
|
-
for (const option of operation.required_options ?? []) {
|
|
3838
|
-
if (!options[option])
|
|
3839
|
-
return null;
|
|
3840
|
-
}
|
|
3841
|
-
const bindings = { ...options };
|
|
3842
|
-
for (let index = 0; index < expectedPositionals.length; index += 1) {
|
|
3843
|
-
const name = expectedPositionals[index];
|
|
3844
|
-
const value = positionals[index];
|
|
3845
|
-
if (name.startsWith("=")) {
|
|
3846
|
-
if (value !== name.slice(1))
|
|
3847
|
-
return null;
|
|
3848
|
-
continue;
|
|
3849
|
-
}
|
|
3850
|
-
bindings[name] = value;
|
|
3851
|
-
}
|
|
3852
|
-
return bindings;
|
|
3853
|
-
}
|
|
3854
|
-
function expandCombinedFlags(argv2) {
|
|
3855
|
-
return argv2.flatMap((token) => {
|
|
3856
|
-
if (token.startsWith("-") && !token.startsWith("--") && token.length > 2 && /^-[a-z]+$/i.test(token)) {
|
|
3857
|
-
return Array.from(token.slice(1), (c3) => `-${c3}`);
|
|
3858
|
-
}
|
|
3859
|
-
return [token];
|
|
3860
|
-
});
|
|
3861
|
-
}
|
|
3862
|
-
function tryMatch(operations, argv2) {
|
|
3863
|
-
return operations.flatMap((operation) => {
|
|
3864
|
-
try {
|
|
3865
|
-
const bindings = matchOperation(operation, argv2);
|
|
3866
|
-
return bindings ? [{ operation, bindings }] : [];
|
|
3867
|
-
} catch {
|
|
3868
|
-
return [];
|
|
3869
|
-
}
|
|
3870
|
-
});
|
|
3871
|
-
}
|
|
3872
4062
|
async function resolveCommand(loaded, fullArgv) {
|
|
3873
4063
|
const [executable, ...commandArgv] = fullArgv;
|
|
3874
4064
|
if (!executable) {
|
|
@@ -3877,34 +4067,12 @@ async function resolveCommand(loaded, fullArgv) {
|
|
|
3877
4067
|
if (executable !== loaded.adapter.cli.executable) {
|
|
3878
4068
|
throw new Error(`Adapter ${loaded.adapter.cli.id} expects executable ${loaded.adapter.cli.executable}, got ${executable}`);
|
|
3879
4069
|
}
|
|
3880
|
-
|
|
3881
|
-
if (
|
|
3882
|
-
const expanded = expandCombinedFlags(commandArgv);
|
|
3883
|
-
if (expanded.length !== commandArgv.length) {
|
|
3884
|
-
matches = tryMatch(loaded.adapter.operations, expanded);
|
|
3885
|
-
}
|
|
3886
|
-
}
|
|
3887
|
-
if (matches.length === 0) {
|
|
4070
|
+
const match = matchArgvToOperation(loaded.adapter.operations, commandArgv);
|
|
4071
|
+
if (!match) {
|
|
3888
4072
|
throw new Error(`No adapter operation matched: ${fullArgv.join(" ")}`);
|
|
3889
4073
|
}
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
matches = [matches[0]];
|
|
3893
|
-
}
|
|
3894
|
-
const { operation, bindings } = matches[0];
|
|
3895
|
-
const resource_chain = parseResourceChain(operation.resource_chain, bindings);
|
|
3896
|
-
const detail = {
|
|
3897
|
-
type: "openape_cli",
|
|
3898
|
-
cli_id: loaded.adapter.cli.id,
|
|
3899
|
-
operation_id: operation.id,
|
|
3900
|
-
resource_chain,
|
|
3901
|
-
action: operation.action,
|
|
3902
|
-
permission: "",
|
|
3903
|
-
display: renderTemplate(operation.display, bindings),
|
|
3904
|
-
risk: operation.risk,
|
|
3905
|
-
...operation.exact_command ? { constraints: { exact_command: true } } : {}
|
|
3906
|
-
};
|
|
3907
|
-
detail.permission = canonicalizeCliPermission(detail);
|
|
4074
|
+
const { operation, bindings } = match;
|
|
4075
|
+
const detail = buildCliAuthDetail(loaded.adapter.cli.id, operation, bindings);
|
|
3908
4076
|
return {
|
|
3909
4077
|
adapter: loaded.adapter,
|
|
3910
4078
|
source: loaded.source,
|
|
@@ -3975,7 +4143,7 @@ function extractOption(args, name) {
|
|
|
3975
4143
|
}
|
|
3976
4144
|
var AUTH_FILE2 = join5(homedir52(), ".config", "apes", "auth.json");
|
|
3977
4145
|
|
|
3978
|
-
// ../../packages/apes/dist/chunk-
|
|
4146
|
+
// ../../packages/apes/dist/chunk-NYJSBFLG.js
|
|
3979
4147
|
init_chunk_OBF7IMQ2();
|
|
3980
4148
|
var debug = process.argv.includes("--debug");
|
|
3981
4149
|
|
|
@@ -4294,7 +4462,7 @@ function readAgentIdentity() {
|
|
|
4294
4462
|
const ownerEmail = parsed.owner_email ?? process.env.OPENAPE_OWNER_EMAIL;
|
|
4295
4463
|
if (!ownerEmail) {
|
|
4296
4464
|
throw new Error(
|
|
4297
|
-
`auth.json at ${path} missing 'owner_email' and no OPENAPE_OWNER_EMAIL env var set \u2014 re-spawn the agent with @openape/apes >= 0.28 or
|
|
4465
|
+
`auth.json at ${path} missing 'owner_email' and no OPENAPE_OWNER_EMAIL env var set \u2014 re-spawn the agent with @openape/apes >= 0.28 or set OPENAPE_OWNER_EMAIL in the container env`
|
|
4298
4466
|
);
|
|
4299
4467
|
}
|
|
4300
4468
|
return { email: parsed.email, ownerEmail, idp: parsed.idp };
|
|
@@ -4794,6 +4962,8 @@ function readConfig() {
|
|
|
4794
4962
|
"APE_CHAT_BRIDGE_MODEL is not set. Set it in the bridge .env (usually `~/Library/Application Support/openape/bridge/.env` on macOS) or globally in `~/litellm/.env` so resolveBridgeConfig picks it up at spawn time. Common values: `gpt-5.4` (ChatGPT-only LiteLLM proxy), `claude-haiku-4-5` (Anthropic-only)."
|
|
4795
4963
|
);
|
|
4796
4964
|
}
|
|
4965
|
+
const targetRaw = (process3.env.OPENAPE_BRIDGE_TARGET ?? "chat").toLowerCase();
|
|
4966
|
+
const target = targetRaw === "troop" ? "troop" : "chat";
|
|
4797
4967
|
return {
|
|
4798
4968
|
endpoint: (process3.env.APE_CHAT_ENDPOINT ?? DEFAULT_ENDPOINT).replace(/\/$/, ""),
|
|
4799
4969
|
apesBin: process3.env.APE_CHAT_BRIDGE_APES_BIN ?? DEFAULT_APES_BIN,
|
|
@@ -4801,7 +4971,8 @@ function readConfig() {
|
|
|
4801
4971
|
systemPrompt: process3.env.APE_CHAT_BRIDGE_SYSTEM_PROMPT ?? DEFAULT_SYSTEM_PROMPT,
|
|
4802
4972
|
tools,
|
|
4803
4973
|
maxSteps: Number.isFinite(maxSteps) && maxSteps > 0 ? maxSteps : DEFAULT_MAX_STEPS,
|
|
4804
|
-
roomFilter: process3.env.APE_CHAT_BRIDGE_ROOM
|
|
4974
|
+
roomFilter: process3.env.APE_CHAT_BRIDGE_ROOM,
|
|
4975
|
+
target
|
|
4805
4976
|
};
|
|
4806
4977
|
}
|
|
4807
4978
|
async function getIdentity() {
|
|
@@ -4837,7 +5008,7 @@ var Bridge = class {
|
|
|
4837
5008
|
const idp = await ensureFreshIdpAuth();
|
|
4838
5009
|
return `Bearer ${idp.access_token}`;
|
|
4839
5010
|
};
|
|
4840
|
-
this.chat = new ChatApi(this.cfg.endpoint, this.bearer);
|
|
5011
|
+
this.chat = this.cfg.target === "troop" ? new TroopChatApi(this.cfg.endpoint, this.bearer) : new ChatApi(this.cfg.endpoint, this.bearer);
|
|
4841
5012
|
this.cron = new CronRunner({
|
|
4842
5013
|
runtimeConfig: this.runtimeConfig(),
|
|
4843
5014
|
chat: this.chat,
|
|
@@ -4855,6 +5026,11 @@ var Bridge = class {
|
|
|
4855
5026
|
// its own message history and calls @openape/apes' runLoop directly
|
|
4856
5027
|
// (no stdio JSON-RPC subprocess — see thread-session.ts).
|
|
4857
5028
|
threads = /* @__PURE__ */ new Map();
|
|
5029
|
+
// ChatApi and TroopChatApi expose the same surface (postMessage /
|
|
5030
|
+
// listMessages / patchMessage / listContacts / requestContact /
|
|
5031
|
+
// acceptContact / createThread) so the rest of the bridge calls
|
|
5032
|
+
// through a structurally-typed reference without caring which
|
|
5033
|
+
// backend is in play. Picked at construction time from cfg.target.
|
|
4858
5034
|
chat;
|
|
4859
5035
|
bearer;
|
|
4860
5036
|
cron;
|
|
@@ -4912,6 +5088,29 @@ var Bridge = class {
|
|
|
4912
5088
|
if (accepted.length > 0) log(`accepted: ${accepted.join(", ")}`);
|
|
4913
5089
|
if (skipped.length > 0) log(`skipped (not on allowlist): ${skipped.join(", ")}`);
|
|
4914
5090
|
}
|
|
5091
|
+
/**
|
|
5092
|
+
* Translate troop's chat-frame payload shape into the
|
|
5093
|
+
* chat.openape.ai-style Message the rest of this bridge expects.
|
|
5094
|
+
* Troop's payload uses `role` (human|agent) + `chatId` + no
|
|
5095
|
+
* senderEmail; the bridge's handleInbound checks
|
|
5096
|
+
* `senderEmail === selfEmail` to skip its own echoes, so we
|
|
5097
|
+
* synthesize the email from role (agent → self, human → owner).
|
|
5098
|
+
* threadId is the synthetic 'main' because troop has no threads.
|
|
5099
|
+
*/
|
|
5100
|
+
translateTroopPayload(chatId, payload) {
|
|
5101
|
+
const role = payload.role === "agent" ? "agent" : "human";
|
|
5102
|
+
return {
|
|
5103
|
+
id: String(payload.id ?? ""),
|
|
5104
|
+
roomId: chatId || String(payload.chatId ?? ""),
|
|
5105
|
+
threadId: "main",
|
|
5106
|
+
senderEmail: role === "agent" ? this.selfEmail : this.ownerEmail,
|
|
5107
|
+
senderAct: role,
|
|
5108
|
+
body: typeof payload.body === "string" ? payload.body : "",
|
|
5109
|
+
replyTo: typeof payload.replyTo === "string" ? payload.replyTo : null,
|
|
5110
|
+
createdAt: typeof payload.createdAt === "number" ? payload.createdAt : Math.floor(Date.now() / 1e3),
|
|
5111
|
+
editedAt: typeof payload.editedAt === "number" ? payload.editedAt : null
|
|
5112
|
+
};
|
|
5113
|
+
}
|
|
4915
5114
|
async handleInbound(msg) {
|
|
4916
5115
|
if (msg.senderEmail === this.selfEmail) return;
|
|
4917
5116
|
if (!msg.body.trim()) return;
|
|
@@ -4977,7 +5176,8 @@ var Bridge = class {
|
|
|
4977
5176
|
}
|
|
4978
5177
|
async pumpOnce() {
|
|
4979
5178
|
const bearer = await this.bearer();
|
|
4980
|
-
const
|
|
5179
|
+
const wsPath = this.cfg.target === "troop" ? "/_ws/chat" : "/api/ws";
|
|
5180
|
+
const wsUrl = `${this.cfg.endpoint.replace(/^http/, "ws")}${wsPath}?token=${encodeURIComponent(bearer.replace(/^Bearer\s+/i, ""))}`;
|
|
4981
5181
|
const ws = new WebSocket(wsUrl);
|
|
4982
5182
|
return new Promise((resolve4, reject) => {
|
|
4983
5183
|
let pingTimer;
|
|
@@ -5006,8 +5206,9 @@ var Bridge = class {
|
|
|
5006
5206
|
} catch {
|
|
5007
5207
|
return;
|
|
5008
5208
|
}
|
|
5009
|
-
if (frame.type !== "message") return;
|
|
5010
|
-
|
|
5209
|
+
if (frame.type !== "message" || !frame.payload) return;
|
|
5210
|
+
const msg = this.cfg.target === "troop" ? this.translateTroopPayload(frame.chat_id ?? "", frame.payload) : frame.payload;
|
|
5211
|
+
void this.handleInbound(msg);
|
|
5011
5212
|
});
|
|
5012
5213
|
ws.on("close", () => {
|
|
5013
5214
|
if (pingTimer) clearInterval(pingTimer);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openape/ape-agent",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.14",
|
|
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",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"ofetch": "^1.4.1",
|
|
24
24
|
"ws": "^8.18.0",
|
|
25
25
|
"yaml": "^2.8.0",
|
|
26
|
-
"@openape/apes": "1.28.
|
|
26
|
+
"@openape/apes": "1.28.13",
|
|
27
27
|
"@openape/prompt-injection-detector": "0.1.0",
|
|
28
|
-
"@openape/cli-auth": "0.
|
|
28
|
+
"@openape/cli-auth": "0.5.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@antfu/eslint-config": "^7.6.1",
|