@ccpocket/bridge 1.51.0 → 1.53.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/codex-process.d.ts +7 -0
- package/dist/codex-process.js +44 -3
- package/dist/codex-process.js.map +1 -1
- package/dist/parser.d.ts +8 -0
- package/dist/parser.js +5 -0
- package/dist/parser.js.map +1 -1
- package/dist/session.d.ts +8 -8
- package/dist/session.js +31 -38
- package/dist/session.js.map +1 -1
- package/dist/sessions-index.d.ts +3 -0
- package/dist/sessions-index.js +253 -5
- package/dist/sessions-index.js.map +1 -1
- package/dist/websocket.d.ts +6 -0
- package/dist/websocket.js +463 -28
- package/dist/websocket.js.map +1 -1
- package/package.json +1 -1
package/dist/sessions-index.js
CHANGED
|
@@ -1345,6 +1345,219 @@ async function getAllRecentCodexSessions(options = {}) {
|
|
|
1345
1345
|
}
|
|
1346
1346
|
return entries;
|
|
1347
1347
|
}
|
|
1348
|
+
export function codexUserTurnUuid(ordinal) {
|
|
1349
|
+
return `codex:user-turn:${ordinal}`;
|
|
1350
|
+
}
|
|
1351
|
+
function numberToIsoTimestamp(value) {
|
|
1352
|
+
return typeof value === "number" && Number.isFinite(value)
|
|
1353
|
+
? new Date(value * 1000).toISOString()
|
|
1354
|
+
: undefined;
|
|
1355
|
+
}
|
|
1356
|
+
function stringValue(value) {
|
|
1357
|
+
return typeof value === "string" ? value : undefined;
|
|
1358
|
+
}
|
|
1359
|
+
function arrayValue(value) {
|
|
1360
|
+
return Array.isArray(value) ? value : [];
|
|
1361
|
+
}
|
|
1362
|
+
function codexToolResultContent(value) {
|
|
1363
|
+
if (value == null)
|
|
1364
|
+
return "";
|
|
1365
|
+
if (typeof value === "string")
|
|
1366
|
+
return value;
|
|
1367
|
+
try {
|
|
1368
|
+
return JSON.stringify(value, null, 2);
|
|
1369
|
+
}
|
|
1370
|
+
catch {
|
|
1371
|
+
return String(value);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
function codexUserInputTextAndImages(content) {
|
|
1375
|
+
const textParts = [];
|
|
1376
|
+
let imageCount = 0;
|
|
1377
|
+
for (const entry of arrayValue(content)) {
|
|
1378
|
+
const item = asObject(entry);
|
|
1379
|
+
if (!item)
|
|
1380
|
+
continue;
|
|
1381
|
+
if (item.type === "text" && typeof item.text === "string") {
|
|
1382
|
+
textParts.push(item.text);
|
|
1383
|
+
}
|
|
1384
|
+
else if (item.type === "image" || item.type === "localImage") {
|
|
1385
|
+
imageCount += 1;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
return { text: textParts.join("\n"), imageCount };
|
|
1389
|
+
}
|
|
1390
|
+
function appendCodexThinkingMessage(messages, text, timestamp) {
|
|
1391
|
+
const normalized = text.trim();
|
|
1392
|
+
if (!normalized)
|
|
1393
|
+
return;
|
|
1394
|
+
messages.push({
|
|
1395
|
+
role: "assistant",
|
|
1396
|
+
content: [{ type: "thinking", thinking: normalized }],
|
|
1397
|
+
...(timestamp ? { timestamp } : {}),
|
|
1398
|
+
});
|
|
1399
|
+
}
|
|
1400
|
+
function appendCodexOfficialToolResult(messages, id, name, content, timestamp) {
|
|
1401
|
+
appendToolResultMessage(messages, id, name, content, {
|
|
1402
|
+
...(timestamp ? { timestamp } : {}),
|
|
1403
|
+
});
|
|
1404
|
+
}
|
|
1405
|
+
export function codexThreadToSessionHistory(thread) {
|
|
1406
|
+
const messages = [];
|
|
1407
|
+
const turns = arrayValue(asObject(thread)?.turns);
|
|
1408
|
+
let userTurnOrdinal = 0;
|
|
1409
|
+
for (const rawTurn of turns) {
|
|
1410
|
+
const turn = asObject(rawTurn);
|
|
1411
|
+
if (!turn)
|
|
1412
|
+
continue;
|
|
1413
|
+
const turnStartedAt = numberToIsoTimestamp(turn.startedAt);
|
|
1414
|
+
const turnCompletedAt = numberToIsoTimestamp(turn.completedAt);
|
|
1415
|
+
for (const rawItem of arrayValue(turn.items)) {
|
|
1416
|
+
const item = asObject(rawItem);
|
|
1417
|
+
if (!item || typeof item.type !== "string")
|
|
1418
|
+
continue;
|
|
1419
|
+
const itemId = stringValue(item.id) ?? `codex-item-${messages.length}`;
|
|
1420
|
+
const itemTimestamp = turnCompletedAt ?? turnStartedAt;
|
|
1421
|
+
switch (item.type) {
|
|
1422
|
+
case "userMessage": {
|
|
1423
|
+
const { text, imageCount } = codexUserInputTextAndImages(item.content);
|
|
1424
|
+
const displayText = text.trim().length > 0
|
|
1425
|
+
? text
|
|
1426
|
+
: imageCount > 0
|
|
1427
|
+
? `[Image attached${imageCount > 1 ? ` x${imageCount}` : ""}]`
|
|
1428
|
+
: "";
|
|
1429
|
+
if (displayText.trim().length === 0)
|
|
1430
|
+
break;
|
|
1431
|
+
userTurnOrdinal += 1;
|
|
1432
|
+
messages.push({
|
|
1433
|
+
role: "user",
|
|
1434
|
+
uuid: codexUserTurnUuid(userTurnOrdinal),
|
|
1435
|
+
content: [{ type: "text", text: displayText }],
|
|
1436
|
+
...(imageCount > 0 ? { imageCount } : {}),
|
|
1437
|
+
...(turnStartedAt ? { timestamp: turnStartedAt } : {}),
|
|
1438
|
+
});
|
|
1439
|
+
break;
|
|
1440
|
+
}
|
|
1441
|
+
case "agentMessage": {
|
|
1442
|
+
appendTextMessage(messages, "assistant", stringValue(item.text) ?? "", itemTimestamp);
|
|
1443
|
+
break;
|
|
1444
|
+
}
|
|
1445
|
+
case "plan": {
|
|
1446
|
+
appendTextMessage(messages, "assistant", stringValue(item.text) ?? "", itemTimestamp);
|
|
1447
|
+
break;
|
|
1448
|
+
}
|
|
1449
|
+
case "reasoning": {
|
|
1450
|
+
const summary = arrayValue(item.summary)
|
|
1451
|
+
.filter((value) => typeof value === "string");
|
|
1452
|
+
const content = arrayValue(item.content)
|
|
1453
|
+
.filter((value) => typeof value === "string");
|
|
1454
|
+
appendCodexThinkingMessage(messages, [...summary, ...content].join("\n"), itemTimestamp);
|
|
1455
|
+
break;
|
|
1456
|
+
}
|
|
1457
|
+
case "commandExecution": {
|
|
1458
|
+
const command = stringValue(item.command) ?? "";
|
|
1459
|
+
appendToolUseMessage(messages, itemId, "Bash", {
|
|
1460
|
+
command,
|
|
1461
|
+
...(typeof item.cwd === "string" ? { cwd: item.cwd } : {}),
|
|
1462
|
+
});
|
|
1463
|
+
const outputParts = [];
|
|
1464
|
+
if (typeof item.status === "string") {
|
|
1465
|
+
outputParts.push(`status: ${item.status}`);
|
|
1466
|
+
}
|
|
1467
|
+
if (typeof item.exitCode === "number") {
|
|
1468
|
+
outputParts.push(`exitCode: ${item.exitCode}`);
|
|
1469
|
+
}
|
|
1470
|
+
if (typeof item.aggregatedOutput === "string") {
|
|
1471
|
+
outputParts.push(item.aggregatedOutput);
|
|
1472
|
+
}
|
|
1473
|
+
appendCodexOfficialToolResult(messages, itemId, "Bash", outputParts.join("\n").trim(), itemTimestamp);
|
|
1474
|
+
break;
|
|
1475
|
+
}
|
|
1476
|
+
case "fileChange": {
|
|
1477
|
+
appendToolUseMessage(messages, itemId, "FileChange", {
|
|
1478
|
+
changes: Array.isArray(item.changes) ? item.changes : [],
|
|
1479
|
+
...(typeof item.status === "string" ? { status: item.status } : {}),
|
|
1480
|
+
});
|
|
1481
|
+
break;
|
|
1482
|
+
}
|
|
1483
|
+
case "mcpToolCall": {
|
|
1484
|
+
const server = stringValue(item.server) ?? "mcp";
|
|
1485
|
+
const tool = stringValue(item.tool) ?? "tool";
|
|
1486
|
+
appendToolUseMessage(messages, itemId, `mcp:${server}/${tool}`, {
|
|
1487
|
+
arguments: item.arguments ?? {},
|
|
1488
|
+
...(typeof item.status === "string" ? { status: item.status } : {}),
|
|
1489
|
+
});
|
|
1490
|
+
if (item.result != null || item.error != null) {
|
|
1491
|
+
const normalized = normalizeCodexMcpResult(item.result ?? item.error);
|
|
1492
|
+
appendToolResultMessage(messages, itemId, `mcp:${server}/${tool}`, normalized.content, {
|
|
1493
|
+
imageBase64: normalized.imageBase64,
|
|
1494
|
+
...(itemTimestamp ? { timestamp: itemTimestamp } : {}),
|
|
1495
|
+
});
|
|
1496
|
+
}
|
|
1497
|
+
break;
|
|
1498
|
+
}
|
|
1499
|
+
case "dynamicToolCall": {
|
|
1500
|
+
const tool = stringValue(item.tool) ?? "tool";
|
|
1501
|
+
appendToolUseMessage(messages, itemId, tool, {
|
|
1502
|
+
arguments: item.arguments ?? {},
|
|
1503
|
+
...(typeof item.status === "string" ? { status: item.status } : {}),
|
|
1504
|
+
});
|
|
1505
|
+
const contentItems = arrayValue(item.contentItems);
|
|
1506
|
+
const resultText = contentItems
|
|
1507
|
+
.map((entry) => {
|
|
1508
|
+
const contentItem = asObject(entry);
|
|
1509
|
+
if (!contentItem)
|
|
1510
|
+
return "";
|
|
1511
|
+
if (contentItem.type === "inputText" &&
|
|
1512
|
+
typeof contentItem.text === "string") {
|
|
1513
|
+
return contentItem.text;
|
|
1514
|
+
}
|
|
1515
|
+
if (contentItem.type === "inputImage" &&
|
|
1516
|
+
typeof contentItem.imageUrl === "string") {
|
|
1517
|
+
return contentItem.imageUrl;
|
|
1518
|
+
}
|
|
1519
|
+
return codexToolResultContent(contentItem);
|
|
1520
|
+
})
|
|
1521
|
+
.filter(Boolean)
|
|
1522
|
+
.join("\n");
|
|
1523
|
+
appendCodexOfficialToolResult(messages, itemId, tool, resultText, itemTimestamp);
|
|
1524
|
+
break;
|
|
1525
|
+
}
|
|
1526
|
+
case "webSearch": {
|
|
1527
|
+
appendToolUseMessage(messages, itemId, "WebSearch", {
|
|
1528
|
+
query: stringValue(item.query) ?? "",
|
|
1529
|
+
...(item.action != null ? { action: item.action } : {}),
|
|
1530
|
+
});
|
|
1531
|
+
break;
|
|
1532
|
+
}
|
|
1533
|
+
case "imageGeneration": {
|
|
1534
|
+
appendToolUseMessage(messages, itemId, "ImageGeneration", {
|
|
1535
|
+
...(typeof item.status === "string" ? { status: item.status } : {}),
|
|
1536
|
+
...(typeof item.revisedPrompt === "string"
|
|
1537
|
+
? { revisedPrompt: item.revisedPrompt }
|
|
1538
|
+
: {}),
|
|
1539
|
+
});
|
|
1540
|
+
appendImageGenerationResult(messages, {
|
|
1541
|
+
id: itemId,
|
|
1542
|
+
status: item.status,
|
|
1543
|
+
revisedPrompt: item.revisedPrompt,
|
|
1544
|
+
savedPath: item.savedPath,
|
|
1545
|
+
result: item.result,
|
|
1546
|
+
}, itemId, itemTimestamp);
|
|
1547
|
+
break;
|
|
1548
|
+
}
|
|
1549
|
+
case "enteredReviewMode":
|
|
1550
|
+
case "exitedReviewMode": {
|
|
1551
|
+
appendTextMessage(messages, "assistant", stringValue(item.review) ?? "", itemTimestamp);
|
|
1552
|
+
break;
|
|
1553
|
+
}
|
|
1554
|
+
default:
|
|
1555
|
+
break;
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
return messages;
|
|
1560
|
+
}
|
|
1348
1561
|
function asObject(value) {
|
|
1349
1562
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1350
1563
|
return null;
|
|
@@ -1363,10 +1576,10 @@ function parseObjectLike(value) {
|
|
|
1363
1576
|
}
|
|
1364
1577
|
return asObject(value) ?? {};
|
|
1365
1578
|
}
|
|
1366
|
-
function appendTextMessage(messages, role, text, timestamp) {
|
|
1579
|
+
function appendTextMessage(messages, role, text, timestamp, uuid) {
|
|
1367
1580
|
const normalized = text.trim();
|
|
1368
1581
|
if (!normalized)
|
|
1369
|
-
return;
|
|
1582
|
+
return false;
|
|
1370
1583
|
const last = messages.at(-1);
|
|
1371
1584
|
if (last
|
|
1372
1585
|
&& last.role === role
|
|
@@ -1375,13 +1588,35 @@ function appendTextMessage(messages, role, text, timestamp) {
|
|
|
1375
1588
|
&& last.content[0].type === "text"
|
|
1376
1589
|
&& typeof last.content[0].text === "string"
|
|
1377
1590
|
&& last.content[0].text.trim() === normalized) {
|
|
1378
|
-
return;
|
|
1591
|
+
return false;
|
|
1379
1592
|
}
|
|
1380
1593
|
messages.push({
|
|
1381
1594
|
role,
|
|
1595
|
+
...(uuid ? { uuid } : {}),
|
|
1382
1596
|
content: [{ type: "text", text }],
|
|
1383
1597
|
...(timestamp ? { timestamp } : {}),
|
|
1384
1598
|
});
|
|
1599
|
+
return true;
|
|
1600
|
+
}
|
|
1601
|
+
function countCodexUserTurns(messages) {
|
|
1602
|
+
return messages.filter((message) => message.role === "user" && !message.isMeta)
|
|
1603
|
+
.length;
|
|
1604
|
+
}
|
|
1605
|
+
function applyCodexThreadRollback(messages, numTurns) {
|
|
1606
|
+
if (!Number.isFinite(numTurns) || numTurns <= 0)
|
|
1607
|
+
return;
|
|
1608
|
+
const userIndices = messages
|
|
1609
|
+
.map((message, index) => message.role === "user" && !message.isMeta ? index : -1)
|
|
1610
|
+
.filter((index) => index >= 0);
|
|
1611
|
+
if (userIndices.length === 0)
|
|
1612
|
+
return;
|
|
1613
|
+
if (numTurns >= userIndices.length) {
|
|
1614
|
+
messages.length = 0;
|
|
1615
|
+
return;
|
|
1616
|
+
}
|
|
1617
|
+
const keepUserTurns = userIndices.length - numTurns;
|
|
1618
|
+
const cutIndex = userIndices[keepUserTurns];
|
|
1619
|
+
messages.splice(cutIndex);
|
|
1385
1620
|
}
|
|
1386
1621
|
function appendImageGenerationResult(messages, payload, fallbackId, timestamp) {
|
|
1387
1622
|
const id = typeof payload.call_id === "string"
|
|
@@ -1884,6 +2119,7 @@ export async function getCodexSessionHistory(threadId) {
|
|
|
1884
2119
|
}
|
|
1885
2120
|
const messages = [];
|
|
1886
2121
|
const lines = raw.split("\n");
|
|
2122
|
+
let userTurnOrdinal = 0;
|
|
1887
2123
|
for (const [index, line] of lines.entries()) {
|
|
1888
2124
|
if (!line.trim())
|
|
1889
2125
|
continue;
|
|
@@ -1899,6 +2135,13 @@ export async function getCodexSessionHistory(threadId) {
|
|
|
1899
2135
|
const payload = asObject(entry.payload);
|
|
1900
2136
|
if (!payload)
|
|
1901
2137
|
continue;
|
|
2138
|
+
if (payload.type === "thread_rolled_back") {
|
|
2139
|
+
const rawNumTurns = payload.num_turns ?? payload.numTurns;
|
|
2140
|
+
const numTurns = typeof rawNumTurns === "number" ? rawNumTurns : Number(rawNumTurns);
|
|
2141
|
+
applyCodexThreadRollback(messages, numTurns);
|
|
2142
|
+
userTurnOrdinal = countCodexUserTurns(messages);
|
|
2143
|
+
continue;
|
|
2144
|
+
}
|
|
1902
2145
|
if (payload.type === "user_message") {
|
|
1903
2146
|
const rawMessage = typeof payload.message === "string" ? payload.message : "";
|
|
1904
2147
|
const images = Array.isArray(payload.images) ? payload.images.length : 0;
|
|
@@ -1917,6 +2160,7 @@ export async function getCodexSessionHistory(threadId) {
|
|
|
1917
2160
|
if (normalized) {
|
|
1918
2161
|
messages.push({
|
|
1919
2162
|
role: "user",
|
|
2163
|
+
uuid: codexUserTurnUuid(++userTurnOrdinal),
|
|
1920
2164
|
content: [{ type: "text", text }],
|
|
1921
2165
|
imageCount,
|
|
1922
2166
|
...(entryTimestamp ? { timestamp: entryTimestamp } : {}),
|
|
@@ -1924,7 +2168,9 @@ export async function getCodexSessionHistory(threadId) {
|
|
|
1924
2168
|
}
|
|
1925
2169
|
}
|
|
1926
2170
|
else {
|
|
1927
|
-
appendTextMessage(messages, "user", text, entryTimestamp)
|
|
2171
|
+
if (appendTextMessage(messages, "user", text, entryTimestamp, codexUserTurnUuid(userTurnOrdinal + 1))) {
|
|
2172
|
+
userTurnOrdinal += 1;
|
|
2173
|
+
}
|
|
1928
2174
|
}
|
|
1929
2175
|
continue;
|
|
1930
2176
|
}
|
|
@@ -1971,7 +2217,9 @@ export async function getCodexSessionHistory(threadId) {
|
|
|
1971
2217
|
.map((item) => item.text)
|
|
1972
2218
|
.join("\n");
|
|
1973
2219
|
if (!isCodexInjectedUserContext(text)) {
|
|
1974
|
-
appendTextMessage(messages, "user", text, entryTimestamp)
|
|
2220
|
+
if (appendTextMessage(messages, "user", text, entryTimestamp, codexUserTurnUuid(userTurnOrdinal + 1))) {
|
|
2221
|
+
userTurnOrdinal += 1;
|
|
2222
|
+
}
|
|
1975
2223
|
}
|
|
1976
2224
|
continue;
|
|
1977
2225
|
}
|