@seele00/seele 0.1.60
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/LEGAL.md +7 -0
- package/README.md +76 -0
- package/bin/seele-codex +58 -0
- package/codex/dist/app-server.js +63 -0
- package/codex/dist/errors.js +16 -0
- package/codex/dist/index.js +4 -0
- package/codex/dist/rpc-client.js +96 -0
- package/codex/dist/transports/stdio.js +81 -0
- package/codex/dist/types.js +1 -0
- package/codex/package.json +12 -0
- package/package.json +24 -0
- package/scripts/deploy/bootstrap.sh +318 -0
- package/scripts/deploy/npm/postinstall.mjs +10 -0
- package/scripts/deploy/prepare-proxy.sh +273 -0
- package/scripts/deploy/seele.env.example +75 -0
- package/scripts/deploy/start.sh +101 -0
- package/server/dist/auth/session.js +71 -0
- package/server/dist/auth/users.js +192 -0
- package/server/dist/codex-runtime/run-streamed-turn.js +587 -0
- package/server/dist/config/config.js +71 -0
- package/server/dist/contracts/artifact-rendering.js +14 -0
- package/server/dist/contracts/global-environment.js +23 -0
- package/server/dist/contracts/index.js +114 -0
- package/server/dist/contracts/managed-assets.js +13 -0
- package/server/dist/contracts/response-style.js +23 -0
- package/server/dist/contracts/task-clarification.js +13 -0
- package/server/dist/contracts/types.js +1 -0
- package/server/dist/contracts/wakeup.js +13 -0
- package/server/dist/contracts/workspace-boundary.js +20 -0
- package/server/dist/contracts/workspace-knowledge.js +48 -0
- package/server/dist/contracts/workspace-memory.js +32 -0
- package/server/dist/contracts/workspace-responsibility.js +23 -0
- package/server/dist/contracts/workspace-transcript.js +26 -0
- package/server/dist/conversations/knowledge.js +380 -0
- package/server/dist/conversations/store.js +2376 -0
- package/server/dist/doctor.js +105 -0
- package/server/dist/realtime/sse.js +12 -0
- package/server/dist/runtime-worker/client.js +405 -0
- package/server/dist/runtime-worker/process.js +216 -0
- package/server/dist/runtime-worker/protocol.js +1 -0
- package/server/dist/server.js +4570 -0
- package/server/dist/storage/sqlite.js +39 -0
- package/web/dist/assets/abnfDiagram-VRR7QNED-DevTexTl.js +1 -0
- package/web/dist/assets/arc-WlXuN6B_.js +1 -0
- package/web/dist/assets/architectureDiagram-ZJ3FMSHR-DJYRAqSp.js +36 -0
- package/web/dist/assets/bash-BELqPA7S.js +1 -0
- package/web/dist/assets/blockDiagram-677ZJIJ3-CsjO1oTv.js +132 -0
- package/web/dist/assets/c4Diagram-LMCZKHZV-DjUCYgVk.js +10 -0
- package/web/dist/assets/channel-DGnywxBx.js +1 -0
- package/web/dist/assets/chunk-2Q5K7J3B-By6S-6eo.js +1 -0
- package/web/dist/assets/chunk-32BRIVSS-Cl-hXbZD.js +1 -0
- package/web/dist/assets/chunk-5VM5RSS4--cWPnxlT.js +15 -0
- package/web/dist/assets/chunk-EX3LRPZG-PakDrWLX.js +231 -0
- package/web/dist/assets/chunk-JWPE2WC7-DMfuuvGl.js +1 -0
- package/web/dist/assets/chunk-MOJQB5TN-BHD_IRop.js +88 -0
- package/web/dist/assets/chunk-RYQCIY6F-T4jqSvsD.js +1 -0
- package/web/dist/assets/chunk-V7JOEXUC-C4paE6t8.js +206 -0
- package/web/dist/assets/chunk-VR4S4FIN-F5foapWH.js +1 -0
- package/web/dist/assets/chunk-XXDRQBXY-Dp4WIFPJ.js +1 -0
- package/web/dist/assets/classDiagram-OUVF2IWQ-DjHXtkKr.js +1 -0
- package/web/dist/assets/classDiagram-v2-EOCWNBFH-DjHXtkKr.js +1 -0
- package/web/dist/assets/core-CGjsG6g4.js +12 -0
- package/web/dist/assets/cose-bilkent-JH36ORCC-DcMU2oKv.js +1 -0
- package/web/dist/assets/css-CLj8gQPS.js +1 -0
- package/web/dist/assets/cynefin-VYW2F7L2-SiDUbAfJ.js +178 -0
- package/web/dist/assets/cynefinDiagram-TSTJHNR4-DhkNlW7i.js +62 -0
- package/web/dist/assets/cytoscape.esm-DTSO7Bv0.js +331 -0
- package/web/dist/assets/dagre-VKFMJZFB-Co--CY4-.js +4 -0
- package/web/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/web/dist/assets/diagram-FQU43EPY-BZs6G_Wi.js +3 -0
- package/web/dist/assets/diagram-G47NLZAW-C6SAe39v.js +24 -0
- package/web/dist/assets/diagram-NH7WQ7WH-D6EoRzQM.js +24 -0
- package/web/dist/assets/diagram-OA4YK3LP-kHe4KJ_b.js +30 -0
- package/web/dist/assets/diagram-WEI45ONY-BM-NnNEq.js +41 -0
- package/web/dist/assets/diff-D97Zzqfu.js +1 -0
- package/web/dist/assets/dockerfile-BcOcwvcX.js +1 -0
- package/web/dist/assets/ebnfDiagram-CCIWWBDH-BfwqR7DU.js +1 -0
- package/web/dist/assets/engine-javascript-DBd1bXLz.js +141 -0
- package/web/dist/assets/erDiagram-Q63AITRT-BwUkv7nL.js +85 -0
- package/web/dist/assets/flowDiagram-23GEKE2U-Cn0zH9bm.js +156 -0
- package/web/dist/assets/ganttDiagram-NO4QXBWP-BY_VLaEQ.js +292 -0
- package/web/dist/assets/gitGraphDiagram-IHSO6WYX-D0xpVnfm.js +106 -0
- package/web/dist/assets/github-light-DAi9KRSo.js +1 -0
- package/web/dist/assets/graph-C9eacEi8.js +1 -0
- package/web/dist/assets/html-pp8916En.js +1 -0
- package/web/dist/assets/index-Bl4JO4M7.css +1 -0
- package/web/dist/assets/index-D9Ao6WQl.js +111 -0
- package/web/dist/assets/infoDiagram-FWYZ7A6U-DnmnPGAH.js +2 -0
- package/web/dist/assets/init-Gi6I4Gst.js +1 -0
- package/web/dist/assets/ishikawaDiagram-FXEZZL3T-DTWLm3ZQ.js +70 -0
- package/web/dist/assets/java-CylS5w8V.js +1 -0
- package/web/dist/assets/javascript-wDzz0qaB.js +1 -0
- package/web/dist/assets/journeyDiagram-5HDEW3XC-RN13a5iK.js +139 -0
- package/web/dist/assets/json-Cp-IABpG.js +1 -0
- package/web/dist/assets/jsonc-Des-eS-w.js +1 -0
- package/web/dist/assets/jsx-g9-lgVsj.js +1 -0
- package/web/dist/assets/kanban-definition-HUTT4EX6-CvmlJTH9.js +89 -0
- package/web/dist/assets/katex-C5jXJg4s.js +257 -0
- package/web/dist/assets/layout-DEXfKzaS.js +1 -0
- package/web/dist/assets/linear-zHsglUI0.js +1 -0
- package/web/dist/assets/map-Czzmt4hB.js +1 -0
- package/web/dist/assets/markdown-Cvjx9yec.js +1 -0
- package/web/dist/assets/mermaid.core-Bfj9YagN.js +314 -0
- package/web/dist/assets/mindmap-definition-LN4V7U3C-CkcLeMWS.js +96 -0
- package/web/dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/web/dist/assets/pegDiagram-2B236MQR-eturQJg0.js +1 -0
- package/web/dist/assets/pieDiagram-ENE6RG2P-DJmmSZSO.js +39 -0
- package/web/dist/assets/python-B6aJPvgy.js +1 -0
- package/web/dist/assets/quadrantDiagram-ABIIQ3AL-Br5y_5ZO.js +7 -0
- package/web/dist/assets/railroadDiagram-RFXS5EU6-DwnwvUqm.js +1 -0
- package/web/dist/assets/requirementDiagram-TGXJPOKE-CMMKGrPQ.js +84 -0
- package/web/dist/assets/sankeyDiagram-HTMAVEWB-BKP-cLrV.js +40 -0
- package/web/dist/assets/sequenceDiagram-DBY2YBRQ-YgkgEj_6.js +162 -0
- package/web/dist/assets/sizeCapture-X5ZJPWSS-nkigHDeZ.js +1 -0
- package/web/dist/assets/sql-CRqJ_cUM.js +1 -0
- package/web/dist/assets/stateDiagram-2N3HPSRC-CEoMK2Kt.js +1 -0
- package/web/dist/assets/stateDiagram-v2-6OUMAXLB--iEtUEGo.js +1 -0
- package/web/dist/assets/swimlanes-5IMT3BWC-Co9CmBP_.js +2 -0
- package/web/dist/assets/swimlanesDiagram-G3AALYLV-BzapPKvi.js +8 -0
- package/web/dist/assets/timeline-definition-FHXFAJF6-C5njALNw.js +120 -0
- package/web/dist/assets/toml-vGWfd6FD.js +1 -0
- package/web/dist/assets/tsx-COt5Ahok.js +1 -0
- package/web/dist/assets/typescript-BPQ3VLAy.js +1 -0
- package/web/dist/assets/vennDiagram-L72KCM5P-BpvLQRHS.js +34 -0
- package/web/dist/assets/wardleyDiagram-EHGQE667-CWINCOno.js +78 -0
- package/web/dist/assets/xml-sdJ4AIDG.js +1 -0
- package/web/dist/assets/xychartDiagram-FW5EYKEG-xDH3ABG4.js +7 -0
- package/web/dist/assets/yaml-Buea-lGh.js +1 -0
- package/web/dist/index.html +13 -0
package/LEGAL.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Legal Disclaimer
|
|
2
|
+
|
|
3
|
+
Within this source code, the comments in Chinese shall be the original, governing version. Any comment in other languages are for reference only. In the event of any conflict between the Chinese language version comments and other language version comments, the Chinese language version shall prevail.
|
|
4
|
+
|
|
5
|
+
法律免责声明
|
|
6
|
+
|
|
7
|
+
关于代码注释部分,中文注释为官方版本,其它语言注释仅做参考。中文注释可能与其它语言注释存在不一致,当中文注释与其它语言注释存在不一致时,请以中文注释为准。
|
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Seele Codex npm Package
|
|
2
|
+
|
|
3
|
+
This package is the prebuilt Linux x64 Seele service. Node.js 24 LTS and
|
|
4
|
+
npm are required on the target host. npm downloads the production dependencies
|
|
5
|
+
during installation; the target host does not need pnpm, TypeScript, or Vite.
|
|
6
|
+
|
|
7
|
+
The web output is path-independent. `SEELE_PUBLIC_BASE_PATH` selects the public
|
|
8
|
+
path when the service starts; changing it does not require another build.
|
|
9
|
+
|
|
10
|
+
## Required Deployment Values
|
|
11
|
+
|
|
12
|
+
Before installation, confirm all of these values with the package owner or
|
|
13
|
+
target-environment owner. Do not invent or silently default them:
|
|
14
|
+
|
|
15
|
+
- `SEELE_ROOT`: persistent root containing `.runtime` and `workspaces`.
|
|
16
|
+
- `SEELE_CODEX_HOST`: service listen address.
|
|
17
|
+
- `SEELE_CODEX_PORT`: service listen port.
|
|
18
|
+
- `SEELE_PUBLIC_BASE_PATH`: externally visible path prefix, such as `/`.
|
|
19
|
+
- `SEELE_PROXY`: local no-auth proxy URL consumed by Codex.
|
|
20
|
+
- `SEELE_UPSTREAM_PROXY`: authenticated upstream proxy URL consumed by gost.
|
|
21
|
+
- `SEELE_AUTH_PASSWORD`: initial admin password for a non-loopback listener.
|
|
22
|
+
|
|
23
|
+
`SEELE_UPSTREAM_PROXY` has the form
|
|
24
|
+
`socks5h://username:password@hostname:port`. Ask the package owner for the
|
|
25
|
+
complete secret value. Do not reconstruct it from the example.
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
Keep npm's cache under the persistent Seele root so later installs and upgrades
|
|
30
|
+
can reuse downloaded packages:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install --global @seele00/seele@latest \
|
|
34
|
+
--registry=https://registry.npmmirror.com/ \
|
|
35
|
+
--cache "$SEELE_ROOT/.runtime/npm-cache"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Copy and edit the environment template:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
cp "$(seele env-example)" "$SEELE_ROOT/seele.env"
|
|
42
|
+
vi "$SEELE_ROOT/seele.env"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
On the first installation, prepare the Seele-managed Codex CLI, authenticate
|
|
46
|
+
with a headless device code, and start the service:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
seele bootstrap \
|
|
50
|
+
--env "$SEELE_ROOT/seele.env" \
|
|
51
|
+
--auth device \
|
|
52
|
+
--start
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The command prints a URL and one-time device code. Complete authentication in
|
|
56
|
+
a browser on another machine. No browser is required on the Linux host.
|
|
57
|
+
|
|
58
|
+
## Start And Upgrade
|
|
59
|
+
|
|
60
|
+
For normal service starts after bootstrap:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
seele start --env "$SEELE_ROOT/seele.env"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Upgrade the npm package without rebuilding Seele on the target host:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npm install --global @seele00/seele@<new-version> \
|
|
70
|
+
--registry=https://registry.npmmirror.com/ \
|
|
71
|
+
--cache "$SEELE_ROOT/.runtime/npm-cache"
|
|
72
|
+
seele start --env "$SEELE_ROOT/seele.env"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Package upgrades do not update an existing Codex CLI. Use Seele's runtime
|
|
76
|
+
settings UI for later Codex CLI updates.
|
package/bin/seele-codex
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SOURCE="${BASH_SOURCE[0]}"
|
|
5
|
+
while [ -h "$SOURCE" ]; do
|
|
6
|
+
SOURCE_DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
|
|
7
|
+
SOURCE="$(readlink "$SOURCE")"
|
|
8
|
+
case "$SOURCE" in
|
|
9
|
+
/*) ;;
|
|
10
|
+
*) SOURCE="$SOURCE_DIR/$SOURCE" ;;
|
|
11
|
+
esac
|
|
12
|
+
done
|
|
13
|
+
PACKAGE_ROOT="$(cd -P "$(dirname "$SOURCE")/.." && pwd)"
|
|
14
|
+
|
|
15
|
+
usage() {
|
|
16
|
+
cat <<'EOF'
|
|
17
|
+
Usage: seele-codex <command> [options]
|
|
18
|
+
|
|
19
|
+
Commands:
|
|
20
|
+
bootstrap Prepare Codex CLI/authentication, then optionally start Seele.
|
|
21
|
+
start Start the Seele web and API service.
|
|
22
|
+
doctor Check the configured Seele runtime.
|
|
23
|
+
env-example Print the installed environment-file template path.
|
|
24
|
+
version Print the installed Seele package version.
|
|
25
|
+
EOF
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
COMMAND="${1:-}"
|
|
29
|
+
if [ -n "$COMMAND" ]; then
|
|
30
|
+
shift
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
case "$COMMAND" in
|
|
34
|
+
bootstrap)
|
|
35
|
+
exec "$PACKAGE_ROOT/scripts/deploy/bootstrap.sh" --skip-build "$@"
|
|
36
|
+
;;
|
|
37
|
+
start)
|
|
38
|
+
exec "$PACKAGE_ROOT/scripts/deploy/start.sh" "$@"
|
|
39
|
+
;;
|
|
40
|
+
doctor)
|
|
41
|
+
export SEELE_CODEX_WEB_DIST="${SEELE_CODEX_WEB_DIST:-$PACKAGE_ROOT/web/dist}"
|
|
42
|
+
exec node "$PACKAGE_ROOT/server/dist/doctor.js" "$@"
|
|
43
|
+
;;
|
|
44
|
+
env-example)
|
|
45
|
+
printf '%s\n' "$PACKAGE_ROOT/scripts/deploy/seele.env.example"
|
|
46
|
+
;;
|
|
47
|
+
version|--version|-v)
|
|
48
|
+
exec node -e 'console.log(require(process.argv[1]).version)' "$PACKAGE_ROOT/package.json"
|
|
49
|
+
;;
|
|
50
|
+
help|--help|-h|"")
|
|
51
|
+
usage
|
|
52
|
+
;;
|
|
53
|
+
*)
|
|
54
|
+
echo "Unknown command: $COMMAND" >&2
|
|
55
|
+
usage >&2
|
|
56
|
+
exit 1
|
|
57
|
+
;;
|
|
58
|
+
esac
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { CodexRpcClient } from "./rpc-client.js";
|
|
2
|
+
import { StdioCodexTransport } from "./transports/stdio.js";
|
|
3
|
+
export class CodexAppServer {
|
|
4
|
+
options;
|
|
5
|
+
transport;
|
|
6
|
+
rpc;
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
this.transport = new StdioCodexTransport();
|
|
10
|
+
this.rpc = new CodexRpcClient(this.transport);
|
|
11
|
+
}
|
|
12
|
+
async start() {
|
|
13
|
+
this.transport.start({
|
|
14
|
+
codexBin: this.options.codexBin,
|
|
15
|
+
codexArgs: this.options.codexArgs,
|
|
16
|
+
cwd: this.options.cwd,
|
|
17
|
+
env: this.options.env,
|
|
18
|
+
});
|
|
19
|
+
await this.rpc.request("initialize", {
|
|
20
|
+
clientInfo: this.options.clientInfo,
|
|
21
|
+
capabilities: this.options.capabilities ?? { experimentalApi: true },
|
|
22
|
+
});
|
|
23
|
+
this.rpc.notify("initialized", {});
|
|
24
|
+
}
|
|
25
|
+
stop() {
|
|
26
|
+
this.transport.stop();
|
|
27
|
+
}
|
|
28
|
+
async startThread(options = {}) {
|
|
29
|
+
const result = await this.rpc.request("thread/start", options);
|
|
30
|
+
if (!result.thread?.id) {
|
|
31
|
+
throw new Error("thread/start did not return a thread id");
|
|
32
|
+
}
|
|
33
|
+
return result.thread;
|
|
34
|
+
}
|
|
35
|
+
async resumeThread(options) {
|
|
36
|
+
const result = await this.rpc.request("thread/resume", options);
|
|
37
|
+
if (!result.thread?.id) {
|
|
38
|
+
throw new Error("thread/resume did not return a thread id");
|
|
39
|
+
}
|
|
40
|
+
return result.thread;
|
|
41
|
+
}
|
|
42
|
+
async startTurn(options) {
|
|
43
|
+
return this.rpc.request("turn/start", options);
|
|
44
|
+
}
|
|
45
|
+
async steerTurn(options) {
|
|
46
|
+
return this.rpc.request("turn/steer", options);
|
|
47
|
+
}
|
|
48
|
+
async injectThreadItems(options) {
|
|
49
|
+
return this.rpc.request("thread/inject_items", options);
|
|
50
|
+
}
|
|
51
|
+
async readThread(options) {
|
|
52
|
+
return this.rpc.request("thread/read", options);
|
|
53
|
+
}
|
|
54
|
+
async interruptTurn(options) {
|
|
55
|
+
return this.rpc.request("turn/interrupt", options);
|
|
56
|
+
}
|
|
57
|
+
async listModels(options = {}) {
|
|
58
|
+
return this.rpc.request("model/list", options);
|
|
59
|
+
}
|
|
60
|
+
async readRateLimits() {
|
|
61
|
+
return this.rpc.request("account/rateLimits/read");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export class CodexRpcError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
data;
|
|
4
|
+
constructor(error) {
|
|
5
|
+
super(error.message);
|
|
6
|
+
this.name = "CodexRpcError";
|
|
7
|
+
this.code = error.code;
|
|
8
|
+
this.data = error.data;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class CodexProcessError extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "CodexProcessError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import { CodexProcessError, CodexRpcError } from "./errors.js";
|
|
3
|
+
export class CodexRpcClient extends EventEmitter {
|
|
4
|
+
transport;
|
|
5
|
+
nextId = 1;
|
|
6
|
+
pending = new Map();
|
|
7
|
+
constructor(transport) {
|
|
8
|
+
super();
|
|
9
|
+
this.transport = transport;
|
|
10
|
+
this.transport.on("message", (message) => this.handleMessage(message));
|
|
11
|
+
this.transport.on("stderr", (line) => this.emit("stderr", line));
|
|
12
|
+
this.transport.on("error", (error) => {
|
|
13
|
+
this.rejectPending(error);
|
|
14
|
+
this.emit("error", error);
|
|
15
|
+
});
|
|
16
|
+
this.transport.on("exit", (event) => {
|
|
17
|
+
this.rejectPending(new CodexProcessError(codexExitMessage(event)));
|
|
18
|
+
this.emit("exit", event);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
request(method, params) {
|
|
22
|
+
const id = this.nextId++;
|
|
23
|
+
const message = params === undefined ? { id, method } : { id, method, params };
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
this.pending.set(id, {
|
|
26
|
+
resolve: (value) => resolve(value),
|
|
27
|
+
reject,
|
|
28
|
+
});
|
|
29
|
+
this.transport.send(message);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
notify(method, params) {
|
|
33
|
+
const message = params === undefined ? { method } : { method, params };
|
|
34
|
+
this.transport.send(message);
|
|
35
|
+
}
|
|
36
|
+
respond(id, result) {
|
|
37
|
+
this.transport.send({ id, result });
|
|
38
|
+
}
|
|
39
|
+
respondError(id, code, message) {
|
|
40
|
+
this.transport.send({ id, error: { code, message } });
|
|
41
|
+
}
|
|
42
|
+
onNotification(handler) {
|
|
43
|
+
this.on("notification", handler);
|
|
44
|
+
return () => this.off("notification", handler);
|
|
45
|
+
}
|
|
46
|
+
onRequest(handler) {
|
|
47
|
+
this.on("request", handler);
|
|
48
|
+
return () => this.off("request", handler);
|
|
49
|
+
}
|
|
50
|
+
handleMessage(message) {
|
|
51
|
+
if (this.isRequest(message)) {
|
|
52
|
+
this.emit("request", message);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (this.isResponse(message)) {
|
|
56
|
+
const pending = this.pending.get(message.id);
|
|
57
|
+
if (!pending) {
|
|
58
|
+
this.emit("unmatchedResponse", message);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.pending.delete(message.id);
|
|
62
|
+
if (message.error) {
|
|
63
|
+
pending.reject(new CodexRpcError(message.error));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
pending.resolve(message.result ?? null);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (this.isNotification(message)) {
|
|
70
|
+
this.emit("notification", message);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
isResponse(message) {
|
|
74
|
+
return (typeof message.id === "number" &&
|
|
75
|
+
typeof message.method !== "string");
|
|
76
|
+
}
|
|
77
|
+
isRequest(message) {
|
|
78
|
+
return (typeof message.id === "number" &&
|
|
79
|
+
typeof message.method === "string");
|
|
80
|
+
}
|
|
81
|
+
isNotification(message) {
|
|
82
|
+
return (typeof message.method === "string" &&
|
|
83
|
+
typeof message.id !== "number");
|
|
84
|
+
}
|
|
85
|
+
rejectPending(error) {
|
|
86
|
+
const pending = [...this.pending.values()];
|
|
87
|
+
this.pending.clear();
|
|
88
|
+
for (const request of pending) {
|
|
89
|
+
request.reject(error);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function codexExitMessage(event) {
|
|
94
|
+
const summary = `codex app-server exited: code=${event.code} signal=${event.signal}`;
|
|
95
|
+
return event.stderr ? `${summary}\n${event.stderr}` : summary;
|
|
96
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import readline from "node:readline";
|
|
3
|
+
import { EventEmitter } from "node:events";
|
|
4
|
+
import { CodexProcessError } from "../errors.js";
|
|
5
|
+
export class StdioCodexTransport extends EventEmitter {
|
|
6
|
+
process = null;
|
|
7
|
+
stderrTail = "";
|
|
8
|
+
start(options = {}) {
|
|
9
|
+
if (this.process) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const codexBin = options.codexBin ?? "codex";
|
|
13
|
+
this.stderrTail = "";
|
|
14
|
+
const child = spawn(codexBin, [...(options.codexArgs ?? []), "app-server", "--listen", "stdio://"], {
|
|
15
|
+
cwd: options.cwd,
|
|
16
|
+
env: { ...process.env, ...options.env },
|
|
17
|
+
detached: process.platform !== "win32",
|
|
18
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
19
|
+
});
|
|
20
|
+
this.process = child;
|
|
21
|
+
const stdout = readline.createInterface({ input: child.stdout });
|
|
22
|
+
stdout.on("line", (line) => {
|
|
23
|
+
if (!line.trim()) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
this.emit("message", JSON.parse(line));
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
this.emit("error", new CodexProcessError(`Failed to parse app-server JSON line: ${error.message}`));
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
child.stderr.on("data", (chunk) => {
|
|
34
|
+
const text = chunk.toString("utf8");
|
|
35
|
+
this.stderrTail = `${this.stderrTail}${text}`.slice(-8_000);
|
|
36
|
+
this.emit("stderr", text);
|
|
37
|
+
});
|
|
38
|
+
child.on("error", (error) => {
|
|
39
|
+
this.emit("error", error);
|
|
40
|
+
});
|
|
41
|
+
child.on("exit", (code, signal) => {
|
|
42
|
+
this.process = null;
|
|
43
|
+
this.emit("exit", {
|
|
44
|
+
code,
|
|
45
|
+
signal,
|
|
46
|
+
stderr: this.stderrTail.trim() || null,
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
send(message) {
|
|
51
|
+
if (!this.process) {
|
|
52
|
+
throw new CodexProcessError("codex app-server process is not running");
|
|
53
|
+
}
|
|
54
|
+
this.process.stdin.write(`${JSON.stringify(message)}\n`);
|
|
55
|
+
}
|
|
56
|
+
stop() {
|
|
57
|
+
if (!this.process) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const child = this.process;
|
|
61
|
+
this.process = null;
|
|
62
|
+
if (process.platform !== "win32" && child.pid) {
|
|
63
|
+
try {
|
|
64
|
+
process.kill(-child.pid, "SIGTERM");
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
child.kill("SIGTERM");
|
|
68
|
+
}
|
|
69
|
+
setTimeout(() => {
|
|
70
|
+
try {
|
|
71
|
+
process.kill(-child.pid, "SIGKILL");
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// The process group already exited.
|
|
75
|
+
}
|
|
76
|
+
}, 1500).unref();
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
child.kill("SIGTERM");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@seele00/seele",
|
|
3
|
+
"version": "0.1.60",
|
|
4
|
+
"description": "Browser UI and server runtime for Seele Codex",
|
|
5
|
+
"private": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"license": "UNLICENSED",
|
|
8
|
+
"os": [
|
|
9
|
+
"linux"
|
|
10
|
+
],
|
|
11
|
+
"cpu": [
|
|
12
|
+
"x64"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=24 <25"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"seele": "bin/seele-codex",
|
|
19
|
+
"seele-codex": "bin/seele-codex"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"postinstall": "node scripts/deploy/npm/postinstall.mjs"
|
|
23
|
+
}
|
|
24
|
+
}
|