codex-to-im 1.0.46 → 1.0.48
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 +271 -13
- package/package.json +2 -2
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
|
);
|
|
@@ -571,7 +580,8 @@ var init_codex_provider = __esm({
|
|
|
571
580
|
usage: usage ? {
|
|
572
581
|
input_tokens: usage.input_tokens ?? 0,
|
|
573
582
|
output_tokens: usage.output_tokens ?? 0,
|
|
574
|
-
cache_read_input_tokens: usage.cached_input_tokens ?? 0
|
|
583
|
+
cache_read_input_tokens: usage.cached_input_tokens ?? 0,
|
|
584
|
+
reasoning_output_tokens: usage.reasoning_output_tokens ?? 0
|
|
575
585
|
} : void 0,
|
|
576
586
|
...threadId ? { session_id: threadId } : {}
|
|
577
587
|
}));
|
|
@@ -617,6 +627,10 @@ var init_codex_provider = __esm({
|
|
|
617
627
|
if (sawTerminalEvent && (runAbortController.signal.aborted || isAbortError(err)) && !userAborted) {
|
|
618
628
|
break;
|
|
619
629
|
}
|
|
630
|
+
if ((sawTerminalEvent || sawCompletedAssistantContent) && isWindowsProcessTerminationParseNoise(message)) {
|
|
631
|
+
console.warn("[codex-provider] Suppressed Codex SDK Windows process cleanup parse noise:", message);
|
|
632
|
+
break;
|
|
633
|
+
}
|
|
620
634
|
if (savedThreadId && !retryFresh && !sawAnyEvent && shouldRetryFreshThread(message)) {
|
|
621
635
|
console.warn("[codex-provider] Resume failed, retrying with a fresh thread:", message);
|
|
622
636
|
self.clearCachedThreadId(params.sessionId);
|
|
@@ -10071,6 +10085,13 @@ function parseUpdatePlanTasks(argumentsJson) {
|
|
|
10071
10085
|
if (!parsed || typeof parsed !== "object") return [];
|
|
10072
10086
|
return parseTaskProgressItems(parsed.plan ?? parsed.tasks);
|
|
10073
10087
|
}
|
|
10088
|
+
function extractReasoningSummary(payload) {
|
|
10089
|
+
for (const value of [payload.summary, payload.content, payload.text, payload.message]) {
|
|
10090
|
+
const text2 = extractNormalizedStructuredText(value);
|
|
10091
|
+
if (text2) return text2;
|
|
10092
|
+
}
|
|
10093
|
+
return "";
|
|
10094
|
+
}
|
|
10074
10095
|
function extractToolOutputText(value) {
|
|
10075
10096
|
if (typeof value !== "string") return extractNormalizedFreeText(value);
|
|
10076
10097
|
const trimmed = value.trim();
|
|
@@ -10084,6 +10105,39 @@ function extractToolOutputText(value) {
|
|
|
10084
10105
|
}
|
|
10085
10106
|
return extractNormalizedFreeText(value);
|
|
10086
10107
|
}
|
|
10108
|
+
function summarizePatchChanges(value) {
|
|
10109
|
+
if (!value || typeof value !== "object") return "";
|
|
10110
|
+
return Object.entries(value).map(([filePath, detail]) => {
|
|
10111
|
+
const kind = detail && typeof detail === "object" ? extractNormalizedFreeText(detail.type ?? detail.kind) : "";
|
|
10112
|
+
return kind ? `${kind}: ${filePath}` : filePath;
|
|
10113
|
+
}).filter(Boolean).join("\n");
|
|
10114
|
+
}
|
|
10115
|
+
function summarizeToolSearchOutput(value) {
|
|
10116
|
+
if (!Array.isArray(value)) return "";
|
|
10117
|
+
let count = 0;
|
|
10118
|
+
const names = [];
|
|
10119
|
+
for (const entry of value) {
|
|
10120
|
+
if (!entry || typeof entry !== "object") continue;
|
|
10121
|
+
const namespaceName = extractNormalizedFreeText(entry.name);
|
|
10122
|
+
if (namespaceName) names.push(namespaceName);
|
|
10123
|
+
const tools = entry.tools;
|
|
10124
|
+
if (Array.isArray(tools)) count += tools.length;
|
|
10125
|
+
}
|
|
10126
|
+
const prefix = count > 0 ? `Found ${count} tools` : "";
|
|
10127
|
+
const suffix = names.length > 0 ? names.slice(0, 5).join(", ") : "";
|
|
10128
|
+
return [prefix, suffix].filter(Boolean).join(": ");
|
|
10129
|
+
}
|
|
10130
|
+
function getDynamicToolCallId(payload) {
|
|
10131
|
+
return extractNormalizedFreeText(payload.call_id ?? payload.callId);
|
|
10132
|
+
}
|
|
10133
|
+
function formatDesktopToolName(namespaceValue, nameValue) {
|
|
10134
|
+
const name = extractNormalizedFreeText(nameValue);
|
|
10135
|
+
if (!name) return "";
|
|
10136
|
+
const namespace = extractNormalizedFreeText(namespaceValue);
|
|
10137
|
+
if (!namespace) return name;
|
|
10138
|
+
if (name.startsWith(namespace)) return name;
|
|
10139
|
+
return namespace.endsWith("__") || namespace.endsWith("/") || namespace.endsWith(".") ? `${namespace}${name}` : `${namespace}__${name}`;
|
|
10140
|
+
}
|
|
10087
10141
|
function createDesktopEventSignature(rawLine) {
|
|
10088
10142
|
return crypto4.createHash("sha1").update(rawLine).digest("hex");
|
|
10089
10143
|
}
|
|
@@ -10115,7 +10169,28 @@ function isSessionMessageLine(line) {
|
|
|
10115
10169
|
function isTurnContextLine(line) {
|
|
10116
10170
|
return line.type === "turn_context";
|
|
10117
10171
|
}
|
|
10172
|
+
var IGNORED_EVENT_MSG_TYPES = /* @__PURE__ */ new Set([
|
|
10173
|
+
"context_compacted",
|
|
10174
|
+
"thread_name_updated",
|
|
10175
|
+
"thread_rolled_back",
|
|
10176
|
+
"token_count"
|
|
10177
|
+
]);
|
|
10178
|
+
var IGNORED_RESPONSE_ITEM_TYPES = /* @__PURE__ */ new Set([
|
|
10179
|
+
"web_search_call"
|
|
10180
|
+
]);
|
|
10181
|
+
function isIgnoredMirrorLineKind(line) {
|
|
10182
|
+
if (isSessionEventLine(line)) {
|
|
10183
|
+
const payloadType = typeof line.payload?.type === "string" ? line.payload.type.trim() : "";
|
|
10184
|
+
return IGNORED_EVENT_MSG_TYPES.has(payloadType);
|
|
10185
|
+
}
|
|
10186
|
+
if (isSessionMessageLine(line)) {
|
|
10187
|
+
const payloadType = typeof line.payload?.type === "string" ? line.payload.type.trim() : "";
|
|
10188
|
+
return IGNORED_RESPONSE_ITEM_TYPES.has(payloadType);
|
|
10189
|
+
}
|
|
10190
|
+
return false;
|
|
10191
|
+
}
|
|
10118
10192
|
function describeUnhandledMirrorLineKind(line) {
|
|
10193
|
+
if (isIgnoredMirrorLineKind(line)) return null;
|
|
10119
10194
|
if (isSessionEventLine(line)) {
|
|
10120
10195
|
const payloadType = typeof line.payload?.type === "string" ? line.payload.type.trim() : "";
|
|
10121
10196
|
return `event_msg:${payloadType || "<unknown>"}`;
|
|
@@ -10192,6 +10267,20 @@ function pushDesktopSessionEvent(events, parsed, rawLine) {
|
|
|
10192
10267
|
});
|
|
10193
10268
|
return;
|
|
10194
10269
|
}
|
|
10270
|
+
if (isSessionEventLine(parsed) && parsed.payload?.type === "agent_message") {
|
|
10271
|
+
const text2 = extractNormalizedStructuredText(parsed.payload.message);
|
|
10272
|
+
if (!text2) return;
|
|
10273
|
+
const role = parsed.payload.phase === "commentary" ? "commentary" : "assistant";
|
|
10274
|
+
const lastEvent = events[events.length - 1];
|
|
10275
|
+
if (lastEvent?.role === role && lastEvent.content === text2) return;
|
|
10276
|
+
events.push({
|
|
10277
|
+
signature: createDesktopEventSignature(rawLine),
|
|
10278
|
+
role,
|
|
10279
|
+
content: text2,
|
|
10280
|
+
timestamp: parsed.timestamp || ""
|
|
10281
|
+
});
|
|
10282
|
+
return;
|
|
10283
|
+
}
|
|
10195
10284
|
if (isSessionEventLine(parsed) && parsed.payload?.type === "task_complete") {
|
|
10196
10285
|
const text2 = extractNormalizedStructuredText(parsed.payload.last_agent_message);
|
|
10197
10286
|
if (!text2) return;
|
|
@@ -10210,10 +10299,14 @@ function pushDesktopSessionEvent(events, parsed, rawLine) {
|
|
|
10210
10299
|
if (isSessionMessageLine(parsed) && parsed.payload?.type === "message" && parsed.payload.role === "assistant") {
|
|
10211
10300
|
const text2 = extractDesktopMessageText(parsed);
|
|
10212
10301
|
if (!text2) return;
|
|
10302
|
+
const role = parsed.payload.phase === "commentary" ? "commentary" : "assistant";
|
|
10303
|
+
const content = parsed.payload.phase === "commentary" ? text2.replace(/^\[commentary\]\n/, "") : text2;
|
|
10304
|
+
const lastEvent = events[events.length - 1];
|
|
10305
|
+
if (lastEvent?.role === role && lastEvent.content === content) return;
|
|
10213
10306
|
events.push({
|
|
10214
10307
|
signature: createDesktopEventSignature(rawLine),
|
|
10215
|
-
role
|
|
10216
|
-
content
|
|
10308
|
+
role,
|
|
10309
|
+
content,
|
|
10217
10310
|
timestamp: parsed.timestamp || ""
|
|
10218
10311
|
});
|
|
10219
10312
|
}
|
|
@@ -10250,6 +10343,22 @@ function pushDesktopMirrorEventRecord(records, parsed, rawLine, activeTurnId) {
|
|
|
10250
10343
|
});
|
|
10251
10344
|
return true;
|
|
10252
10345
|
}
|
|
10346
|
+
if (isIgnoredMirrorLineKind(parsed)) {
|
|
10347
|
+
return true;
|
|
10348
|
+
}
|
|
10349
|
+
if (parsed.payload?.type === "agent_message") {
|
|
10350
|
+
const text2 = extractNormalizedStructuredText(parsed.payload.message);
|
|
10351
|
+
if (!text2) return true;
|
|
10352
|
+
records.push({
|
|
10353
|
+
signature,
|
|
10354
|
+
type: "message",
|
|
10355
|
+
role: parsed.payload.phase === "commentary" ? "commentary" : "assistant",
|
|
10356
|
+
content: text2,
|
|
10357
|
+
timestamp,
|
|
10358
|
+
...activeTurnId ? { turnId: activeTurnId } : {}
|
|
10359
|
+
});
|
|
10360
|
+
return true;
|
|
10361
|
+
}
|
|
10253
10362
|
if (parsed.payload?.type === "agent_reasoning") {
|
|
10254
10363
|
const text2 = extractNormalizedStructuredText(parsed.payload.text);
|
|
10255
10364
|
if (!text2) return true;
|
|
@@ -10292,6 +10401,68 @@ function pushDesktopMirrorEventRecord(records, parsed, rawLine, activeTurnId) {
|
|
|
10292
10401
|
});
|
|
10293
10402
|
return true;
|
|
10294
10403
|
}
|
|
10404
|
+
if (parsed.payload?.type === "exec_command_end") {
|
|
10405
|
+
const toolId = extractNormalizedFreeText(parsed.payload.call_id) || signature;
|
|
10406
|
+
const exitCode = typeof parsed.payload.exit_code === "number" ? parsed.payload.exit_code : null;
|
|
10407
|
+
const status = extractNormalizedFreeText(parsed.payload.status).toLowerCase();
|
|
10408
|
+
records.push({
|
|
10409
|
+
signature,
|
|
10410
|
+
type: "tool_finished",
|
|
10411
|
+
content: extractToolOutputText(
|
|
10412
|
+
parsed.payload.aggregated_output ?? parsed.payload.formatted_output ?? parsed.payload.stdout ?? parsed.payload.stderr ?? parsed.payload.command
|
|
10413
|
+
),
|
|
10414
|
+
timestamp,
|
|
10415
|
+
...parsed.payload.turn_id || activeTurnId ? { turnId: parsed.payload.turn_id || activeTurnId || void 0 } : {},
|
|
10416
|
+
toolId,
|
|
10417
|
+
toolName: "Bash",
|
|
10418
|
+
isError: status === "failed" || exitCode != null && exitCode !== 0
|
|
10419
|
+
});
|
|
10420
|
+
return true;
|
|
10421
|
+
}
|
|
10422
|
+
if (parsed.payload?.type === "patch_apply_end") {
|
|
10423
|
+
const toolId = extractNormalizedFreeText(parsed.payload.call_id) || signature;
|
|
10424
|
+
const status = extractNormalizedFreeText(parsed.payload.status).toLowerCase();
|
|
10425
|
+
records.push({
|
|
10426
|
+
signature,
|
|
10427
|
+
type: "tool_finished",
|
|
10428
|
+
content: summarizePatchChanges(parsed.payload.changes) || extractToolOutputText(parsed.payload.stdout ?? parsed.payload.stderr),
|
|
10429
|
+
timestamp,
|
|
10430
|
+
...parsed.payload.turn_id || activeTurnId ? { turnId: parsed.payload.turn_id || activeTurnId || void 0 } : {},
|
|
10431
|
+
toolId,
|
|
10432
|
+
toolName: "apply_patch",
|
|
10433
|
+
isError: parsed.payload.success === false || status === "failed"
|
|
10434
|
+
});
|
|
10435
|
+
return true;
|
|
10436
|
+
}
|
|
10437
|
+
if (parsed.payload?.type === "dynamic_tool_call_request") {
|
|
10438
|
+
const toolId = getDynamicToolCallId(parsed.payload) || signature;
|
|
10439
|
+
const toolName = extractNormalizedFreeText(parsed.payload.tool) || "tool";
|
|
10440
|
+
records.push({
|
|
10441
|
+
signature,
|
|
10442
|
+
type: "tool_started",
|
|
10443
|
+
content: "",
|
|
10444
|
+
timestamp,
|
|
10445
|
+
...parsed.payload.turnId || activeTurnId ? { turnId: parsed.payload.turnId || activeTurnId || void 0 } : {},
|
|
10446
|
+
toolId,
|
|
10447
|
+
toolName
|
|
10448
|
+
});
|
|
10449
|
+
return true;
|
|
10450
|
+
}
|
|
10451
|
+
if (parsed.payload?.type === "dynamic_tool_call_response") {
|
|
10452
|
+
const toolId = getDynamicToolCallId(parsed.payload) || signature;
|
|
10453
|
+
const toolName = extractNormalizedFreeText(parsed.payload.tool) || "tool";
|
|
10454
|
+
records.push({
|
|
10455
|
+
signature,
|
|
10456
|
+
type: "tool_finished",
|
|
10457
|
+
content: extractToolOutputText(parsed.payload.content_items ?? parsed.payload.error),
|
|
10458
|
+
timestamp,
|
|
10459
|
+
...parsed.payload.turn_id || activeTurnId ? { turnId: parsed.payload.turn_id || activeTurnId || void 0 } : {},
|
|
10460
|
+
toolId,
|
|
10461
|
+
toolName,
|
|
10462
|
+
isError: parsed.payload.success === false
|
|
10463
|
+
});
|
|
10464
|
+
return true;
|
|
10465
|
+
}
|
|
10295
10466
|
if (parsed.payload?.type === "user_message") {
|
|
10296
10467
|
const text2 = extractNormalizedStructuredText(parsed.payload.message);
|
|
10297
10468
|
if (!text2) return true;
|
|
@@ -10321,6 +10492,21 @@ function pushDesktopMirrorEventRecord(records, parsed, rawLine, activeTurnId) {
|
|
|
10321
10492
|
function pushDesktopMirrorResponseRecord(records, parsed, rawLine, activeTurnId, activeSpecialCallIds) {
|
|
10322
10493
|
const signature = createDesktopEventSignature(rawLine);
|
|
10323
10494
|
const timestamp = parsed.timestamp || "";
|
|
10495
|
+
if (isIgnoredMirrorLineKind(parsed)) {
|
|
10496
|
+
return true;
|
|
10497
|
+
}
|
|
10498
|
+
if (parsed.payload?.type === "reasoning") {
|
|
10499
|
+
const text2 = extractReasoningSummary(parsed.payload);
|
|
10500
|
+
if (!text2) return true;
|
|
10501
|
+
records.push({
|
|
10502
|
+
signature,
|
|
10503
|
+
type: "reasoning",
|
|
10504
|
+
content: text2,
|
|
10505
|
+
timestamp,
|
|
10506
|
+
...activeTurnId ? { turnId: activeTurnId } : {}
|
|
10507
|
+
});
|
|
10508
|
+
return true;
|
|
10509
|
+
}
|
|
10324
10510
|
if (parsed.payload?.type === "message" && parsed.payload.role === "assistant") {
|
|
10325
10511
|
const text2 = extractDesktopMessageText(parsed);
|
|
10326
10512
|
if (!text2) return true;
|
|
@@ -10334,8 +10520,36 @@ function pushDesktopMirrorResponseRecord(records, parsed, rawLine, activeTurnId,
|
|
|
10334
10520
|
});
|
|
10335
10521
|
return true;
|
|
10336
10522
|
}
|
|
10523
|
+
if (parsed.payload?.type === "tool_search_call") {
|
|
10524
|
+
const toolId = extractNormalizedFreeText(parsed.payload.call_id) || signature;
|
|
10525
|
+
records.push({
|
|
10526
|
+
signature,
|
|
10527
|
+
type: "tool_started",
|
|
10528
|
+
content: "",
|
|
10529
|
+
timestamp,
|
|
10530
|
+
...activeTurnId ? { turnId: activeTurnId } : {},
|
|
10531
|
+
toolId,
|
|
10532
|
+
toolName: "tool_search"
|
|
10533
|
+
});
|
|
10534
|
+
return true;
|
|
10535
|
+
}
|
|
10536
|
+
if (parsed.payload?.type === "tool_search_output") {
|
|
10537
|
+
const toolId = extractNormalizedFreeText(parsed.payload.call_id) || signature;
|
|
10538
|
+
const status = extractNormalizedFreeText(parsed.payload.status).toLowerCase();
|
|
10539
|
+
records.push({
|
|
10540
|
+
signature,
|
|
10541
|
+
type: "tool_finished",
|
|
10542
|
+
content: summarizeToolSearchOutput(parsed.payload.tools),
|
|
10543
|
+
timestamp,
|
|
10544
|
+
...activeTurnId ? { turnId: activeTurnId } : {},
|
|
10545
|
+
toolId,
|
|
10546
|
+
toolName: "tool_search",
|
|
10547
|
+
isError: status === "failed"
|
|
10548
|
+
});
|
|
10549
|
+
return true;
|
|
10550
|
+
}
|
|
10337
10551
|
if (parsed.payload?.type === "function_call") {
|
|
10338
|
-
const toolName =
|
|
10552
|
+
const toolName = formatDesktopToolName(parsed.payload.namespace, parsed.payload.name);
|
|
10339
10553
|
const toolId = extractNormalizedFreeText(parsed.payload.call_id) || signature;
|
|
10340
10554
|
if (!toolName) return true;
|
|
10341
10555
|
if (toolName === "update_plan") {
|
|
@@ -10363,7 +10577,7 @@ function pushDesktopMirrorResponseRecord(records, parsed, rawLine, activeTurnId,
|
|
|
10363
10577
|
return true;
|
|
10364
10578
|
}
|
|
10365
10579
|
if (parsed.payload?.type === "custom_tool_call") {
|
|
10366
|
-
const toolName =
|
|
10580
|
+
const toolName = formatDesktopToolName(parsed.payload.namespace, parsed.payload.name);
|
|
10367
10581
|
const toolId = extractNormalizedFreeText(parsed.payload.call_id) || signature;
|
|
10368
10582
|
if (!toolName) return true;
|
|
10369
10583
|
if (toolName === "update_plan") {
|
|
@@ -11801,6 +12015,7 @@ ${notice}` : notice;
|
|
|
11801
12015
|
function nowIso2() {
|
|
11802
12016
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
11803
12017
|
}
|
|
12018
|
+
var MIRROR_DUPLICATE_TEXT_WINDOW_MS = 2e3;
|
|
11804
12019
|
function createMirrorTurnState(sessionId, timestamp, turnId) {
|
|
11805
12020
|
const safeTimestamp = timestamp || nowIso2();
|
|
11806
12021
|
return {
|
|
@@ -11865,6 +12080,14 @@ function markMirrorContentResponse(turnState, timestamp) {
|
|
|
11865
12080
|
turnState.lastContentResponseAt = responseAt;
|
|
11866
12081
|
turnState.lastResponseAt = responseAt;
|
|
11867
12082
|
}
|
|
12083
|
+
function isNearDuplicateMirrorText(previousText, nextText, previousTimestamp, nextTimestamp) {
|
|
12084
|
+
if (previousText !== nextText) return false;
|
|
12085
|
+
if (!previousTimestamp || !nextTimestamp) return true;
|
|
12086
|
+
const previousMs = Date.parse(previousTimestamp);
|
|
12087
|
+
const nextMs = Date.parse(nextTimestamp);
|
|
12088
|
+
if (!Number.isFinite(previousMs) || !Number.isFinite(nextMs)) return true;
|
|
12089
|
+
return Math.abs(nextMs - previousMs) <= MIRROR_DUPLICATE_TEXT_WINDOW_MS;
|
|
12090
|
+
}
|
|
11868
12091
|
function finalizeMirrorTurn(subscription, signature, timestamp, status, preferredText) {
|
|
11869
12092
|
const pendingTurn = subscription.pendingTurn;
|
|
11870
12093
|
subscription.pendingTurn = null;
|
|
@@ -11934,7 +12157,14 @@ function consumeMirrorRecords(subscription, records, hooks = {}) {
|
|
|
11934
12157
|
if (record.role === "assistant") {
|
|
11935
12158
|
const text2 = record.content.trim();
|
|
11936
12159
|
if (text2) {
|
|
12160
|
+
if (isNearDuplicateMirrorText(
|
|
12161
|
+
pendingTurn.lastAssistantText,
|
|
12162
|
+
text2,
|
|
12163
|
+
pendingTurn.lastAssistantTextAt ?? null,
|
|
12164
|
+
record.timestamp
|
|
12165
|
+
)) continue;
|
|
11937
12166
|
pendingTurn.lastAssistantText = text2;
|
|
12167
|
+
pendingTurn.lastAssistantTextAt = record.timestamp || nowIso2();
|
|
11938
12168
|
appendMirrorStreamText(pendingTurn, text2);
|
|
11939
12169
|
markMirrorContentResponse(pendingTurn, record.timestamp);
|
|
11940
12170
|
hooks.onStreamText?.(subscription, pendingTurn);
|
|
@@ -11942,7 +12172,14 @@ function consumeMirrorRecords(subscription, records, hooks = {}) {
|
|
|
11942
12172
|
} else if (record.role === "commentary") {
|
|
11943
12173
|
const text2 = record.content.trim();
|
|
11944
12174
|
if (text2) {
|
|
12175
|
+
if (isNearDuplicateMirrorText(
|
|
12176
|
+
pendingTurn.lastCommentaryText,
|
|
12177
|
+
text2,
|
|
12178
|
+
pendingTurn.lastCommentaryTextAt ?? null,
|
|
12179
|
+
record.timestamp
|
|
12180
|
+
)) continue;
|
|
11945
12181
|
pendingTurn.lastCommentaryText = text2;
|
|
12182
|
+
pendingTurn.lastCommentaryTextAt = record.timestamp || nowIso2();
|
|
11946
12183
|
appendMirrorStreamText(pendingTurn, text2);
|
|
11947
12184
|
markMirrorContentResponse(pendingTurn, record.timestamp);
|
|
11948
12185
|
hooks.onStreamText?.(subscription, pendingTurn);
|
|
@@ -14243,6 +14480,10 @@ function shouldShowStreamLastContentResponseAge(state, nowMs, config2) {
|
|
|
14243
14480
|
const ageMs = getStreamLastContentResponseAgeMs(state, nowMs);
|
|
14244
14481
|
return ageMs != null && ageMs >= Math.max(1e3, config2.heartbeatMs);
|
|
14245
14482
|
}
|
|
14483
|
+
function getVisibleStreamLastContentResponseAgeMs(state, nowMs, config2) {
|
|
14484
|
+
if (!shouldShowStreamLastContentResponseAge(state, nowMs, config2)) return null;
|
|
14485
|
+
return getStreamLastContentResponseAgeMs(state, nowMs);
|
|
14486
|
+
}
|
|
14246
14487
|
function buildStreamRuntimeStatus(state, nowMs, options = {}) {
|
|
14247
14488
|
return formatStreamRuntimeStatus(
|
|
14248
14489
|
Math.max(0, nowMs - state.startedAtMs),
|
|
@@ -14479,11 +14720,20 @@ async function runInteractiveMessage(adapter, msg, text2, attachments, deps) {
|
|
|
14479
14720
|
if (!snapshot) return;
|
|
14480
14721
|
deps.recordInteractiveStreamUiSnapshot?.(binding.codepilotSessionId, snapshot);
|
|
14481
14722
|
};
|
|
14723
|
+
const getVisibleLastResponseAgeMs = () => getVisibleStreamLastContentResponseAgeMs(
|
|
14724
|
+
streamState,
|
|
14725
|
+
nowMs(),
|
|
14726
|
+
{
|
|
14727
|
+
idleStartMs: streamStatusIdleDetectionStartMs,
|
|
14728
|
+
heartbeatMs: streamStatusHeartbeatMs
|
|
14729
|
+
}
|
|
14730
|
+
);
|
|
14482
14731
|
const pushRunningStatus = (lastResponseAgeMs) => {
|
|
14483
14732
|
if (!supportsStructuredStreamUi || streamStatusUpdatesClosed) return;
|
|
14733
|
+
const effectiveLastResponseAgeMs = lastResponseAgeMs === void 0 ? getVisibleLastResponseAgeMs() : lastResponseAgeMs;
|
|
14484
14734
|
pushStreamFeedbackStatus(
|
|
14485
14735
|
streamFeedbackTarget,
|
|
14486
|
-
|
|
14736
|
+
effectiveLastResponseAgeMs == null ? buildStreamRuntimeStatus(streamState, nowMs()) : formatStreamRuntimeStatus(nowMs() - taskStartedAt, effectiveLastResponseAgeMs, streamState.statusNote)
|
|
14487
14737
|
);
|
|
14488
14738
|
syncStructuredStreamUiSnapshot();
|
|
14489
14739
|
};
|
|
@@ -14570,7 +14820,7 @@ async function runInteractiveMessage(adapter, msg, text2, attachments, deps) {
|
|
|
14570
14820
|
if (hasStreamingCards) {
|
|
14571
14821
|
pushStreamFeedbackTools(streamFeedbackTarget, Array.from(toolCallTracker.values()));
|
|
14572
14822
|
}
|
|
14573
|
-
pushRunningStatus(
|
|
14823
|
+
pushRunningStatus();
|
|
14574
14824
|
syncStructuredStreamUiSnapshot();
|
|
14575
14825
|
};
|
|
14576
14826
|
const onTaskEvent = (tasks) => {
|
|
@@ -14580,14 +14830,14 @@ async function runInteractiveMessage(adapter, msg, text2, attachments, deps) {
|
|
|
14580
14830
|
if (hasStreamingCards) {
|
|
14581
14831
|
pushStreamFeedbackTasks(streamFeedbackTarget, latestTasks);
|
|
14582
14832
|
}
|
|
14583
|
-
pushRunningStatus(
|
|
14833
|
+
pushRunningStatus();
|
|
14584
14834
|
syncStructuredStreamUiSnapshot();
|
|
14585
14835
|
};
|
|
14586
14836
|
const onStatusNote = (note) => {
|
|
14587
14837
|
if (!deps.isCurrentInteractiveTask(binding.codepilotSessionId, taskId)) return;
|
|
14588
14838
|
updateStreamStatusNote(streamState, note, nowMs());
|
|
14589
14839
|
if (streamState.statusNote) markActivity();
|
|
14590
|
-
pushRunningStatus(
|
|
14840
|
+
pushRunningStatus();
|
|
14591
14841
|
syncStructuredStreamUiSnapshot();
|
|
14592
14842
|
};
|
|
14593
14843
|
const onPartialText = (fullText) => {
|
|
@@ -14598,7 +14848,7 @@ async function runInteractiveMessage(adapter, msg, text2, attachments, deps) {
|
|
|
14598
14848
|
deps.recordInteractiveHealthProgress(binding.codepilotSessionId, "text");
|
|
14599
14849
|
previewOnPartialText?.(fullText);
|
|
14600
14850
|
onStreamCardText?.(fullText);
|
|
14601
|
-
pushRunningStatus(
|
|
14851
|
+
pushRunningStatus();
|
|
14602
14852
|
syncStructuredStreamUiSnapshot();
|
|
14603
14853
|
};
|
|
14604
14854
|
const waitForDesktopTerminalFinalization = async () => {
|
|
@@ -14690,7 +14940,7 @@ async function runInteractiveMessage(adapter, msg, text2, attachments, deps) {
|
|
|
14690
14940
|
`\u5F53\u524D\u6B63\u5728\u7B49\u5F85\u5DE5\u5177 ${perm.toolName} \u7684\u6743\u9650\u786E\u8BA4\u3002`
|
|
14691
14941
|
);
|
|
14692
14942
|
markActivity();
|
|
14693
|
-
pushRunningStatus(
|
|
14943
|
+
pushRunningStatus();
|
|
14694
14944
|
syncStructuredStreamUiSnapshot();
|
|
14695
14945
|
},
|
|
14696
14946
|
taskAbort.signal,
|
|
@@ -15724,9 +15974,16 @@ function createMirrorFeedbackController(deps) {
|
|
|
15724
15974
|
if (minIntervalMs > 0 && turnState.lastStatusAt > 0 && nowMs - turnState.lastStatusAt < minIntervalMs) {
|
|
15725
15975
|
return;
|
|
15726
15976
|
}
|
|
15977
|
+
const lastContentResponseAtMs = turnState.lastContentResponseAt ? Date.parse(turnState.lastContentResponseAt) : turnState.lastResponseAt ? Date.parse(turnState.lastResponseAt) : null;
|
|
15978
|
+
const streamState = {
|
|
15979
|
+
startedAtMs,
|
|
15980
|
+
lastContentResponseAtMs: Number.isFinite(lastContentResponseAtMs) ? lastContentResponseAtMs : null
|
|
15981
|
+
};
|
|
15982
|
+
const statusConfig = deps.getStructuredStreamStatusConfig?.();
|
|
15983
|
+
const effectiveLastResponseAgeMs = Object.prototype.hasOwnProperty.call(options, "lastResponseAgeMs") ? options.lastResponseAgeMs : statusConfig ? getVisibleStreamLastContentResponseAgeMs(streamState, nowMs, statusConfig) : null;
|
|
15727
15984
|
const statusText = formatStreamRuntimeStatus(
|
|
15728
15985
|
Math.max(0, nowMs - startedAtMs),
|
|
15729
|
-
|
|
15986
|
+
effectiveLastResponseAgeMs,
|
|
15730
15987
|
turnState.statusNote
|
|
15731
15988
|
);
|
|
15732
15989
|
if (turnState.lastStatusText === statusText) return;
|
|
@@ -16889,6 +17146,7 @@ function getMirrorStructuredStreamStatusConfig() {
|
|
|
16889
17146
|
var MIRROR_FEEDBACK = createMirrorFeedbackController({
|
|
16890
17147
|
getAdapter: (channelType) => getState().adapters.get(channelType) || null,
|
|
16891
17148
|
getThreadTitle: (threadId) => getDesktopThreadTitle(threadId),
|
|
17149
|
+
getStructuredStreamStatusConfig: getMirrorStructuredStreamStatusConfig,
|
|
16892
17150
|
nowIso: nowIso3,
|
|
16893
17151
|
eventBatchLimit: MIRROR_EVENT_BATCH_LIMIT,
|
|
16894
17152
|
deliverResponse
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-to-im",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.48",
|
|
4
4
|
"description": "Installable Codex-to-IM bridge with local setup UI and background service",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/zhangle1987/codex-to-im#readme",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@larksuiteoapi/node-sdk": "^1.59.0",
|
|
44
|
-
"@openai/codex-sdk": "^0.
|
|
44
|
+
"@openai/codex-sdk": "^0.130.0",
|
|
45
45
|
"markdown-it": "^14.1.1",
|
|
46
46
|
"qrcode": "^1.5.4",
|
|
47
47
|
"ws": "^8.18.0"
|