codex-to-im 1.0.60 → 1.0.61
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 +238 -105
- package/dist/ui-server.mjs +117 -81
- package/package.json +1 -1
package/dist/daemon.mjs
CHANGED
|
@@ -324,9 +324,9 @@ __export(codex_provider_exports, {
|
|
|
324
324
|
CodexProvider: () => CodexProvider,
|
|
325
325
|
mapCodexUsage: () => mapCodexUsage
|
|
326
326
|
});
|
|
327
|
-
import
|
|
327
|
+
import fs17 from "node:fs";
|
|
328
328
|
import os4 from "node:os";
|
|
329
|
-
import
|
|
329
|
+
import path18 from "node:path";
|
|
330
330
|
function isRecord(value) {
|
|
331
331
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
332
332
|
}
|
|
@@ -543,13 +543,13 @@ var init_codex_provider = __esm({
|
|
|
543
543
|
{ type: "text", text: params.prompt }
|
|
544
544
|
];
|
|
545
545
|
for (const file of imageFiles) {
|
|
546
|
-
if (file.filePath &&
|
|
546
|
+
if (file.filePath && fs17.existsSync(file.filePath)) {
|
|
547
547
|
parts.push({ type: "local_image", path: file.filePath });
|
|
548
548
|
continue;
|
|
549
549
|
}
|
|
550
550
|
const ext = MIME_EXT[file.type] || ".png";
|
|
551
|
-
const tmpPath =
|
|
552
|
-
|
|
551
|
+
const tmpPath = path18.join(os4.tmpdir(), `cti-img-${Date.now()}-${Math.random().toString(36).slice(2)}${ext}`);
|
|
552
|
+
fs17.writeFileSync(tmpPath, Buffer.from(file.data, "base64"));
|
|
553
553
|
tempFiles.push(tmpPath);
|
|
554
554
|
parts.push({ type: "local_image", path: tmpPath });
|
|
555
555
|
}
|
|
@@ -715,7 +715,7 @@ var init_codex_provider = __esm({
|
|
|
715
715
|
} finally {
|
|
716
716
|
for (const tmp of tempFiles) {
|
|
717
717
|
try {
|
|
718
|
-
|
|
718
|
+
fs17.unlinkSync(tmp);
|
|
719
719
|
} catch {
|
|
720
720
|
}
|
|
721
721
|
}
|
|
@@ -845,9 +845,9 @@ var init_codex_provider = __esm({
|
|
|
845
845
|
});
|
|
846
846
|
|
|
847
847
|
// src/main.ts
|
|
848
|
-
import
|
|
849
|
-
import
|
|
850
|
-
import
|
|
848
|
+
import fs18 from "node:fs";
|
|
849
|
+
import path19 from "node:path";
|
|
850
|
+
import crypto11 from "node:crypto";
|
|
851
851
|
|
|
852
852
|
// src/lib/bridge/context.ts
|
|
853
853
|
var CONTEXT_KEY = "__bridge_context__";
|
|
@@ -3286,20 +3286,20 @@ ${trimmedResponse}`;
|
|
|
3286
3286
|
buffer = Buffer.concat(chunks);
|
|
3287
3287
|
} catch (streamErr) {
|
|
3288
3288
|
console.warn("[feishu-adapter] Stream read failed, falling back to writeFile:", streamErr instanceof Error ? streamErr.message : streamErr);
|
|
3289
|
-
const
|
|
3289
|
+
const fs19 = await import("fs");
|
|
3290
3290
|
const os5 = await import("os");
|
|
3291
|
-
const
|
|
3292
|
-
const tmpPath =
|
|
3291
|
+
const path20 = await import("path");
|
|
3292
|
+
const tmpPath = path20.join(os5.tmpdir(), `feishu-dl-${crypto3.randomUUID()}`);
|
|
3293
3293
|
try {
|
|
3294
3294
|
await res.writeFile(tmpPath);
|
|
3295
|
-
buffer =
|
|
3295
|
+
buffer = fs19.readFileSync(tmpPath);
|
|
3296
3296
|
if (buffer.length > MAX_FILE_SIZE) {
|
|
3297
3297
|
console.warn(`[feishu-adapter] Resource too large (>${MAX_FILE_SIZE} bytes), key: ${fileKey}`);
|
|
3298
3298
|
return null;
|
|
3299
3299
|
}
|
|
3300
3300
|
} finally {
|
|
3301
3301
|
try {
|
|
3302
|
-
|
|
3302
|
+
fs19.unlinkSync(tmpPath);
|
|
3303
3303
|
} catch {
|
|
3304
3304
|
}
|
|
3305
3305
|
}
|
|
@@ -10837,8 +10837,10 @@ var IGNORED_RESPONSE_ITEM_TYPES = /* @__PURE__ */ new Set([
|
|
|
10837
10837
|
"web_search_call"
|
|
10838
10838
|
]);
|
|
10839
10839
|
var IGNORED_TOP_LEVEL_TYPES = /* @__PURE__ */ new Set([
|
|
10840
|
+
"compacted",
|
|
10840
10841
|
"session_meta",
|
|
10841
|
-
"turn_context"
|
|
10842
|
+
"turn_context",
|
|
10843
|
+
"world_state"
|
|
10842
10844
|
]);
|
|
10843
10845
|
var TERMINAL_COMPLETION_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
10844
10846
|
"task_complete",
|
|
@@ -10865,6 +10867,10 @@ function extractTerminalCompletionText(payload) {
|
|
|
10865
10867
|
}
|
|
10866
10868
|
return "";
|
|
10867
10869
|
}
|
|
10870
|
+
function isSyntheticDesktopUserContext(text2) {
|
|
10871
|
+
const normalized = text2.trim();
|
|
10872
|
+
return normalized.startsWith("<environment_context>") && normalized.endsWith("</environment_context>");
|
|
10873
|
+
}
|
|
10868
10874
|
function isIgnoredMirrorLineKind(line) {
|
|
10869
10875
|
if (isSessionEventLine(line)) {
|
|
10870
10876
|
const payloadType = typeof line.payload?.type === "string" ? line.payload.type.trim() : "";
|
|
@@ -11177,7 +11183,7 @@ function pushDesktopMirrorEventRecord(records, parsed, rawLine, activeTurnId) {
|
|
|
11177
11183
|
}
|
|
11178
11184
|
if (parsed.payload?.type === "user_message") {
|
|
11179
11185
|
const text2 = extractNormalizedStructuredText(parsed.payload.message);
|
|
11180
|
-
if (!text2) return true;
|
|
11186
|
+
if (!text2 || isSyntheticDesktopUserContext(text2)) return true;
|
|
11181
11187
|
records.push({
|
|
11182
11188
|
signature,
|
|
11183
11189
|
type: "message",
|
|
@@ -11234,7 +11240,7 @@ function pushDesktopMirrorResponseRecord(records, parsed, rawLine, activeTurnId,
|
|
|
11234
11240
|
}
|
|
11235
11241
|
if (parsed.payload?.type === "message" && parsed.payload.role === "user") {
|
|
11236
11242
|
const text2 = extractDesktopMessageText(parsed);
|
|
11237
|
-
if (!text2) return true;
|
|
11243
|
+
if (!text2 || isSyntheticDesktopUserContext(text2)) return true;
|
|
11238
11244
|
const previous = records.at(-1);
|
|
11239
11245
|
if (previous?.type === "message" && previous.role === "user" && previous.content === text2 && previous.turnId === (activeTurnId || void 0)) {
|
|
11240
11246
|
return true;
|
|
@@ -11249,6 +11255,9 @@ function pushDesktopMirrorResponseRecord(records, parsed, rawLine, activeTurnId,
|
|
|
11249
11255
|
});
|
|
11250
11256
|
return true;
|
|
11251
11257
|
}
|
|
11258
|
+
if (parsed.payload?.type === "message") {
|
|
11259
|
+
return true;
|
|
11260
|
+
}
|
|
11252
11261
|
if (parsed.payload?.type === "tool_search_call") {
|
|
11253
11262
|
const toolId = extractNormalizedFreeText(parsed.payload.call_id) || signature;
|
|
11254
11263
|
records.push({
|
|
@@ -13165,6 +13174,10 @@ function filterSuppressedMirrorRecords(store, sessionId, records, config2, nowMs
|
|
|
13165
13174
|
break;
|
|
13166
13175
|
}
|
|
13167
13176
|
if (record.type === "message" && record.role === "user") {
|
|
13177
|
+
if (isSyntheticDesktopUserContext(record.content || "")) {
|
|
13178
|
+
handled = true;
|
|
13179
|
+
break;
|
|
13180
|
+
}
|
|
13168
13181
|
if (suppression.promptText && normalizedContent === suppression.promptText) {
|
|
13169
13182
|
suppression.awaitingPromptMatch = false;
|
|
13170
13183
|
suppression.droppingTurn = true;
|
|
@@ -16677,6 +16690,44 @@ async function runMirrorReconcileBatch(deps) {
|
|
|
16677
16690
|
|
|
16678
16691
|
// src/lib/bridge/mirror-runtime.ts
|
|
16679
16692
|
function createMirrorRuntime(getState2, options, deps) {
|
|
16693
|
+
function isAtOrBefore(timestamp, boundary) {
|
|
16694
|
+
if (!timestamp) return true;
|
|
16695
|
+
const timestampMs = Date.parse(timestamp);
|
|
16696
|
+
const boundaryMs = Date.parse(boundary);
|
|
16697
|
+
if (Number.isFinite(timestampMs) && Number.isFinite(boundaryMs)) {
|
|
16698
|
+
return timestampMs <= boundaryMs;
|
|
16699
|
+
}
|
|
16700
|
+
return timestamp <= boundary;
|
|
16701
|
+
}
|
|
16702
|
+
function discardClaimedMirrorTurn(subscription, routeResult) {
|
|
16703
|
+
if (!routeResult.terminalClaimed) return;
|
|
16704
|
+
const claimedTurnId = routeResult.claimedTurnId;
|
|
16705
|
+
if (claimedTurnId) {
|
|
16706
|
+
const claimedStreamKey = buildMirrorStreamKey(subscription.sessionId, claimedTurnId, "");
|
|
16707
|
+
subscription.bufferedRecords = subscription.bufferedRecords.filter(
|
|
16708
|
+
(record) => record.turnId !== claimedTurnId
|
|
16709
|
+
);
|
|
16710
|
+
subscription.pendingDeliveries = subscription.pendingDeliveries.filter(
|
|
16711
|
+
(turn) => turn.streamKey !== claimedStreamKey
|
|
16712
|
+
);
|
|
16713
|
+
if (subscription.pendingTurn?.turnId === claimedTurnId) {
|
|
16714
|
+
deps.stopMirrorStreaming(subscription, "interrupted");
|
|
16715
|
+
subscription.pendingTurn = null;
|
|
16716
|
+
}
|
|
16717
|
+
}
|
|
16718
|
+
const claimedAt = routeResult.claimedAt;
|
|
16719
|
+
if (!claimedAt) return;
|
|
16720
|
+
const retainedAtOrBeforeClaim = [
|
|
16721
|
+
...subscription.bufferedRecords.map((record) => record.timestamp),
|
|
16722
|
+
...subscription.pendingDeliveries.map((turn) => turn.timestamp),
|
|
16723
|
+
...routeResult.unclaimed.map((record) => record.timestamp),
|
|
16724
|
+
...subscription.pendingTurn ? [subscription.pendingTurn.lastActivityAt] : []
|
|
16725
|
+
].some((timestamp) => isAtOrBefore(timestamp, claimedAt));
|
|
16726
|
+
if (retainedAtOrBeforeClaim) return;
|
|
16727
|
+
if (!subscription.lastDeliveredAt || !isAtOrBefore(claimedAt, subscription.lastDeliveredAt)) {
|
|
16728
|
+
subscription.lastDeliveredAt = claimedAt;
|
|
16729
|
+
}
|
|
16730
|
+
}
|
|
16680
16731
|
function closeMirrorWatcher(subscription) {
|
|
16681
16732
|
if (subscription.watcher) {
|
|
16682
16733
|
try {
|
|
@@ -16864,7 +16915,14 @@ function createMirrorRuntime(getState2, options, deps) {
|
|
|
16864
16915
|
`[bridge-manager] Unhandled desktop mirror event for thread ${subscription.threadId}: ${kind}`
|
|
16865
16916
|
);
|
|
16866
16917
|
}
|
|
16867
|
-
const routeResult = deliverableRecords.length > 0 && deps.routeDesktopRecords ? await deps.routeDesktopRecords(subscription.sessionId, subscription.threadId, deliverableRecords) : {
|
|
16918
|
+
const routeResult = deliverableRecords.length > 0 && deps.routeDesktopRecords ? await deps.routeDesktopRecords(subscription.sessionId, subscription.threadId, deliverableRecords) : {
|
|
16919
|
+
claimed: [],
|
|
16920
|
+
unclaimed: deliverableRecords,
|
|
16921
|
+
terminalClaimed: false,
|
|
16922
|
+
claimedTurnId: null,
|
|
16923
|
+
claimedAt: null
|
|
16924
|
+
};
|
|
16925
|
+
discardClaimedMirrorTurn(subscription, routeResult);
|
|
16868
16926
|
const mirrorRecords = routeResult.unclaimed;
|
|
16869
16927
|
if (mirrorRecords.length > 0) {
|
|
16870
16928
|
deps.observeSessionHealthRecords(subscription.sessionId, subscription.threadId, mirrorRecords);
|
|
@@ -17930,7 +17988,9 @@ async function routeDesktopRecords(sessionId, desktopThreadId, records, coordina
|
|
|
17930
17988
|
return {
|
|
17931
17989
|
claimed: [],
|
|
17932
17990
|
unclaimed: records,
|
|
17933
|
-
terminalClaimed: false
|
|
17991
|
+
terminalClaimed: false,
|
|
17992
|
+
claimedTurnId: null,
|
|
17993
|
+
claimedAt: null
|
|
17934
17994
|
};
|
|
17935
17995
|
}
|
|
17936
17996
|
const claim = await coordinator.claimDesktopTerminal(
|
|
@@ -17940,7 +18000,9 @@ async function routeDesktopRecords(sessionId, desktopThreadId, records, coordina
|
|
|
17940
18000
|
return {
|
|
17941
18001
|
claimed: [],
|
|
17942
18002
|
unclaimed: records,
|
|
17943
|
-
terminalClaimed: false
|
|
18003
|
+
terminalClaimed: false,
|
|
18004
|
+
claimedTurnId: null,
|
|
18005
|
+
claimedAt: null
|
|
17944
18006
|
};
|
|
17945
18007
|
}
|
|
17946
18008
|
const claimedTurnId = terminalRecord.turnId;
|
|
@@ -17949,7 +18011,9 @@ async function routeDesktopRecords(sessionId, desktopThreadId, records, coordina
|
|
|
17949
18011
|
return {
|
|
17950
18012
|
claimed,
|
|
17951
18013
|
unclaimed: records.filter((record) => !claimedSet.has(record.signature)),
|
|
17952
|
-
terminalClaimed: true
|
|
18014
|
+
terminalClaimed: true,
|
|
18015
|
+
claimedTurnId: claimedTurnId || null,
|
|
18016
|
+
claimedAt: terminalRecord.timestamp || null
|
|
17953
18017
|
};
|
|
17954
18018
|
}
|
|
17955
18019
|
|
|
@@ -18579,40 +18643,76 @@ function persistSdkSessionUpdate(sessionId, sdkSessionId, hasError) {
|
|
|
18579
18643
|
}
|
|
18580
18644
|
|
|
18581
18645
|
// src/store.ts
|
|
18646
|
+
import fs13 from "node:fs";
|
|
18647
|
+
import path15 from "node:path";
|
|
18648
|
+
import crypto10 from "node:crypto";
|
|
18649
|
+
|
|
18650
|
+
// src/atomic-file.ts
|
|
18651
|
+
import crypto9 from "node:crypto";
|
|
18582
18652
|
import fs12 from "node:fs";
|
|
18583
18653
|
import path14 from "node:path";
|
|
18584
|
-
|
|
18585
|
-
var
|
|
18586
|
-
|
|
18587
|
-
|
|
18588
|
-
|
|
18589
|
-
|
|
18590
|
-
|
|
18591
|
-
|
|
18592
|
-
|
|
18593
|
-
|
|
18594
|
-
|
|
18595
|
-
|
|
18596
|
-
|
|
18654
|
+
var RETRYABLE_RENAME_CODES = /* @__PURE__ */ new Set(["EACCES", "EBUSY", "EPERM"]);
|
|
18655
|
+
var WAIT_ARRAY2 = new Int32Array(new SharedArrayBuffer(4));
|
|
18656
|
+
function defaultSleepSync(delayMs) {
|
|
18657
|
+
Atomics.wait(WAIT_ARRAY2, 0, 0, Math.max(1, delayMs));
|
|
18658
|
+
}
|
|
18659
|
+
function isRetryableRenameError(error) {
|
|
18660
|
+
return RETRYABLE_RENAME_CODES.has(error?.code || "");
|
|
18661
|
+
}
|
|
18662
|
+
function renameFileWithRetrySync(source, destination, options = {}) {
|
|
18663
|
+
const maxAttempts = Math.max(1, options.maxAttempts ?? 8);
|
|
18664
|
+
const baseDelayMs = Math.max(1, options.baseDelayMs ?? 15);
|
|
18665
|
+
const renameSync = options.renameSync ?? fs12.renameSync;
|
|
18666
|
+
const sleepSync2 = options.sleepSync ?? defaultSleepSync;
|
|
18667
|
+
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
18668
|
+
try {
|
|
18669
|
+
renameSync(source, destination);
|
|
18670
|
+
return;
|
|
18671
|
+
} catch (error) {
|
|
18672
|
+
if (!isRetryableRenameError(error) || attempt === maxAttempts - 1) {
|
|
18673
|
+
throw error;
|
|
18674
|
+
}
|
|
18675
|
+
sleepSync2(Math.min(250, baseDelayMs * 2 ** attempt));
|
|
18676
|
+
}
|
|
18677
|
+
}
|
|
18597
18678
|
}
|
|
18598
|
-
function
|
|
18599
|
-
|
|
18679
|
+
function atomicWriteFileSync(filePath, data) {
|
|
18680
|
+
fs12.mkdirSync(path14.dirname(filePath), { recursive: true });
|
|
18681
|
+
const tmpPath = `${filePath}.${process.pid}.${crypto9.randomUUID()}.tmp`;
|
|
18600
18682
|
try {
|
|
18601
|
-
fs12.writeFileSync(
|
|
18602
|
-
|
|
18683
|
+
fs12.writeFileSync(tmpPath, data, "utf-8");
|
|
18684
|
+
renameFileWithRetrySync(tmpPath, filePath);
|
|
18603
18685
|
} finally {
|
|
18604
18686
|
try {
|
|
18605
|
-
fs12.rmSync(
|
|
18687
|
+
fs12.rmSync(tmpPath, { force: true });
|
|
18606
18688
|
} catch {
|
|
18607
18689
|
}
|
|
18608
18690
|
}
|
|
18609
18691
|
}
|
|
18692
|
+
|
|
18693
|
+
// src/store.ts
|
|
18694
|
+
var DATA_DIR2 = path15.join(CTI_HOME, "data");
|
|
18695
|
+
var MESSAGES_DIR = path15.join(DATA_DIR2, "messages");
|
|
18696
|
+
var SESSIONS_PATH = path15.join(DATA_DIR2, "sessions.json");
|
|
18697
|
+
var BINDINGS_PATH = path15.join(DATA_DIR2, "bindings.json");
|
|
18698
|
+
var PERMISSIONS_PATH = path15.join(DATA_DIR2, "permissions.json");
|
|
18699
|
+
var OFFSETS_PATH = path15.join(DATA_DIR2, "offsets.json");
|
|
18700
|
+
var DEDUP_PATH = path15.join(DATA_DIR2, "dedup.json");
|
|
18701
|
+
var AUDIT_PATH = path15.join(DATA_DIR2, "audit.json");
|
|
18702
|
+
var DEFAULT_DEDUP_TTL_MS = 5 * 60 * 1e3;
|
|
18703
|
+
var INBOUND_DEDUP_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
18704
|
+
function ensureDir2(dir) {
|
|
18705
|
+
fs13.mkdirSync(dir, { recursive: true });
|
|
18706
|
+
}
|
|
18707
|
+
function atomicWrite2(filePath, data) {
|
|
18708
|
+
atomicWriteFileSync(filePath, data);
|
|
18709
|
+
}
|
|
18610
18710
|
function dedupTtlMs(key) {
|
|
18611
18711
|
return key.startsWith("inbound:") ? INBOUND_DEDUP_TTL_MS : DEFAULT_DEDUP_TTL_MS;
|
|
18612
18712
|
}
|
|
18613
18713
|
function readJson2(filePath, fallback) {
|
|
18614
18714
|
try {
|
|
18615
|
-
const raw =
|
|
18715
|
+
const raw = fs13.readFileSync(filePath, "utf-8");
|
|
18616
18716
|
return JSON.parse(raw);
|
|
18617
18717
|
} catch (error) {
|
|
18618
18718
|
if (error.code === "ENOENT") return fallback;
|
|
@@ -18623,7 +18723,7 @@ function writeJson(filePath, data) {
|
|
|
18623
18723
|
atomicWrite2(filePath, JSON.stringify(data, null, 2));
|
|
18624
18724
|
}
|
|
18625
18725
|
function uuid() {
|
|
18626
|
-
return
|
|
18726
|
+
return crypto10.randomUUID();
|
|
18627
18727
|
}
|
|
18628
18728
|
function now() {
|
|
18629
18729
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -18786,14 +18886,14 @@ var JsonFileStore = class {
|
|
|
18786
18886
|
}
|
|
18787
18887
|
persistMessages(sessionId) {
|
|
18788
18888
|
const msgs = this.messages.get(sessionId) || [];
|
|
18789
|
-
writeJson(
|
|
18889
|
+
writeJson(path15.join(MESSAGES_DIR, `${sessionId}.json`), msgs);
|
|
18790
18890
|
}
|
|
18791
18891
|
loadMessages(sessionId) {
|
|
18792
18892
|
if (this.messages.has(sessionId)) {
|
|
18793
18893
|
return this.messages.get(sessionId);
|
|
18794
18894
|
}
|
|
18795
18895
|
const msgs = readJson2(
|
|
18796
|
-
|
|
18896
|
+
path15.join(MESSAGES_DIR, `${sessionId}.json`),
|
|
18797
18897
|
[]
|
|
18798
18898
|
);
|
|
18799
18899
|
this.messages.set(sessionId, msgs);
|
|
@@ -18816,7 +18916,7 @@ var JsonFileStore = class {
|
|
|
18816
18916
|
});
|
|
18817
18917
|
}
|
|
18818
18918
|
mutateMessages(sessionId, mutation) {
|
|
18819
|
-
const messagePath =
|
|
18919
|
+
const messagePath = path15.join(MESSAGES_DIR, `${sessionId}.json`);
|
|
18820
18920
|
return withFileLock(messagePath, () => {
|
|
18821
18921
|
const messages = readJson2(messagePath, []);
|
|
18822
18922
|
this.messages.set(sessionId, messages);
|
|
@@ -18975,7 +19075,7 @@ var JsonFileStore = class {
|
|
|
18975
19075
|
});
|
|
18976
19076
|
}
|
|
18977
19077
|
deleteSession(sessionId) {
|
|
18978
|
-
const messagePath =
|
|
19078
|
+
const messagePath = path15.join(MESSAGES_DIR, `${sessionId}.json`);
|
|
18979
19079
|
withFileLocks([SESSIONS_PATH, BINDINGS_PATH, messagePath], () => {
|
|
18980
19080
|
this.reloadSessions();
|
|
18981
19081
|
this.reloadBindings();
|
|
@@ -18987,7 +19087,7 @@ var JsonFileStore = class {
|
|
|
18987
19087
|
}
|
|
18988
19088
|
this.messages.delete(sessionId);
|
|
18989
19089
|
try {
|
|
18990
|
-
|
|
19090
|
+
fs13.rmSync(messagePath, { force: true });
|
|
18991
19091
|
} catch {
|
|
18992
19092
|
}
|
|
18993
19093
|
this.persistSessions();
|
|
@@ -19001,7 +19101,7 @@ var JsonFileStore = class {
|
|
|
19001
19101
|
});
|
|
19002
19102
|
}
|
|
19003
19103
|
getMessages(sessionId, opts) {
|
|
19004
|
-
const messagePath =
|
|
19104
|
+
const messagePath = path15.join(MESSAGES_DIR, `${sessionId}.json`);
|
|
19005
19105
|
const msgs = readJson2(messagePath, []);
|
|
19006
19106
|
this.messages.set(sessionId, msgs);
|
|
19007
19107
|
if (opts?.limit && opts.limit > 0) {
|
|
@@ -19242,8 +19342,8 @@ var PendingPermissions = class {
|
|
|
19242
19342
|
};
|
|
19243
19343
|
|
|
19244
19344
|
// src/logger.ts
|
|
19245
|
-
import
|
|
19246
|
-
import
|
|
19345
|
+
import fs14 from "node:fs";
|
|
19346
|
+
import path16 from "node:path";
|
|
19247
19347
|
import { inspect as inspect2 } from "node:util";
|
|
19248
19348
|
var MASK_PATTERNS = [
|
|
19249
19349
|
/(?:token|secret|password|api_key)["']?\s*[:=]\s*["']?([^\s"',]+)/gi,
|
|
@@ -19261,8 +19361,8 @@ function maskSecrets(text2) {
|
|
|
19261
19361
|
}
|
|
19262
19362
|
return result;
|
|
19263
19363
|
}
|
|
19264
|
-
var LOG_DIR =
|
|
19265
|
-
var LOG_PATH =
|
|
19364
|
+
var LOG_DIR = path16.join(CTI_HOME, "logs");
|
|
19365
|
+
var LOG_PATH = path16.join(LOG_DIR, "bridge.log");
|
|
19266
19366
|
var MAX_LOG_SIZE = 10 * 1024 * 1024;
|
|
19267
19367
|
var MAX_ROTATED = 3;
|
|
19268
19368
|
var logStream = null;
|
|
@@ -19283,11 +19383,11 @@ function formatLogArg(value) {
|
|
|
19283
19383
|
return String(value);
|
|
19284
19384
|
}
|
|
19285
19385
|
function openLogStream() {
|
|
19286
|
-
return
|
|
19386
|
+
return fs14.createWriteStream(LOG_PATH, { flags: "a" });
|
|
19287
19387
|
}
|
|
19288
19388
|
function rotateIfNeeded() {
|
|
19289
19389
|
try {
|
|
19290
|
-
const stat =
|
|
19390
|
+
const stat = fs14.statSync(LOG_PATH);
|
|
19291
19391
|
if (stat.size < MAX_LOG_SIZE) return;
|
|
19292
19392
|
} catch {
|
|
19293
19393
|
return;
|
|
@@ -19297,17 +19397,17 @@ function rotateIfNeeded() {
|
|
|
19297
19397
|
logStream = null;
|
|
19298
19398
|
}
|
|
19299
19399
|
const path32 = `${LOG_PATH}.${MAX_ROTATED}`;
|
|
19300
|
-
if (
|
|
19400
|
+
if (fs14.existsSync(path32)) fs14.unlinkSync(path32);
|
|
19301
19401
|
for (let i = MAX_ROTATED - 1; i >= 1; i--) {
|
|
19302
19402
|
const src = `${LOG_PATH}.${i}`;
|
|
19303
19403
|
const dst = `${LOG_PATH}.${i + 1}`;
|
|
19304
|
-
if (
|
|
19404
|
+
if (fs14.existsSync(src)) fs14.renameSync(src, dst);
|
|
19305
19405
|
}
|
|
19306
|
-
|
|
19406
|
+
fs14.renameSync(LOG_PATH, `${LOG_PATH}.1`);
|
|
19307
19407
|
logStream = openLogStream();
|
|
19308
19408
|
}
|
|
19309
19409
|
function setupLogger() {
|
|
19310
|
-
|
|
19410
|
+
fs14.mkdirSync(LOG_DIR, { recursive: true });
|
|
19311
19411
|
logStream = openLogStream();
|
|
19312
19412
|
const write = (level, args) => {
|
|
19313
19413
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -19323,13 +19423,13 @@ function setupLogger() {
|
|
|
19323
19423
|
}
|
|
19324
19424
|
|
|
19325
19425
|
// src/bridge-instance-lock.ts
|
|
19326
|
-
import
|
|
19327
|
-
import
|
|
19328
|
-
var runtimeDir =
|
|
19329
|
-
var bridgeInstanceLockFile =
|
|
19426
|
+
import fs15 from "node:fs";
|
|
19427
|
+
import path17 from "node:path";
|
|
19428
|
+
var runtimeDir = path17.join(CTI_HOME, "runtime");
|
|
19429
|
+
var bridgeInstanceLockFile = path17.join(runtimeDir, "bridge.instance.lock");
|
|
19330
19430
|
function readJsonFile(filePath, fallback) {
|
|
19331
19431
|
try {
|
|
19332
|
-
return JSON.parse(
|
|
19432
|
+
return JSON.parse(fs15.readFileSync(filePath, "utf-8"));
|
|
19333
19433
|
} catch {
|
|
19334
19434
|
return fallback;
|
|
19335
19435
|
}
|
|
@@ -19361,8 +19461,8 @@ function tryAcquireBridgeInstanceLock(options = {}) {
|
|
|
19361
19461
|
};
|
|
19362
19462
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
19363
19463
|
try {
|
|
19364
|
-
|
|
19365
|
-
|
|
19464
|
+
fs15.mkdirSync(path17.dirname(filePath), { recursive: true });
|
|
19465
|
+
fs15.writeFileSync(filePath, JSON.stringify(payload, null, 2), { encoding: "utf-8", flag: "wx" });
|
|
19366
19466
|
return { acquired: true };
|
|
19367
19467
|
} catch (error) {
|
|
19368
19468
|
const code2 = error.code;
|
|
@@ -19372,7 +19472,7 @@ function tryAcquireBridgeInstanceLock(options = {}) {
|
|
|
19372
19472
|
return { acquired: false, holderPid: existing2.pid };
|
|
19373
19473
|
}
|
|
19374
19474
|
try {
|
|
19375
|
-
|
|
19475
|
+
fs15.unlinkSync(filePath);
|
|
19376
19476
|
} catch {
|
|
19377
19477
|
}
|
|
19378
19478
|
}
|
|
@@ -19387,37 +19487,46 @@ function releaseBridgeInstanceLock(filePath = bridgeInstanceLockFile, ownerPid =
|
|
|
19387
19487
|
const existing = readBridgeInstanceLock(filePath);
|
|
19388
19488
|
if (!existing) {
|
|
19389
19489
|
try {
|
|
19390
|
-
|
|
19490
|
+
fs15.unlinkSync(filePath);
|
|
19391
19491
|
} catch {
|
|
19392
19492
|
}
|
|
19393
19493
|
return;
|
|
19394
19494
|
}
|
|
19395
19495
|
if (existing.pid !== ownerPid) return;
|
|
19396
19496
|
try {
|
|
19397
|
-
|
|
19497
|
+
fs15.unlinkSync(filePath);
|
|
19398
19498
|
} catch {
|
|
19399
19499
|
}
|
|
19400
19500
|
}
|
|
19401
19501
|
|
|
19402
|
-
// src/
|
|
19403
|
-
|
|
19404
|
-
|
|
19405
|
-
var PID_FILE = path18.join(RUNTIME_DIR, "bridge.pid");
|
|
19406
|
-
async function resolveProvider() {
|
|
19407
|
-
const { CodexProvider: CodexProvider2 } = await Promise.resolve().then(() => (init_codex_provider(), codex_provider_exports));
|
|
19408
|
-
return new CodexProvider2();
|
|
19409
|
-
}
|
|
19410
|
-
function writeStatus(info) {
|
|
19411
|
-
fs16.mkdirSync(RUNTIME_DIR, { recursive: true });
|
|
19502
|
+
// src/runtime-status.ts
|
|
19503
|
+
import fs16 from "node:fs";
|
|
19504
|
+
function writeRuntimeStatus(filePath, info, options = {}) {
|
|
19412
19505
|
let existing = {};
|
|
19413
19506
|
try {
|
|
19414
|
-
existing = JSON.parse(fs16.readFileSync(
|
|
19507
|
+
existing = JSON.parse(fs16.readFileSync(filePath, "utf-8"));
|
|
19415
19508
|
} catch {
|
|
19416
19509
|
}
|
|
19510
|
+
const existingRunId = typeof existing.runId === "string" ? existing.runId : "";
|
|
19511
|
+
if (options.expectedRunId && existingRunId && existingRunId !== options.expectedRunId && options.allowRunIdTakeover !== true) {
|
|
19512
|
+
return false;
|
|
19513
|
+
}
|
|
19417
19514
|
const merged = { ...existing, ...info };
|
|
19418
|
-
|
|
19419
|
-
|
|
19420
|
-
|
|
19515
|
+
atomicWriteFileSync(filePath, JSON.stringify(merged, null, 2));
|
|
19516
|
+
return true;
|
|
19517
|
+
}
|
|
19518
|
+
|
|
19519
|
+
// src/main.ts
|
|
19520
|
+
var RUNTIME_DIR = path19.join(CTI_HOME, "runtime");
|
|
19521
|
+
var STATUS_FILE = path19.join(RUNTIME_DIR, "status.json");
|
|
19522
|
+
var PID_FILE = path19.join(RUNTIME_DIR, "bridge.pid");
|
|
19523
|
+
var runId = crypto11.randomUUID();
|
|
19524
|
+
async function resolveProvider() {
|
|
19525
|
+
const { CodexProvider: CodexProvider2 } = await Promise.resolve().then(() => (init_codex_provider(), codex_provider_exports));
|
|
19526
|
+
return new CodexProvider2();
|
|
19527
|
+
}
|
|
19528
|
+
function writeStatus(info, options = {}) {
|
|
19529
|
+
return writeRuntimeStatus(STATUS_FILE, info, options);
|
|
19421
19530
|
}
|
|
19422
19531
|
function getRunningChannels() {
|
|
19423
19532
|
return getStatus().adapters.map((adapter) => adapter.channelType).sort();
|
|
@@ -19429,10 +19538,6 @@ async function main() {
|
|
|
19429
19538
|
const lockState = tryAcquireBridgeInstanceLock();
|
|
19430
19539
|
if (!lockState.acquired) {
|
|
19431
19540
|
const holderPid = lockState.holderPid;
|
|
19432
|
-
writeStatus({
|
|
19433
|
-
running: true,
|
|
19434
|
-
...Number.isFinite(holderPid) && holderPid ? { pid: holderPid } : {}
|
|
19435
|
-
});
|
|
19436
19541
|
console.log(
|
|
19437
19542
|
`[codex-to-im] Another bridge daemon is already running${holderPid ? ` (PID: ${holderPid})` : ""}. Exiting duplicate launcher.`
|
|
19438
19543
|
);
|
|
@@ -19444,9 +19549,15 @@ async function main() {
|
|
|
19444
19549
|
releaseBridgeInstanceLock(void 0, process.pid);
|
|
19445
19550
|
instanceLockHeld = false;
|
|
19446
19551
|
};
|
|
19552
|
+
writeStatus({
|
|
19553
|
+
running: false,
|
|
19554
|
+
pid: process.pid,
|
|
19555
|
+
runId,
|
|
19556
|
+
channels: [],
|
|
19557
|
+
adapters: []
|
|
19558
|
+
}, { expectedRunId: runId, allowRunIdTakeover: true });
|
|
19447
19559
|
const config2 = loadConfig();
|
|
19448
19560
|
setupLogger();
|
|
19449
|
-
const runId = crypto10.randomUUID();
|
|
19450
19561
|
console.log(`[codex-to-im] Starting bridge (run_id: ${runId})`);
|
|
19451
19562
|
const settings = configToSettings(config2);
|
|
19452
19563
|
const store = new JsonFileStore(settings, { dynamicSettings: true });
|
|
@@ -19462,8 +19573,8 @@ async function main() {
|
|
|
19462
19573
|
permissions: gateway,
|
|
19463
19574
|
lifecycle: {
|
|
19464
19575
|
onBridgeStart: () => {
|
|
19465
|
-
|
|
19466
|
-
|
|
19576
|
+
fs18.mkdirSync(RUNTIME_DIR, { recursive: true });
|
|
19577
|
+
fs18.writeFileSync(PID_FILE, String(process.pid), "utf-8");
|
|
19467
19578
|
const channels = getRunningChannels();
|
|
19468
19579
|
writeStatus({
|
|
19469
19580
|
running: true,
|
|
@@ -19472,7 +19583,7 @@ async function main() {
|
|
|
19472
19583
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19473
19584
|
channels,
|
|
19474
19585
|
adapters: getAdapterStatuses()
|
|
19475
|
-
});
|
|
19586
|
+
}, { expectedRunId: runId });
|
|
19476
19587
|
console.log(`[codex-to-im] Bridge started (PID: ${process.pid}, channels: ${channels.join(", ")})`);
|
|
19477
19588
|
},
|
|
19478
19589
|
onBridgeAdaptersChanged: (channels) => {
|
|
@@ -19482,41 +19593,60 @@ async function main() {
|
|
|
19482
19593
|
runId,
|
|
19483
19594
|
channels,
|
|
19484
19595
|
adapters: getAdapterStatuses()
|
|
19485
|
-
});
|
|
19596
|
+
}, { expectedRunId: runId });
|
|
19486
19597
|
console.log(`[codex-to-im] Active channels updated: ${channels.join(", ") || "none"}`);
|
|
19487
19598
|
},
|
|
19488
19599
|
onBridgeStop: () => {
|
|
19489
19600
|
releaseInstanceLock();
|
|
19490
|
-
writeStatus({ running: false, channels: [], adapters: [] });
|
|
19601
|
+
writeStatus({ running: false, channels: [], adapters: [] }, { expectedRunId: runId });
|
|
19491
19602
|
console.log("[codex-to-im] Bridge stopped");
|
|
19492
19603
|
}
|
|
19493
19604
|
}
|
|
19494
19605
|
});
|
|
19495
19606
|
await start();
|
|
19496
19607
|
let shuttingDown = false;
|
|
19497
|
-
const shutdown = async (
|
|
19608
|
+
const shutdown = async (reason, exitCode = 0) => {
|
|
19498
19609
|
if (shuttingDown) return;
|
|
19499
19610
|
shuttingDown = true;
|
|
19500
|
-
const reason = signal ? `signal: ${signal}` : "shutdown requested";
|
|
19501
19611
|
console.log(`[codex-to-im] Shutting down (${reason})...`);
|
|
19502
19612
|
pendingPerms.denyAll();
|
|
19503
|
-
|
|
19504
|
-
|
|
19505
|
-
|
|
19506
|
-
|
|
19613
|
+
try {
|
|
19614
|
+
await stop();
|
|
19615
|
+
} catch (error) {
|
|
19616
|
+
console.error("[codex-to-im] Graceful bridge stop failed:", error instanceof Error ? error.stack || error.message : error);
|
|
19617
|
+
} finally {
|
|
19618
|
+
releaseInstanceLock();
|
|
19619
|
+
try {
|
|
19620
|
+
writeStatus({ running: false, lastExitReason: reason }, { expectedRunId: runId });
|
|
19621
|
+
} catch (error) {
|
|
19622
|
+
console.error("[codex-to-im] Failed to write final runtime status:", error instanceof Error ? error.message : error);
|
|
19623
|
+
}
|
|
19624
|
+
process.exit(exitCode);
|
|
19625
|
+
}
|
|
19507
19626
|
};
|
|
19508
|
-
process.on("SIGTERM", () =>
|
|
19509
|
-
|
|
19510
|
-
|
|
19627
|
+
process.on("SIGTERM", () => {
|
|
19628
|
+
void shutdown("signal: SIGTERM");
|
|
19629
|
+
});
|
|
19630
|
+
process.on("SIGINT", () => {
|
|
19631
|
+
void shutdown("signal: SIGINT");
|
|
19632
|
+
});
|
|
19633
|
+
process.on("SIGHUP", () => {
|
|
19634
|
+
void shutdown("signal: SIGHUP");
|
|
19635
|
+
});
|
|
19511
19636
|
process.on("unhandledRejection", (reason) => {
|
|
19512
19637
|
console.error("[codex-to-im] unhandledRejection:", reason instanceof Error ? reason.stack || reason.message : reason);
|
|
19513
|
-
writeStatus({
|
|
19638
|
+
writeStatus({
|
|
19639
|
+
running: true,
|
|
19640
|
+
pid: process.pid,
|
|
19641
|
+
runId,
|
|
19642
|
+
channels: getRunningChannels(),
|
|
19643
|
+
adapters: getAdapterStatuses(),
|
|
19644
|
+
lastExitReason: `unhandledRejection: ${reason instanceof Error ? reason.message : String(reason)}`
|
|
19645
|
+
}, { expectedRunId: runId });
|
|
19514
19646
|
});
|
|
19515
19647
|
process.on("uncaughtException", (err) => {
|
|
19516
19648
|
console.error("[codex-to-im] uncaughtException:", err.stack || err.message);
|
|
19517
|
-
|
|
19518
|
-
writeStatus({ running: false, lastExitReason: `uncaughtException: ${err.message}` });
|
|
19519
|
-
process.exit(1);
|
|
19649
|
+
void shutdown(`uncaughtException: ${err.message}`, 1);
|
|
19520
19650
|
});
|
|
19521
19651
|
process.on("beforeExit", (code2) => {
|
|
19522
19652
|
console.log(`[codex-to-im] beforeExit (code: ${code2})`);
|
|
@@ -19532,7 +19662,10 @@ main().catch((err) => {
|
|
|
19532
19662
|
console.error("[codex-to-im] Fatal error:", err instanceof Error ? err.stack || err.message : err);
|
|
19533
19663
|
releaseBridgeInstanceLock(void 0, process.pid);
|
|
19534
19664
|
try {
|
|
19535
|
-
writeStatus(
|
|
19665
|
+
writeStatus(
|
|
19666
|
+
{ running: false, lastExitReason: `fatal: ${err instanceof Error ? err.message : String(err)}` },
|
|
19667
|
+
{ expectedRunId: runId }
|
|
19668
|
+
);
|
|
19536
19669
|
} catch {
|
|
19537
19670
|
}
|
|
19538
19671
|
process.exit(1);
|
package/dist/ui-server.mjs
CHANGED
|
@@ -1572,10 +1572,10 @@ var require_segments = __commonJS({
|
|
|
1572
1572
|
const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled());
|
|
1573
1573
|
const nodes = buildNodes(segs);
|
|
1574
1574
|
const graph = buildGraph(nodes, version);
|
|
1575
|
-
const
|
|
1575
|
+
const path11 = dijkstra.find_path(graph.map, "start", "end");
|
|
1576
1576
|
const optimizedSegs = [];
|
|
1577
|
-
for (let i = 1; i <
|
|
1578
|
-
optimizedSegs.push(graph.table[
|
|
1577
|
+
for (let i = 1; i < path11.length - 1; i++) {
|
|
1578
|
+
optimizedSegs.push(graph.table[path11[i]].node);
|
|
1579
1579
|
}
|
|
1580
1580
|
return exports.fromArray(mergeSegments(optimizedSegs));
|
|
1581
1581
|
};
|
|
@@ -4011,7 +4011,7 @@ var require_utils2 = __commonJS({
|
|
|
4011
4011
|
// node_modules/qrcode/lib/renderer/png.js
|
|
4012
4012
|
var require_png2 = __commonJS({
|
|
4013
4013
|
"node_modules/qrcode/lib/renderer/png.js"(exports) {
|
|
4014
|
-
var
|
|
4014
|
+
var fs11 = __require("fs");
|
|
4015
4015
|
var PNG = require_png().PNG;
|
|
4016
4016
|
var Utils = require_utils2();
|
|
4017
4017
|
exports.render = function render(qrData, options) {
|
|
@@ -4052,7 +4052,7 @@ var require_png2 = __commonJS({
|
|
|
4052
4052
|
});
|
|
4053
4053
|
png.pack();
|
|
4054
4054
|
};
|
|
4055
|
-
exports.renderToFile = function renderToFile(
|
|
4055
|
+
exports.renderToFile = function renderToFile(path11, qrData, options, cb) {
|
|
4056
4056
|
if (typeof cb === "undefined") {
|
|
4057
4057
|
cb = options;
|
|
4058
4058
|
options = void 0;
|
|
@@ -4063,7 +4063,7 @@ var require_png2 = __commonJS({
|
|
|
4063
4063
|
called = true;
|
|
4064
4064
|
cb.apply(null, args);
|
|
4065
4065
|
};
|
|
4066
|
-
const stream =
|
|
4066
|
+
const stream = fs11.createWriteStream(path11);
|
|
4067
4067
|
stream.on("error", done);
|
|
4068
4068
|
stream.on("close", done);
|
|
4069
4069
|
exports.renderToFileStream(stream, qrData, options);
|
|
@@ -4125,14 +4125,14 @@ var require_utf8 = __commonJS({
|
|
|
4125
4125
|
}
|
|
4126
4126
|
return output;
|
|
4127
4127
|
};
|
|
4128
|
-
exports.renderToFile = function renderToFile(
|
|
4128
|
+
exports.renderToFile = function renderToFile(path11, qrData, options, cb) {
|
|
4129
4129
|
if (typeof cb === "undefined") {
|
|
4130
4130
|
cb = options;
|
|
4131
4131
|
options = void 0;
|
|
4132
4132
|
}
|
|
4133
|
-
const
|
|
4133
|
+
const fs11 = __require("fs");
|
|
4134
4134
|
const utf8 = exports.render(qrData, options);
|
|
4135
|
-
|
|
4135
|
+
fs11.writeFile(path11, utf8, cb);
|
|
4136
4136
|
};
|
|
4137
4137
|
}
|
|
4138
4138
|
});
|
|
@@ -4253,7 +4253,7 @@ var require_svg_tag = __commonJS({
|
|
|
4253
4253
|
return str;
|
|
4254
4254
|
}
|
|
4255
4255
|
function qrToPath(data, size, margin) {
|
|
4256
|
-
let
|
|
4256
|
+
let path11 = "";
|
|
4257
4257
|
let moveBy = 0;
|
|
4258
4258
|
let newRow = false;
|
|
4259
4259
|
let lineLength = 0;
|
|
@@ -4264,19 +4264,19 @@ var require_svg_tag = __commonJS({
|
|
|
4264
4264
|
if (data[i]) {
|
|
4265
4265
|
lineLength++;
|
|
4266
4266
|
if (!(i > 0 && col > 0 && data[i - 1])) {
|
|
4267
|
-
|
|
4267
|
+
path11 += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0);
|
|
4268
4268
|
moveBy = 0;
|
|
4269
4269
|
newRow = false;
|
|
4270
4270
|
}
|
|
4271
4271
|
if (!(col + 1 < size && data[i + 1])) {
|
|
4272
|
-
|
|
4272
|
+
path11 += svgCmd("h", lineLength);
|
|
4273
4273
|
lineLength = 0;
|
|
4274
4274
|
}
|
|
4275
4275
|
} else {
|
|
4276
4276
|
moveBy++;
|
|
4277
4277
|
}
|
|
4278
4278
|
}
|
|
4279
|
-
return
|
|
4279
|
+
return path11;
|
|
4280
4280
|
}
|
|
4281
4281
|
exports.render = function render(qrData, options, cb) {
|
|
4282
4282
|
const opts = Utils.getOptions(options);
|
|
@@ -4284,10 +4284,10 @@ var require_svg_tag = __commonJS({
|
|
|
4284
4284
|
const data = qrData.modules.data;
|
|
4285
4285
|
const qrcodesize = size + opts.margin * 2;
|
|
4286
4286
|
const bg = !opts.color.light.a ? "" : "<path " + getColorAttrib(opts.color.light, "fill") + ' d="M0 0h' + qrcodesize + "v" + qrcodesize + 'H0z"/>';
|
|
4287
|
-
const
|
|
4287
|
+
const path11 = "<path " + getColorAttrib(opts.color.dark, "stroke") + ' d="' + qrToPath(data, size, opts.margin) + '"/>';
|
|
4288
4288
|
const viewBox = 'viewBox="0 0 ' + qrcodesize + " " + qrcodesize + '"';
|
|
4289
4289
|
const width = !opts.width ? "" : 'width="' + opts.width + '" height="' + opts.width + '" ';
|
|
4290
|
-
const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg +
|
|
4290
|
+
const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path11 + "</svg>\n";
|
|
4291
4291
|
if (typeof cb === "function") {
|
|
4292
4292
|
cb(null, svgTag);
|
|
4293
4293
|
}
|
|
@@ -4301,15 +4301,15 @@ var require_svg = __commonJS({
|
|
|
4301
4301
|
"node_modules/qrcode/lib/renderer/svg.js"(exports) {
|
|
4302
4302
|
var svgTagRenderer = require_svg_tag();
|
|
4303
4303
|
exports.render = svgTagRenderer.render;
|
|
4304
|
-
exports.renderToFile = function renderToFile(
|
|
4304
|
+
exports.renderToFile = function renderToFile(path11, qrData, options, cb) {
|
|
4305
4305
|
if (typeof cb === "undefined") {
|
|
4306
4306
|
cb = options;
|
|
4307
4307
|
options = void 0;
|
|
4308
4308
|
}
|
|
4309
|
-
const
|
|
4309
|
+
const fs11 = __require("fs");
|
|
4310
4310
|
const svgTag = exports.render(qrData, options);
|
|
4311
4311
|
const xmlStr = '<?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' + svgTag;
|
|
4312
|
-
|
|
4312
|
+
fs11.writeFile(path11, xmlStr, cb);
|
|
4313
4313
|
};
|
|
4314
4314
|
}
|
|
4315
4315
|
});
|
|
@@ -4467,8 +4467,8 @@ var require_server = __commonJS({
|
|
|
4467
4467
|
cb
|
|
4468
4468
|
};
|
|
4469
4469
|
}
|
|
4470
|
-
function getTypeFromFilename(
|
|
4471
|
-
return
|
|
4470
|
+
function getTypeFromFilename(path11) {
|
|
4471
|
+
return path11.slice((path11.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
|
|
4472
4472
|
}
|
|
4473
4473
|
function getRendererFromType(type) {
|
|
4474
4474
|
switch (type) {
|
|
@@ -4532,17 +4532,17 @@ var require_server = __commonJS({
|
|
|
4532
4532
|
const renderer = getRendererFromType(params.opts.type);
|
|
4533
4533
|
return render(renderer.renderToBuffer, text2, params);
|
|
4534
4534
|
};
|
|
4535
|
-
exports.toFile = function toFile(
|
|
4536
|
-
if (typeof
|
|
4535
|
+
exports.toFile = function toFile(path11, text2, opts, cb) {
|
|
4536
|
+
if (typeof path11 !== "string" || !(typeof text2 === "string" || typeof text2 === "object")) {
|
|
4537
4537
|
throw new Error("Invalid argument");
|
|
4538
4538
|
}
|
|
4539
4539
|
if (arguments.length < 3 && !canPromise()) {
|
|
4540
4540
|
throw new Error("Too few arguments provided");
|
|
4541
4541
|
}
|
|
4542
4542
|
const params = checkParams(text2, opts, cb);
|
|
4543
|
-
const type = params.opts.type || getTypeFromFilename(
|
|
4543
|
+
const type = params.opts.type || getTypeFromFilename(path11);
|
|
4544
4544
|
const renderer = getRendererFromType(type);
|
|
4545
|
-
const renderToFile = renderer.renderToFile.bind(null,
|
|
4545
|
+
const renderToFile = renderer.renderToFile.bind(null, path11);
|
|
4546
4546
|
return render(renderToFile, text2, params);
|
|
4547
4547
|
};
|
|
4548
4548
|
exports.toFileStream = function toFileStream(stream, text2, opts) {
|
|
@@ -4566,7 +4566,7 @@ var require_lib = __commonJS({
|
|
|
4566
4566
|
|
|
4567
4567
|
// src/ui-server.ts
|
|
4568
4568
|
import http from "node:http";
|
|
4569
|
-
import
|
|
4569
|
+
import crypto9 from "node:crypto";
|
|
4570
4570
|
import net from "node:net";
|
|
4571
4571
|
import os5 from "node:os";
|
|
4572
4572
|
|
|
@@ -6438,40 +6438,76 @@ function isCodexIntegrationInstalled() {
|
|
|
6438
6438
|
}
|
|
6439
6439
|
|
|
6440
6440
|
// src/store.ts
|
|
6441
|
+
import fs7 from "node:fs";
|
|
6442
|
+
import path7 from "node:path";
|
|
6443
|
+
import crypto5 from "node:crypto";
|
|
6444
|
+
|
|
6445
|
+
// src/atomic-file.ts
|
|
6446
|
+
import crypto4 from "node:crypto";
|
|
6441
6447
|
import fs6 from "node:fs";
|
|
6442
6448
|
import path6 from "node:path";
|
|
6443
|
-
|
|
6444
|
-
var
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6449
|
+
var RETRYABLE_RENAME_CODES = /* @__PURE__ */ new Set(["EACCES", "EBUSY", "EPERM"]);
|
|
6450
|
+
var WAIT_ARRAY2 = new Int32Array(new SharedArrayBuffer(4));
|
|
6451
|
+
function defaultSleepSync(delayMs) {
|
|
6452
|
+
Atomics.wait(WAIT_ARRAY2, 0, 0, Math.max(1, delayMs));
|
|
6453
|
+
}
|
|
6454
|
+
function isRetryableRenameError(error) {
|
|
6455
|
+
return RETRYABLE_RENAME_CODES.has(error?.code || "");
|
|
6456
|
+
}
|
|
6457
|
+
function renameFileWithRetrySync(source, destination, options = {}) {
|
|
6458
|
+
const maxAttempts = Math.max(1, options.maxAttempts ?? 8);
|
|
6459
|
+
const baseDelayMs = Math.max(1, options.baseDelayMs ?? 15);
|
|
6460
|
+
const renameSync = options.renameSync ?? fs6.renameSync;
|
|
6461
|
+
const sleepSync2 = options.sleepSync ?? defaultSleepSync;
|
|
6462
|
+
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
6463
|
+
try {
|
|
6464
|
+
renameSync(source, destination);
|
|
6465
|
+
return;
|
|
6466
|
+
} catch (error) {
|
|
6467
|
+
if (!isRetryableRenameError(error) || attempt === maxAttempts - 1) {
|
|
6468
|
+
throw error;
|
|
6469
|
+
}
|
|
6470
|
+
sleepSync2(Math.min(250, baseDelayMs * 2 ** attempt));
|
|
6471
|
+
}
|
|
6472
|
+
}
|
|
6456
6473
|
}
|
|
6457
|
-
function
|
|
6458
|
-
|
|
6474
|
+
function atomicWriteFileSync(filePath, data) {
|
|
6475
|
+
fs6.mkdirSync(path6.dirname(filePath), { recursive: true });
|
|
6476
|
+
const tmpPath = `${filePath}.${process.pid}.${crypto4.randomUUID()}.tmp`;
|
|
6459
6477
|
try {
|
|
6460
|
-
fs6.writeFileSync(
|
|
6461
|
-
|
|
6478
|
+
fs6.writeFileSync(tmpPath, data, "utf-8");
|
|
6479
|
+
renameFileWithRetrySync(tmpPath, filePath);
|
|
6462
6480
|
} finally {
|
|
6463
6481
|
try {
|
|
6464
|
-
fs6.rmSync(
|
|
6482
|
+
fs6.rmSync(tmpPath, { force: true });
|
|
6465
6483
|
} catch {
|
|
6466
6484
|
}
|
|
6467
6485
|
}
|
|
6468
6486
|
}
|
|
6487
|
+
|
|
6488
|
+
// src/store.ts
|
|
6489
|
+
var DATA_DIR = path7.join(CTI_HOME, "data");
|
|
6490
|
+
var MESSAGES_DIR = path7.join(DATA_DIR, "messages");
|
|
6491
|
+
var SESSIONS_PATH = path7.join(DATA_DIR, "sessions.json");
|
|
6492
|
+
var BINDINGS_PATH = path7.join(DATA_DIR, "bindings.json");
|
|
6493
|
+
var PERMISSIONS_PATH = path7.join(DATA_DIR, "permissions.json");
|
|
6494
|
+
var OFFSETS_PATH = path7.join(DATA_DIR, "offsets.json");
|
|
6495
|
+
var DEDUP_PATH = path7.join(DATA_DIR, "dedup.json");
|
|
6496
|
+
var AUDIT_PATH = path7.join(DATA_DIR, "audit.json");
|
|
6497
|
+
var DEFAULT_DEDUP_TTL_MS = 5 * 60 * 1e3;
|
|
6498
|
+
var INBOUND_DEDUP_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
6499
|
+
function ensureDir(dir) {
|
|
6500
|
+
fs7.mkdirSync(dir, { recursive: true });
|
|
6501
|
+
}
|
|
6502
|
+
function atomicWrite(filePath, data) {
|
|
6503
|
+
atomicWriteFileSync(filePath, data);
|
|
6504
|
+
}
|
|
6469
6505
|
function dedupTtlMs(key) {
|
|
6470
6506
|
return key.startsWith("inbound:") ? INBOUND_DEDUP_TTL_MS : DEFAULT_DEDUP_TTL_MS;
|
|
6471
6507
|
}
|
|
6472
6508
|
function readJson(filePath, fallback) {
|
|
6473
6509
|
try {
|
|
6474
|
-
const raw =
|
|
6510
|
+
const raw = fs7.readFileSync(filePath, "utf-8");
|
|
6475
6511
|
return JSON.parse(raw);
|
|
6476
6512
|
} catch (error) {
|
|
6477
6513
|
if (error.code === "ENOENT") return fallback;
|
|
@@ -6482,7 +6518,7 @@ function writeJson(filePath, data) {
|
|
|
6482
6518
|
atomicWrite(filePath, JSON.stringify(data, null, 2));
|
|
6483
6519
|
}
|
|
6484
6520
|
function uuid() {
|
|
6485
|
-
return
|
|
6521
|
+
return crypto5.randomUUID();
|
|
6486
6522
|
}
|
|
6487
6523
|
function now() {
|
|
6488
6524
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -6645,14 +6681,14 @@ var JsonFileStore = class {
|
|
|
6645
6681
|
}
|
|
6646
6682
|
persistMessages(sessionId) {
|
|
6647
6683
|
const msgs = this.messages.get(sessionId) || [];
|
|
6648
|
-
writeJson(
|
|
6684
|
+
writeJson(path7.join(MESSAGES_DIR, `${sessionId}.json`), msgs);
|
|
6649
6685
|
}
|
|
6650
6686
|
loadMessages(sessionId) {
|
|
6651
6687
|
if (this.messages.has(sessionId)) {
|
|
6652
6688
|
return this.messages.get(sessionId);
|
|
6653
6689
|
}
|
|
6654
6690
|
const msgs = readJson(
|
|
6655
|
-
|
|
6691
|
+
path7.join(MESSAGES_DIR, `${sessionId}.json`),
|
|
6656
6692
|
[]
|
|
6657
6693
|
);
|
|
6658
6694
|
this.messages.set(sessionId, msgs);
|
|
@@ -6675,7 +6711,7 @@ var JsonFileStore = class {
|
|
|
6675
6711
|
});
|
|
6676
6712
|
}
|
|
6677
6713
|
mutateMessages(sessionId, mutation) {
|
|
6678
|
-
const messagePath =
|
|
6714
|
+
const messagePath = path7.join(MESSAGES_DIR, `${sessionId}.json`);
|
|
6679
6715
|
return withFileLock(messagePath, () => {
|
|
6680
6716
|
const messages = readJson(messagePath, []);
|
|
6681
6717
|
this.messages.set(sessionId, messages);
|
|
@@ -6834,7 +6870,7 @@ var JsonFileStore = class {
|
|
|
6834
6870
|
});
|
|
6835
6871
|
}
|
|
6836
6872
|
deleteSession(sessionId) {
|
|
6837
|
-
const messagePath =
|
|
6873
|
+
const messagePath = path7.join(MESSAGES_DIR, `${sessionId}.json`);
|
|
6838
6874
|
withFileLocks([SESSIONS_PATH, BINDINGS_PATH, messagePath], () => {
|
|
6839
6875
|
this.reloadSessions();
|
|
6840
6876
|
this.reloadBindings();
|
|
@@ -6846,7 +6882,7 @@ var JsonFileStore = class {
|
|
|
6846
6882
|
}
|
|
6847
6883
|
this.messages.delete(sessionId);
|
|
6848
6884
|
try {
|
|
6849
|
-
|
|
6885
|
+
fs7.rmSync(messagePath, { force: true });
|
|
6850
6886
|
} catch {
|
|
6851
6887
|
}
|
|
6852
6888
|
this.persistSessions();
|
|
@@ -6860,7 +6896,7 @@ var JsonFileStore = class {
|
|
|
6860
6896
|
});
|
|
6861
6897
|
}
|
|
6862
6898
|
getMessages(sessionId, opts) {
|
|
6863
|
-
const messagePath =
|
|
6899
|
+
const messagePath = path7.join(MESSAGES_DIR, `${sessionId}.json`);
|
|
6864
6900
|
const msgs = readJson(messagePath, []);
|
|
6865
6901
|
this.messages.set(sessionId, msgs);
|
|
6866
6902
|
if (opts?.limit && opts.limit > 0) {
|
|
@@ -7064,13 +7100,13 @@ var JsonFileStore = class {
|
|
|
7064
7100
|
|
|
7065
7101
|
// src/weixin-login.ts
|
|
7066
7102
|
var import_qrcode = __toESM(require_lib(), 1);
|
|
7067
|
-
import
|
|
7068
|
-
import
|
|
7069
|
-
import
|
|
7103
|
+
import fs9 from "node:fs";
|
|
7104
|
+
import path9 from "node:path";
|
|
7105
|
+
import crypto8 from "node:crypto";
|
|
7070
7106
|
import { spawn as spawn2 } from "node:child_process";
|
|
7071
7107
|
|
|
7072
7108
|
// src/adapters/weixin/weixin-api.ts
|
|
7073
|
-
import
|
|
7109
|
+
import crypto6 from "node:crypto";
|
|
7074
7110
|
|
|
7075
7111
|
// src/adapters/weixin/weixin-types.ts
|
|
7076
7112
|
var DEFAULT_BASE_URL = "https://ilinkai.weixin.qq.com";
|
|
@@ -7119,32 +7155,32 @@ async function pollLoginQrStatus(qrcode, baseUrl) {
|
|
|
7119
7155
|
}
|
|
7120
7156
|
|
|
7121
7157
|
// src/weixin-store.ts
|
|
7122
|
-
import
|
|
7123
|
-
import
|
|
7124
|
-
import
|
|
7125
|
-
var DATA_DIR2 =
|
|
7126
|
-
var ACCOUNTS_PATH =
|
|
7127
|
-
var CONTEXT_TOKENS_PATH =
|
|
7158
|
+
import fs8 from "node:fs";
|
|
7159
|
+
import crypto7 from "node:crypto";
|
|
7160
|
+
import path8 from "node:path";
|
|
7161
|
+
var DATA_DIR2 = path8.join(CTI_HOME, "data");
|
|
7162
|
+
var ACCOUNTS_PATH = path8.join(DATA_DIR2, "weixin-accounts.json");
|
|
7163
|
+
var CONTEXT_TOKENS_PATH = path8.join(DATA_DIR2, "weixin-context-tokens.json");
|
|
7128
7164
|
var DEFAULT_BASE_URL2 = "https://ilinkai.weixin.qq.com";
|
|
7129
7165
|
var DEFAULT_CDN_BASE_URL2 = "https://novac2c.cdn.weixin.qq.com/c2c";
|
|
7130
7166
|
function ensureDir2(dir) {
|
|
7131
|
-
|
|
7167
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
7132
7168
|
}
|
|
7133
7169
|
function atomicWrite2(filePath, data) {
|
|
7134
|
-
const tmpPath = `${filePath}.${process.pid}.${
|
|
7170
|
+
const tmpPath = `${filePath}.${process.pid}.${crypto7.randomUUID()}.tmp`;
|
|
7135
7171
|
try {
|
|
7136
|
-
|
|
7137
|
-
|
|
7172
|
+
fs8.writeFileSync(tmpPath, data, "utf-8");
|
|
7173
|
+
fs8.renameSync(tmpPath, filePath);
|
|
7138
7174
|
} finally {
|
|
7139
7175
|
try {
|
|
7140
|
-
|
|
7176
|
+
fs8.rmSync(tmpPath, { force: true });
|
|
7141
7177
|
} catch {
|
|
7142
7178
|
}
|
|
7143
7179
|
}
|
|
7144
7180
|
}
|
|
7145
7181
|
function readJson2(filePath, fallback) {
|
|
7146
7182
|
try {
|
|
7147
|
-
const raw =
|
|
7183
|
+
const raw = fs8.readFileSync(filePath, "utf-8");
|
|
7148
7184
|
return JSON.parse(raw);
|
|
7149
7185
|
} catch (error) {
|
|
7150
7186
|
if (error.code === "ENOENT") return fallback;
|
|
@@ -7236,11 +7272,11 @@ var MAX_REFRESHES = 3;
|
|
|
7236
7272
|
var QR_TTL_MS = 5 * 6e4;
|
|
7237
7273
|
var POLL_INTERVAL_MS = 3e3;
|
|
7238
7274
|
var WEB_SESSION_TTL_MS = 15 * 6e4;
|
|
7239
|
-
var RUNTIME_DIR =
|
|
7240
|
-
var HTML_PATH =
|
|
7275
|
+
var RUNTIME_DIR = path9.join(CTI_HOME, "runtime");
|
|
7276
|
+
var HTML_PATH = path9.join(RUNTIME_DIR, "weixin-login.html");
|
|
7241
7277
|
var webLoginSessions = /* @__PURE__ */ new Map();
|
|
7242
7278
|
function ensureRuntimeDir() {
|
|
7243
|
-
|
|
7279
|
+
fs9.mkdirSync(RUNTIME_DIR, { recursive: true });
|
|
7244
7280
|
}
|
|
7245
7281
|
function escapeHtml(text2) {
|
|
7246
7282
|
return text2.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
@@ -7553,7 +7589,7 @@ function buildWeixinLoginPopupHtml(sessionId) {
|
|
|
7553
7589
|
async function writeQrHtml(session) {
|
|
7554
7590
|
ensureRuntimeDir();
|
|
7555
7591
|
const qrSvg = await buildQrSvg(session.qrImageUrl);
|
|
7556
|
-
|
|
7592
|
+
fs9.writeFileSync(HTML_PATH, buildQrHtml(qrSvg), "utf-8");
|
|
7557
7593
|
}
|
|
7558
7594
|
function openQrHtml() {
|
|
7559
7595
|
try {
|
|
@@ -7742,7 +7778,7 @@ async function startWeixinLoginWebSession(options = {}) {
|
|
|
7742
7778
|
ensureRuntimeDir();
|
|
7743
7779
|
const config = options.config || {};
|
|
7744
7780
|
const seed = await createSession(0, config.baseUrl);
|
|
7745
|
-
const sessionId =
|
|
7781
|
+
const sessionId = crypto8.randomUUID();
|
|
7746
7782
|
const qrSvg = await buildQrSvg(seed.qrImageUrl);
|
|
7747
7783
|
const session = {
|
|
7748
7784
|
id: sessionId,
|
|
@@ -7814,7 +7850,7 @@ async function runWeixinLogin(config = {}) {
|
|
|
7814
7850
|
}
|
|
7815
7851
|
var isMainModule = (() => {
|
|
7816
7852
|
const entry = process.argv[1];
|
|
7817
|
-
return !!entry &&
|
|
7853
|
+
return !!entry && path9.resolve(entry) === path9.resolve(new URL(import.meta.url).pathname);
|
|
7818
7854
|
})();
|
|
7819
7855
|
if (isMainModule) {
|
|
7820
7856
|
runWeixinLogin().catch((err) => {
|
|
@@ -7824,11 +7860,11 @@ if (isMainModule) {
|
|
|
7824
7860
|
}
|
|
7825
7861
|
|
|
7826
7862
|
// src/codex-models.ts
|
|
7827
|
-
import
|
|
7863
|
+
import fs10 from "node:fs";
|
|
7828
7864
|
import os4 from "node:os";
|
|
7829
|
-
import
|
|
7830
|
-
var DEFAULT_CODEX_CONFIG_PATH =
|
|
7831
|
-
var DEFAULT_CODEX_MODELS_CACHE_PATH =
|
|
7865
|
+
import path10 from "node:path";
|
|
7866
|
+
var DEFAULT_CODEX_CONFIG_PATH = path10.join(os4.homedir(), ".codex", "config.toml");
|
|
7867
|
+
var DEFAULT_CODEX_MODELS_CACHE_PATH = path10.join(os4.homedir(), ".codex", "models_cache.json");
|
|
7832
7868
|
var REASONING_LEVEL_DESCRIPTIONS = {
|
|
7833
7869
|
low: "Fast responses with lighter reasoning",
|
|
7834
7870
|
medium: "Balances speed and reasoning depth for everyday tasks",
|
|
@@ -7877,7 +7913,7 @@ var KNOWN_CODEX_MODEL_FALLBACKS = [
|
|
|
7877
7913
|
];
|
|
7878
7914
|
function readConfiguredCodexModel(configPath = DEFAULT_CODEX_CONFIG_PATH) {
|
|
7879
7915
|
try {
|
|
7880
|
-
const raw =
|
|
7916
|
+
const raw = fs10.readFileSync(configPath, "utf-8");
|
|
7881
7917
|
let inSection = false;
|
|
7882
7918
|
for (const line of raw.split(/\r?\n/)) {
|
|
7883
7919
|
const trimmed = line.trim();
|
|
@@ -7921,7 +7957,7 @@ function parseSupportedReasoningLevels(value) {
|
|
|
7921
7957
|
}
|
|
7922
7958
|
function listCachedCodexModels(cachePath = DEFAULT_CODEX_MODELS_CACHE_PATH) {
|
|
7923
7959
|
try {
|
|
7924
|
-
const raw =
|
|
7960
|
+
const raw = fs10.readFileSync(cachePath, "utf-8");
|
|
7925
7961
|
const parsed = JSON.parse(raw);
|
|
7926
7962
|
if (!Array.isArray(parsed.models)) return [];
|
|
7927
7963
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -8220,14 +8256,14 @@ function channelToPayload(channel) {
|
|
|
8220
8256
|
};
|
|
8221
8257
|
}
|
|
8222
8258
|
function generateAccessToken() {
|
|
8223
|
-
return
|
|
8259
|
+
return crypto9.randomBytes(18).toString("base64url");
|
|
8224
8260
|
}
|
|
8225
8261
|
function timingSafeMatch(left, right) {
|
|
8226
8262
|
if (!left || !right) return false;
|
|
8227
8263
|
const leftBuffer = Buffer.from(left);
|
|
8228
8264
|
const rightBuffer = Buffer.from(right);
|
|
8229
8265
|
if (leftBuffer.length !== rightBuffer.length) return false;
|
|
8230
|
-
return
|
|
8266
|
+
return crypto9.timingSafeEqual(leftBuffer, rightBuffer);
|
|
8231
8267
|
}
|
|
8232
8268
|
function parseCookies(request) {
|
|
8233
8269
|
const header = request.headers.cookie;
|
package/package.json
CHANGED