codex-to-im 1.0.11 → 1.0.13
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/README.md +2 -0
- package/README_CN.md +2 -0
- package/SKILL.md +67 -0
- package/agents/openai.yaml +4 -0
- package/dist/cli.mjs +1 -0
- package/dist/daemon.mjs +549 -176
- package/dist/ui-server.mjs +71 -6
- package/docs/install-windows.md +2 -0
- package/package.json +3 -1
- package/scripts/install-codex.sh +57 -0
package/dist/ui-server.mjs
CHANGED
|
@@ -4568,7 +4568,7 @@ var require_lib = __commonJS({
|
|
|
4568
4568
|
import http from "node:http";
|
|
4569
4569
|
import crypto4 from "node:crypto";
|
|
4570
4570
|
import net from "node:net";
|
|
4571
|
-
import
|
|
4571
|
+
import os6 from "node:os";
|
|
4572
4572
|
import fs9 from "node:fs";
|
|
4573
4573
|
|
|
4574
4574
|
// src/config.ts
|
|
@@ -5563,6 +5563,9 @@ import path4 from "node:path";
|
|
|
5563
5563
|
function formatChannelLabel(channelType) {
|
|
5564
5564
|
return channelType === "weixin" ? "\u5FAE\u4FE1" : channelType === "feishu" ? "\u98DE\u4E66" : channelType;
|
|
5565
5565
|
}
|
|
5566
|
+
function formatBindingChatTarget(binding) {
|
|
5567
|
+
return binding.chatDisplayName?.trim() || binding.chatId;
|
|
5568
|
+
}
|
|
5566
5569
|
function findConflictingBinding(store, current, match) {
|
|
5567
5570
|
return store.listChannelBindings().find((binding) => {
|
|
5568
5571
|
if (binding.channelType === current.channelType && binding.chatId === current.chatId) {
|
|
@@ -5579,7 +5582,7 @@ function assertBindingTargetAvailable(store, current, opts) {
|
|
|
5579
5582
|
);
|
|
5580
5583
|
if (!conflict) return;
|
|
5581
5584
|
throw new Error(
|
|
5582
|
-
`\u8BE5\u4F1A\u8BDD\u5DF2\u7ED1\u5B9A\u5230 ${formatChannelLabel(conflict.channelType)} \u804A\u5929 ${conflict
|
|
5585
|
+
`\u8BE5\u4F1A\u8BDD\u5DF2\u7ED1\u5B9A\u5230 ${formatChannelLabel(conflict.channelType)} \u804A\u5929 ${formatBindingChatTarget(conflict)}\u3002\u4E00\u4E2A\u4F1A\u8BDD\u53EA\u80FD\u7ED1\u5B9A\u4E00\u4E2A\u804A\u5929\u3002`
|
|
5583
5586
|
);
|
|
5584
5587
|
}
|
|
5585
5588
|
function getSessionName(session) {
|
|
@@ -5735,6 +5738,7 @@ function removeBinding(store, bindingId) {
|
|
|
5735
5738
|
|
|
5736
5739
|
// src/service-manager.ts
|
|
5737
5740
|
import fs4 from "node:fs";
|
|
5741
|
+
import os4 from "node:os";
|
|
5738
5742
|
import path5 from "node:path";
|
|
5739
5743
|
import { spawn } from "node:child_process";
|
|
5740
5744
|
import { fileURLToPath } from "node:url";
|
|
@@ -5901,6 +5905,38 @@ function writeUiServerStatus(status) {
|
|
|
5901
5905
|
ensureDirs();
|
|
5902
5906
|
fs4.writeFileSync(uiStatusFile, JSON.stringify(status, null, 2), "utf-8");
|
|
5903
5907
|
}
|
|
5908
|
+
async function installCodexIntegration() {
|
|
5909
|
+
const sourceSkill = path5.join(packageRoot, "SKILL.md");
|
|
5910
|
+
if (!fs4.existsSync(sourceSkill)) {
|
|
5911
|
+
throw new Error(`SKILL.md not found at ${sourceSkill}`);
|
|
5912
|
+
}
|
|
5913
|
+
const skillsDir = path5.join(os4.homedir(), ".codex", "skills");
|
|
5914
|
+
const targetDir = path5.join(skillsDir, "codex-to-im");
|
|
5915
|
+
fs4.mkdirSync(skillsDir, { recursive: true });
|
|
5916
|
+
if (fs4.existsSync(targetDir)) {
|
|
5917
|
+
return { targetDir, method: "existing" };
|
|
5918
|
+
}
|
|
5919
|
+
try {
|
|
5920
|
+
fs4.symlinkSync(packageRoot, targetDir, process.platform === "win32" ? "junction" : "dir");
|
|
5921
|
+
return { targetDir, method: "junction" };
|
|
5922
|
+
} catch {
|
|
5923
|
+
fs4.cpSync(packageRoot, targetDir, {
|
|
5924
|
+
recursive: true,
|
|
5925
|
+
filter: (source) => {
|
|
5926
|
+
const relative = path5.relative(packageRoot, source);
|
|
5927
|
+
if (!relative) return true;
|
|
5928
|
+
if (relative === ".git" || relative.startsWith(`.git${path5.sep}`)) return false;
|
|
5929
|
+
if (relative === "node_modules" || relative.startsWith(`node_modules${path5.sep}`)) return false;
|
|
5930
|
+
return true;
|
|
5931
|
+
}
|
|
5932
|
+
});
|
|
5933
|
+
return { targetDir, method: "copy" };
|
|
5934
|
+
}
|
|
5935
|
+
}
|
|
5936
|
+
function isCodexIntegrationInstalled() {
|
|
5937
|
+
const targetDir = path5.join(os4.homedir(), ".codex", "skills", "codex-to-im");
|
|
5938
|
+
return fs4.existsSync(path5.join(targetDir, "SKILL.md"));
|
|
5939
|
+
}
|
|
5904
5940
|
|
|
5905
5941
|
// src/store.ts
|
|
5906
5942
|
import fs5 from "node:fs";
|
|
@@ -6797,10 +6833,10 @@ if (isMainModule) {
|
|
|
6797
6833
|
|
|
6798
6834
|
// src/codex-models.ts
|
|
6799
6835
|
import fs8 from "node:fs";
|
|
6800
|
-
import
|
|
6836
|
+
import os5 from "node:os";
|
|
6801
6837
|
import path9 from "node:path";
|
|
6802
|
-
var DEFAULT_CODEX_CONFIG_PATH = path9.join(
|
|
6803
|
-
var DEFAULT_CODEX_MODELS_CACHE_PATH = path9.join(
|
|
6838
|
+
var DEFAULT_CODEX_CONFIG_PATH = path9.join(os5.homedir(), ".codex", "config.toml");
|
|
6839
|
+
var DEFAULT_CODEX_MODELS_CACHE_PATH = path9.join(os5.homedir(), ".codex", "models_cache.json");
|
|
6804
6840
|
function readConfiguredCodexModel(configPath = DEFAULT_CODEX_CONFIG_PATH) {
|
|
6805
6841
|
try {
|
|
6806
6842
|
const raw = fs8.readFileSync(configPath, "utf-8");
|
|
@@ -6991,7 +7027,7 @@ function isLocalRequest(request) {
|
|
|
6991
7027
|
return isLoopbackAddress(getRemoteAddress(request));
|
|
6992
7028
|
}
|
|
6993
7029
|
function getLanUrls(currentPort) {
|
|
6994
|
-
const interfaces =
|
|
7030
|
+
const interfaces = os6.networkInterfaces();
|
|
6995
7031
|
const urls = /* @__PURE__ */ new Set();
|
|
6996
7032
|
for (const records of Object.values(interfaces)) {
|
|
6997
7033
|
for (const record of records || []) {
|
|
@@ -8442,6 +8478,10 @@ function renderHtml() {
|
|
|
8442
8478
|
<strong>Bridge</strong>
|
|
8443
8479
|
<div class="status-value" id="bridgeStatus">-</div>
|
|
8444
8480
|
</div>
|
|
8481
|
+
<div class="status-card">
|
|
8482
|
+
<strong>Codex Skill</strong>
|
|
8483
|
+
<div class="status-value" id="integrationStatus">-</div>
|
|
8484
|
+
</div>
|
|
8445
8485
|
<div class="status-card">
|
|
8446
8486
|
<strong>Runtime</strong>
|
|
8447
8487
|
<div class="status-value" id="runtimeStatus">-</div>
|
|
@@ -8481,6 +8521,14 @@ function renderHtml() {
|
|
|
8481
8521
|
<div class="notice">\u5DF2\u63A5\u901A\uFF1A\u4FDD\u5B58\u914D\u7F6E\u3001\u540E\u53F0\u542F\u505C\u3001\u98DE\u4E66\u51ED\u636E\u6D4B\u8BD5\u3001\u5FAE\u4FE1\u626B\u7801\u3001Codex \u8FDE\u63A5\u6D4B\u8BD5\u3001\u684C\u9762\u4F1A\u8BDD\u53D1\u73B0\u3001IM \u7ED1\u5B9A\u67E5\u770B\u4E0E\u7F51\u9875\u4FA7\u5207\u6362\u3002</div>
|
|
8482
8522
|
</div>
|
|
8483
8523
|
|
|
8524
|
+
<div class="panel-block">
|
|
8525
|
+
<p class="panel-subtitle">\u53EF\u9009 Codex Skill</p>
|
|
8526
|
+
<div class="notice">bridge \u4E0D\u518D\u6CE8\u5165\u53D1\u9001\u9644\u4EF6\u7684\u63D0\u793A\u8BCD\u3002\u9700\u8981\u8BA9 Codex \u77E5\u9053\u201C\u53EF\u4EE5\u628A\u672C\u5730\u56FE\u7247/\u6587\u4EF6\u56DE\u53D1\u5230 IM\u201D\u65F6\uFF0C\u8BF7\u5B89\u88C5\u8FD9\u4E2A\u53EF\u9009 skill\u3002</div>
|
|
8527
|
+
<div class="actions" style="margin-top: 12px;">
|
|
8528
|
+
<button id="installIntegrationBtn">\u5B89\u88C5\u53EF\u9009 Codex Skill</button>
|
|
8529
|
+
</div>
|
|
8530
|
+
</div>
|
|
8531
|
+
|
|
8484
8532
|
<div class="message" id="opsMessage"></div>
|
|
8485
8533
|
</section>
|
|
8486
8534
|
|
|
@@ -9763,6 +9811,7 @@ function renderHtml() {
|
|
|
9763
9811
|
fillForm(config);
|
|
9764
9812
|
const runningChannelText = runningChannels().length ? ' \xB7 ' + runningChannels().join(', ') : '';
|
|
9765
9813
|
document.getElementById('bridgeStatus').textContent = status.bridge.running ? 'Running' + runningChannelText : 'Stopped';
|
|
9814
|
+
document.getElementById('integrationStatus').textContent = status.codexIntegrationInstalled ? '\u5DF2\u5B89\u88C5' : '\u672A\u5B89\u88C5';
|
|
9766
9815
|
document.getElementById('runtimeStatus').textContent = config.runtime || 'codex';
|
|
9767
9816
|
document.getElementById('homeStatus').textContent = status.home;
|
|
9768
9817
|
document.getElementById('overviewHomeStatus').textContent = status.home;
|
|
@@ -9997,6 +10046,16 @@ function renderHtml() {
|
|
|
9997
10046
|
}
|
|
9998
10047
|
});
|
|
9999
10048
|
|
|
10049
|
+
document.getElementById('installIntegrationBtn').addEventListener('click', async () => {
|
|
10050
|
+
try {
|
|
10051
|
+
const result = await api('/api/install-codex-integration', { method: 'POST' });
|
|
10052
|
+
showMessage('opsMessage', 'success', '\u53EF\u9009 Codex Skill \u5DF2\u5904\u7406\uFF1A' + result.method + ' -> ' + result.targetDir);
|
|
10053
|
+
await loadStatus();
|
|
10054
|
+
} catch (error) {
|
|
10055
|
+
showMessage('opsMessage', 'error', error.message);
|
|
10056
|
+
}
|
|
10057
|
+
});
|
|
10058
|
+
|
|
10000
10059
|
document.getElementById('refreshLogsBtn').addEventListener('click', async () => {
|
|
10001
10060
|
try {
|
|
10002
10061
|
await loadLogs();
|
|
@@ -10192,6 +10251,7 @@ var server = http.createServer(async (request, response) => {
|
|
|
10192
10251
|
uiAccess: buildUiAccessInfo(port, config, request),
|
|
10193
10252
|
home: CTI_HOME,
|
|
10194
10253
|
packageRoot: getPackageRoot(),
|
|
10254
|
+
codexIntegrationInstalled: isCodexIntegrationInstalled(),
|
|
10195
10255
|
weixin: {
|
|
10196
10256
|
linkedAccounts: getWeixinAccountsPayload()
|
|
10197
10257
|
},
|
|
@@ -10243,6 +10303,11 @@ var server = http.createServer(async (request, response) => {
|
|
|
10243
10303
|
json(response, 200, result);
|
|
10244
10304
|
return;
|
|
10245
10305
|
}
|
|
10306
|
+
if (request.method === "POST" && url.pathname === "/api/install-codex-integration") {
|
|
10307
|
+
const result = await installCodexIntegration();
|
|
10308
|
+
json(response, 200, result);
|
|
10309
|
+
return;
|
|
10310
|
+
}
|
|
10246
10311
|
if (request.method === "POST" && url.pathname === "/api/bridge/start") {
|
|
10247
10312
|
const status = await startBridge();
|
|
10248
10313
|
json(response, 200, { ok: true, status });
|
package/docs/install-windows.md
CHANGED
package/package.json
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-to-im",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"description": "Installable Codex-to-IM bridge with local setup UI and background service",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist/",
|
|
9
|
+
"agents/",
|
|
9
10
|
"docs/",
|
|
10
11
|
"references/",
|
|
11
12
|
"scripts/",
|
|
13
|
+
"SKILL.md",
|
|
12
14
|
"LICENSE",
|
|
13
15
|
"README.md",
|
|
14
16
|
"README_CN.md",
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Install the optional codex-to-im skill for Codex.
|
|
5
|
+
# Usage: bash scripts/install-codex.sh [--link]
|
|
6
|
+
# --link Create a symlink instead of copying (for development)
|
|
7
|
+
|
|
8
|
+
INTEGRATION_NAME="codex-to-im"
|
|
9
|
+
CODEX_SKILLS_DIR="$HOME/.codex/skills"
|
|
10
|
+
TARGET_DIR="$CODEX_SKILLS_DIR/$INTEGRATION_NAME"
|
|
11
|
+
SOURCE_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
12
|
+
|
|
13
|
+
echo "Installing optional $INTEGRATION_NAME skill for Codex..."
|
|
14
|
+
|
|
15
|
+
if [ ! -f "$SOURCE_DIR/SKILL.md" ]; then
|
|
16
|
+
echo "Error: SKILL.md not found in $SOURCE_DIR"
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
mkdir -p "$CODEX_SKILLS_DIR"
|
|
21
|
+
|
|
22
|
+
if [ -e "$TARGET_DIR" ]; then
|
|
23
|
+
if [ -L "$TARGET_DIR" ]; then
|
|
24
|
+
EXISTING=$(readlink "$TARGET_DIR")
|
|
25
|
+
echo "Already installed as symlink -> $EXISTING"
|
|
26
|
+
else
|
|
27
|
+
echo "Already installed at $TARGET_DIR"
|
|
28
|
+
fi
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
if [ "${1:-}" = "--link" ]; then
|
|
33
|
+
ln -s "$SOURCE_DIR" "$TARGET_DIR"
|
|
34
|
+
echo "Symlinked: $TARGET_DIR -> $SOURCE_DIR"
|
|
35
|
+
echo ""
|
|
36
|
+
echo "Development mode: no install/build/prune steps were run against the source repo."
|
|
37
|
+
exit 0
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
cp -R "$SOURCE_DIR" "$TARGET_DIR"
|
|
41
|
+
echo "Copied to: $TARGET_DIR"
|
|
42
|
+
|
|
43
|
+
if [ ! -d "$TARGET_DIR/node_modules" ] || [ ! -d "$TARGET_DIR/node_modules/@openai/codex-sdk" ]; then
|
|
44
|
+
echo "Installing dependencies..."
|
|
45
|
+
(cd "$TARGET_DIR" && npm install)
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
if [ ! -f "$TARGET_DIR/dist/daemon.mjs" ]; then
|
|
49
|
+
echo "Building daemon bundle..."
|
|
50
|
+
(cd "$TARGET_DIR" && npm run build)
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
echo "Pruning dev dependencies..."
|
|
54
|
+
(cd "$TARGET_DIR" && npm prune --production)
|
|
55
|
+
|
|
56
|
+
echo ""
|
|
57
|
+
echo "Done. Start a new Codex session and use the installed codex-to-im skill when you need to send artifacts back to IM."
|