codex-to-im 1.0.47 → 1.0.49
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/daemon.mjs +39 -58
- package/package.json +1 -1
package/dist/daemon.mjs
CHANGED
|
@@ -359,6 +359,10 @@ function getTerminalDrainTimeoutMs() {
|
|
|
359
359
|
function isAbortError(error) {
|
|
360
360
|
return error instanceof DOMException && error.name === "AbortError" || error instanceof Error && error.name === "AbortError";
|
|
361
361
|
}
|
|
362
|
+
function isWindowsProcessTerminationParseNoise(message) {
|
|
363
|
+
const normalized = message.replace(/\s+/g, " ").trim().toLowerCase();
|
|
364
|
+
return normalized.startsWith("failed to parse item: success:") && normalized.includes("the process with pid") && normalized.includes("has been terminated");
|
|
365
|
+
}
|
|
362
366
|
function normalizeTaskText(value) {
|
|
363
367
|
return typeof value === "string" ? value.trim() : "";
|
|
364
368
|
}
|
|
@@ -505,6 +509,7 @@ var init_codex_provider = __esm({
|
|
|
505
509
|
}
|
|
506
510
|
let sawAnyEvent = false;
|
|
507
511
|
let sawTerminalEvent = false;
|
|
512
|
+
let sawCompletedAssistantContent = false;
|
|
508
513
|
const runAbortController = new AbortController();
|
|
509
514
|
let terminalDrainTimer = null;
|
|
510
515
|
const clearTerminalDrainTimer = () => {
|
|
@@ -555,10 +560,14 @@ var init_codex_provider = __esm({
|
|
|
555
560
|
case "item.updated":
|
|
556
561
|
case "item.completed": {
|
|
557
562
|
const item = event.item;
|
|
563
|
+
const phase = event.type === "item.started" ? "started" : event.type === "item.updated" ? "updated" : "completed";
|
|
564
|
+
if (phase === "completed" && item.type === "agent_message" && typeof item.text === "string" && item.text.trim()) {
|
|
565
|
+
sawCompletedAssistantContent = true;
|
|
566
|
+
}
|
|
558
567
|
self.handleItemEvent(
|
|
559
568
|
controller,
|
|
560
569
|
item,
|
|
561
|
-
|
|
570
|
+
phase,
|
|
562
571
|
params.sessionId,
|
|
563
572
|
emittedToolStarts
|
|
564
573
|
);
|
|
@@ -618,6 +627,10 @@ var init_codex_provider = __esm({
|
|
|
618
627
|
if (sawTerminalEvent && (runAbortController.signal.aborted || isAbortError(err)) && !userAborted) {
|
|
619
628
|
break;
|
|
620
629
|
}
|
|
630
|
+
if ((sawTerminalEvent || sawCompletedAssistantContent) && isWindowsProcessTerminationParseNoise(message)) {
|
|
631
|
+
console.warn("[codex-provider] Suppressed Codex SDK Windows process cleanup parse noise:", message);
|
|
632
|
+
break;
|
|
633
|
+
}
|
|
621
634
|
if (savedThreadId && !retryFresh && !sawAnyEvent && shouldRetryFreshThread(message)) {
|
|
622
635
|
console.warn("[codex-provider] Resume failed, retrying with a fresh thread:", message);
|
|
623
636
|
self.clearCachedThreadId(params.sessionId);
|
|
@@ -1402,7 +1415,8 @@ function buildPermissionButtonCard(text2, permissionRequestId, chatId) {
|
|
|
1402
1415
|
// src/lib/bridge/adapters/feishu-adapter.ts
|
|
1403
1416
|
var DEDUP_MAX = 1e3;
|
|
1404
1417
|
var MAX_FILE_SIZE = 20 * 1024 * 1024;
|
|
1405
|
-
var
|
|
1418
|
+
var COMPLETED_EMOJI = "DONE";
|
|
1419
|
+
var ERROR_EMOJI = "ERROR";
|
|
1406
1420
|
var CARD_THROTTLE_MS = 1e3;
|
|
1407
1421
|
var CARD_REQUEST_TIMEOUT_MS = 15e3;
|
|
1408
1422
|
var CARD_FINALIZE_FLUSH_WAIT_EXTRA_MS = 1e3;
|
|
@@ -1471,14 +1485,8 @@ var FeishuAdapter = class extends BaseChannelAdapter {
|
|
|
1471
1485
|
botOpenId = null;
|
|
1472
1486
|
/** All known bot IDs (open_id, user_id, union_id) for mention matching. */
|
|
1473
1487
|
botIds = /* @__PURE__ */ new Set();
|
|
1474
|
-
/** Track last incoming message ID per chat for
|
|
1488
|
+
/** Track last incoming message ID per chat for replying with streaming cards. */
|
|
1475
1489
|
lastIncomingMessageId = /* @__PURE__ */ new Map();
|
|
1476
|
-
/** Track active typing reaction IDs per stream key for cleanup. */
|
|
1477
|
-
typingReactions = /* @__PURE__ */ new Map();
|
|
1478
|
-
/** Track in-flight typing reaction creates so repeated status updates stay idempotent. */
|
|
1479
|
-
typingReactionCreatePromises = /* @__PURE__ */ new Map();
|
|
1480
|
-
/** Track streams that ended before the async reaction create finished. */
|
|
1481
|
-
typingReactionCleanupRequested = /* @__PURE__ */ new Set();
|
|
1482
1490
|
/** Active streaming card state per stream key. */
|
|
1483
1491
|
activeCards = /* @__PURE__ */ new Map();
|
|
1484
1492
|
/** In-flight card creation promises per stream key — prevents duplicate creation. */
|
|
@@ -1585,9 +1593,6 @@ var FeishuAdapter = class extends BaseChannelAdapter {
|
|
|
1585
1593
|
this.cardCreatePromises.clear();
|
|
1586
1594
|
this.seenMessageIds.clear();
|
|
1587
1595
|
this.lastIncomingMessageId.clear();
|
|
1588
|
-
this.typingReactions.clear();
|
|
1589
|
-
this.typingReactionCreatePromises.clear();
|
|
1590
|
-
this.typingReactionCleanupRequested.clear();
|
|
1591
1596
|
console.log("[feishu-adapter] Stopped");
|
|
1592
1597
|
}
|
|
1593
1598
|
isRunning() {
|
|
@@ -1597,67 +1602,24 @@ var FeishuAdapter = class extends BaseChannelAdapter {
|
|
|
1597
1602
|
consumeOne() {
|
|
1598
1603
|
return this.consumeInboundMessage(this.running);
|
|
1599
1604
|
}
|
|
1600
|
-
// ──
|
|
1605
|
+
// ── Streaming lifecycle hooks ──────────────────────────────
|
|
1601
1606
|
/**
|
|
1602
|
-
*
|
|
1607
|
+
* Create the streaming card as early as possible.
|
|
1603
1608
|
* Called by bridge-manager via onMessageStart().
|
|
1604
1609
|
*/
|
|
1605
1610
|
onMessageStart(chatId, streamKey) {
|
|
1606
1611
|
const messageId = this.lastIncomingMessageId.get(chatId);
|
|
1607
|
-
const reactionKey = this.resolveStreamKey(chatId, streamKey);
|
|
1608
1612
|
if (messageId && this.isStreamingEnabled()) {
|
|
1609
1613
|
this.createStreamingCard(chatId, messageId, streamKey).catch(() => {
|
|
1610
1614
|
});
|
|
1611
1615
|
}
|
|
1612
|
-
if (!messageId || !this.restClient) return;
|
|
1613
|
-
if (this.typingReactions.has(reactionKey) || this.typingReactionCreatePromises.has(reactionKey)) {
|
|
1614
|
-
return;
|
|
1615
|
-
}
|
|
1616
|
-
const createPromise = this.restClient.im.messageReaction.create({
|
|
1617
|
-
path: { message_id: messageId },
|
|
1618
|
-
data: { reaction_type: { emoji_type: TYPING_EMOJI } }
|
|
1619
|
-
}).then((res) => {
|
|
1620
|
-
const reactionId = res?.data?.reaction_id;
|
|
1621
|
-
if (reactionId) {
|
|
1622
|
-
this.typingReactions.set(reactionKey, { messageId, reactionId });
|
|
1623
|
-
if (this.typingReactionCleanupRequested.delete(reactionKey)) {
|
|
1624
|
-
this.removeTypingReaction(reactionKey);
|
|
1625
|
-
}
|
|
1626
|
-
}
|
|
1627
|
-
}).catch((err) => {
|
|
1628
|
-
const code2 = err?.code;
|
|
1629
|
-
if (code2 !== 99991400 && code2 !== 99991403) {
|
|
1630
|
-
console.warn("[feishu-adapter] Typing indicator failed:", err instanceof Error ? err.message : err);
|
|
1631
|
-
}
|
|
1632
|
-
}).finally(() => {
|
|
1633
|
-
this.typingReactionCreatePromises.delete(reactionKey);
|
|
1634
|
-
if (!this.typingReactions.has(reactionKey)) {
|
|
1635
|
-
this.typingReactionCleanupRequested.delete(reactionKey);
|
|
1636
|
-
}
|
|
1637
|
-
});
|
|
1638
|
-
this.typingReactionCreatePromises.set(reactionKey, createPromise);
|
|
1639
1616
|
}
|
|
1640
1617
|
/**
|
|
1641
|
-
*
|
|
1618
|
+
* Clean up card state.
|
|
1642
1619
|
* Called by bridge-manager via onMessageEnd().
|
|
1643
1620
|
*/
|
|
1644
1621
|
onMessageEnd(chatId, streamKey) {
|
|
1645
1622
|
this.cleanupCard(chatId, streamKey);
|
|
1646
|
-
const reactionKey = this.resolveStreamKey(chatId, streamKey);
|
|
1647
|
-
if (this.typingReactionCreatePromises.has(reactionKey) && !this.typingReactions.has(reactionKey)) {
|
|
1648
|
-
this.typingReactionCleanupRequested.add(reactionKey);
|
|
1649
|
-
return;
|
|
1650
|
-
}
|
|
1651
|
-
this.removeTypingReaction(reactionKey);
|
|
1652
|
-
}
|
|
1653
|
-
removeTypingReaction(reactionKey) {
|
|
1654
|
-
const reaction = this.typingReactions.get(reactionKey);
|
|
1655
|
-
if (!reaction || !this.restClient) return;
|
|
1656
|
-
this.typingReactions.delete(reactionKey);
|
|
1657
|
-
this.restClient.im.messageReaction.delete({
|
|
1658
|
-
path: { message_id: reaction.messageId, reaction_id: reaction.reactionId }
|
|
1659
|
-
}).catch(() => {
|
|
1660
|
-
});
|
|
1661
1623
|
}
|
|
1662
1624
|
// ── Card Action Handler ─────────────────────────────────────
|
|
1663
1625
|
/**
|
|
@@ -2042,6 +2004,10 @@ ${trimmedResponse}`;
|
|
|
2042
2004
|
sequence: state.sequence
|
|
2043
2005
|
}
|
|
2044
2006
|
}));
|
|
2007
|
+
const terminalReactionEmoji = status === "completed" ? COMPLETED_EMOJI : status === "error" ? ERROR_EMOJI : null;
|
|
2008
|
+
if (terminalReactionEmoji) {
|
|
2009
|
+
await this.addTerminalReaction(cardKey, state.messageId, terminalReactionEmoji);
|
|
2010
|
+
}
|
|
2045
2011
|
console.log(`[feishu-adapter] Card finalized: streamKey=${cardKey}, cardId=${state.cardId}, status=${status}, elapsed=${formatElapsed(elapsedMs)}`);
|
|
2046
2012
|
return true;
|
|
2047
2013
|
} catch (err) {
|
|
@@ -2051,6 +2017,21 @@ ${trimmedResponse}`;
|
|
|
2051
2017
|
this.activeCards.delete(cardKey);
|
|
2052
2018
|
}
|
|
2053
2019
|
}
|
|
2020
|
+
async addTerminalReaction(streamKey, messageId, emojiType) {
|
|
2021
|
+
const messageReaction = this.restClient?.im?.messageReaction;
|
|
2022
|
+
if (typeof messageReaction?.create !== "function") return;
|
|
2023
|
+
try {
|
|
2024
|
+
await this.withFeishuRequestTimeout(streamKey, `im.messageReaction.create:${emojiType}`, () => messageReaction.create({
|
|
2025
|
+
path: { message_id: messageId },
|
|
2026
|
+
data: { reaction_type: { emoji_type: emojiType } }
|
|
2027
|
+
}));
|
|
2028
|
+
} catch (err) {
|
|
2029
|
+
const code2 = err?.code;
|
|
2030
|
+
if (code2 !== 99991400 && code2 !== 99991403) {
|
|
2031
|
+
console.warn("[feishu-adapter] Terminal reaction failed:", err instanceof Error ? err.message : err);
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2054
2035
|
/**
|
|
2055
2036
|
* Clean up card state without finalizing (e.g. on unexpected errors).
|
|
2056
2037
|
*/
|
package/package.json
CHANGED