@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.
Files changed (129) hide show
  1. package/LEGAL.md +7 -0
  2. package/README.md +76 -0
  3. package/bin/seele-codex +58 -0
  4. package/codex/dist/app-server.js +63 -0
  5. package/codex/dist/errors.js +16 -0
  6. package/codex/dist/index.js +4 -0
  7. package/codex/dist/rpc-client.js +96 -0
  8. package/codex/dist/transports/stdio.js +81 -0
  9. package/codex/dist/types.js +1 -0
  10. package/codex/package.json +12 -0
  11. package/package.json +24 -0
  12. package/scripts/deploy/bootstrap.sh +318 -0
  13. package/scripts/deploy/npm/postinstall.mjs +10 -0
  14. package/scripts/deploy/prepare-proxy.sh +273 -0
  15. package/scripts/deploy/seele.env.example +75 -0
  16. package/scripts/deploy/start.sh +101 -0
  17. package/server/dist/auth/session.js +71 -0
  18. package/server/dist/auth/users.js +192 -0
  19. package/server/dist/codex-runtime/run-streamed-turn.js +587 -0
  20. package/server/dist/config/config.js +71 -0
  21. package/server/dist/contracts/artifact-rendering.js +14 -0
  22. package/server/dist/contracts/global-environment.js +23 -0
  23. package/server/dist/contracts/index.js +114 -0
  24. package/server/dist/contracts/managed-assets.js +13 -0
  25. package/server/dist/contracts/response-style.js +23 -0
  26. package/server/dist/contracts/task-clarification.js +13 -0
  27. package/server/dist/contracts/types.js +1 -0
  28. package/server/dist/contracts/wakeup.js +13 -0
  29. package/server/dist/contracts/workspace-boundary.js +20 -0
  30. package/server/dist/contracts/workspace-knowledge.js +48 -0
  31. package/server/dist/contracts/workspace-memory.js +32 -0
  32. package/server/dist/contracts/workspace-responsibility.js +23 -0
  33. package/server/dist/contracts/workspace-transcript.js +26 -0
  34. package/server/dist/conversations/knowledge.js +380 -0
  35. package/server/dist/conversations/store.js +2376 -0
  36. package/server/dist/doctor.js +105 -0
  37. package/server/dist/realtime/sse.js +12 -0
  38. package/server/dist/runtime-worker/client.js +405 -0
  39. package/server/dist/runtime-worker/process.js +216 -0
  40. package/server/dist/runtime-worker/protocol.js +1 -0
  41. package/server/dist/server.js +4570 -0
  42. package/server/dist/storage/sqlite.js +39 -0
  43. package/web/dist/assets/abnfDiagram-VRR7QNED-DevTexTl.js +1 -0
  44. package/web/dist/assets/arc-WlXuN6B_.js +1 -0
  45. package/web/dist/assets/architectureDiagram-ZJ3FMSHR-DJYRAqSp.js +36 -0
  46. package/web/dist/assets/bash-BELqPA7S.js +1 -0
  47. package/web/dist/assets/blockDiagram-677ZJIJ3-CsjO1oTv.js +132 -0
  48. package/web/dist/assets/c4Diagram-LMCZKHZV-DjUCYgVk.js +10 -0
  49. package/web/dist/assets/channel-DGnywxBx.js +1 -0
  50. package/web/dist/assets/chunk-2Q5K7J3B-By6S-6eo.js +1 -0
  51. package/web/dist/assets/chunk-32BRIVSS-Cl-hXbZD.js +1 -0
  52. package/web/dist/assets/chunk-5VM5RSS4--cWPnxlT.js +15 -0
  53. package/web/dist/assets/chunk-EX3LRPZG-PakDrWLX.js +231 -0
  54. package/web/dist/assets/chunk-JWPE2WC7-DMfuuvGl.js +1 -0
  55. package/web/dist/assets/chunk-MOJQB5TN-BHD_IRop.js +88 -0
  56. package/web/dist/assets/chunk-RYQCIY6F-T4jqSvsD.js +1 -0
  57. package/web/dist/assets/chunk-V7JOEXUC-C4paE6t8.js +206 -0
  58. package/web/dist/assets/chunk-VR4S4FIN-F5foapWH.js +1 -0
  59. package/web/dist/assets/chunk-XXDRQBXY-Dp4WIFPJ.js +1 -0
  60. package/web/dist/assets/classDiagram-OUVF2IWQ-DjHXtkKr.js +1 -0
  61. package/web/dist/assets/classDiagram-v2-EOCWNBFH-DjHXtkKr.js +1 -0
  62. package/web/dist/assets/core-CGjsG6g4.js +12 -0
  63. package/web/dist/assets/cose-bilkent-JH36ORCC-DcMU2oKv.js +1 -0
  64. package/web/dist/assets/css-CLj8gQPS.js +1 -0
  65. package/web/dist/assets/cynefin-VYW2F7L2-SiDUbAfJ.js +178 -0
  66. package/web/dist/assets/cynefinDiagram-TSTJHNR4-DhkNlW7i.js +62 -0
  67. package/web/dist/assets/cytoscape.esm-DTSO7Bv0.js +331 -0
  68. package/web/dist/assets/dagre-VKFMJZFB-Co--CY4-.js +4 -0
  69. package/web/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  70. package/web/dist/assets/diagram-FQU43EPY-BZs6G_Wi.js +3 -0
  71. package/web/dist/assets/diagram-G47NLZAW-C6SAe39v.js +24 -0
  72. package/web/dist/assets/diagram-NH7WQ7WH-D6EoRzQM.js +24 -0
  73. package/web/dist/assets/diagram-OA4YK3LP-kHe4KJ_b.js +30 -0
  74. package/web/dist/assets/diagram-WEI45ONY-BM-NnNEq.js +41 -0
  75. package/web/dist/assets/diff-D97Zzqfu.js +1 -0
  76. package/web/dist/assets/dockerfile-BcOcwvcX.js +1 -0
  77. package/web/dist/assets/ebnfDiagram-CCIWWBDH-BfwqR7DU.js +1 -0
  78. package/web/dist/assets/engine-javascript-DBd1bXLz.js +141 -0
  79. package/web/dist/assets/erDiagram-Q63AITRT-BwUkv7nL.js +85 -0
  80. package/web/dist/assets/flowDiagram-23GEKE2U-Cn0zH9bm.js +156 -0
  81. package/web/dist/assets/ganttDiagram-NO4QXBWP-BY_VLaEQ.js +292 -0
  82. package/web/dist/assets/gitGraphDiagram-IHSO6WYX-D0xpVnfm.js +106 -0
  83. package/web/dist/assets/github-light-DAi9KRSo.js +1 -0
  84. package/web/dist/assets/graph-C9eacEi8.js +1 -0
  85. package/web/dist/assets/html-pp8916En.js +1 -0
  86. package/web/dist/assets/index-Bl4JO4M7.css +1 -0
  87. package/web/dist/assets/index-D9Ao6WQl.js +111 -0
  88. package/web/dist/assets/infoDiagram-FWYZ7A6U-DnmnPGAH.js +2 -0
  89. package/web/dist/assets/init-Gi6I4Gst.js +1 -0
  90. package/web/dist/assets/ishikawaDiagram-FXEZZL3T-DTWLm3ZQ.js +70 -0
  91. package/web/dist/assets/java-CylS5w8V.js +1 -0
  92. package/web/dist/assets/javascript-wDzz0qaB.js +1 -0
  93. package/web/dist/assets/journeyDiagram-5HDEW3XC-RN13a5iK.js +139 -0
  94. package/web/dist/assets/json-Cp-IABpG.js +1 -0
  95. package/web/dist/assets/jsonc-Des-eS-w.js +1 -0
  96. package/web/dist/assets/jsx-g9-lgVsj.js +1 -0
  97. package/web/dist/assets/kanban-definition-HUTT4EX6-CvmlJTH9.js +89 -0
  98. package/web/dist/assets/katex-C5jXJg4s.js +257 -0
  99. package/web/dist/assets/layout-DEXfKzaS.js +1 -0
  100. package/web/dist/assets/linear-zHsglUI0.js +1 -0
  101. package/web/dist/assets/map-Czzmt4hB.js +1 -0
  102. package/web/dist/assets/markdown-Cvjx9yec.js +1 -0
  103. package/web/dist/assets/mermaid.core-Bfj9YagN.js +314 -0
  104. package/web/dist/assets/mindmap-definition-LN4V7U3C-CkcLeMWS.js +96 -0
  105. package/web/dist/assets/ordinal-Cboi1Yqb.js +1 -0
  106. package/web/dist/assets/pegDiagram-2B236MQR-eturQJg0.js +1 -0
  107. package/web/dist/assets/pieDiagram-ENE6RG2P-DJmmSZSO.js +39 -0
  108. package/web/dist/assets/python-B6aJPvgy.js +1 -0
  109. package/web/dist/assets/quadrantDiagram-ABIIQ3AL-Br5y_5ZO.js +7 -0
  110. package/web/dist/assets/railroadDiagram-RFXS5EU6-DwnwvUqm.js +1 -0
  111. package/web/dist/assets/requirementDiagram-TGXJPOKE-CMMKGrPQ.js +84 -0
  112. package/web/dist/assets/sankeyDiagram-HTMAVEWB-BKP-cLrV.js +40 -0
  113. package/web/dist/assets/sequenceDiagram-DBY2YBRQ-YgkgEj_6.js +162 -0
  114. package/web/dist/assets/sizeCapture-X5ZJPWSS-nkigHDeZ.js +1 -0
  115. package/web/dist/assets/sql-CRqJ_cUM.js +1 -0
  116. package/web/dist/assets/stateDiagram-2N3HPSRC-CEoMK2Kt.js +1 -0
  117. package/web/dist/assets/stateDiagram-v2-6OUMAXLB--iEtUEGo.js +1 -0
  118. package/web/dist/assets/swimlanes-5IMT3BWC-Co9CmBP_.js +2 -0
  119. package/web/dist/assets/swimlanesDiagram-G3AALYLV-BzapPKvi.js +8 -0
  120. package/web/dist/assets/timeline-definition-FHXFAJF6-C5njALNw.js +120 -0
  121. package/web/dist/assets/toml-vGWfd6FD.js +1 -0
  122. package/web/dist/assets/tsx-COt5Ahok.js +1 -0
  123. package/web/dist/assets/typescript-BPQ3VLAy.js +1 -0
  124. package/web/dist/assets/vennDiagram-L72KCM5P-BpvLQRHS.js +34 -0
  125. package/web/dist/assets/wardleyDiagram-EHGQE667-CWINCOno.js +78 -0
  126. package/web/dist/assets/xml-sdJ4AIDG.js +1 -0
  127. package/web/dist/assets/xychartDiagram-FW5EYKEG-xDH3ABG4.js +7 -0
  128. package/web/dist/assets/yaml-Buea-lGh.js +1 -0
  129. package/web/dist/index.html +13 -0
@@ -0,0 +1,318 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
5
+ cd "$ROOT_DIR"
6
+
7
+ ENV_FILE=""
8
+ CLI_AUTH_MODE=""
9
+ START_AFTER=0
10
+ SKIP_BUILD=0
11
+
12
+ usage() {
13
+ cat <<'EOF'
14
+ Usage: ./scripts/deploy/bootstrap.sh [options]
15
+
16
+ Options:
17
+ --env PATH Load deployment environment variables from PATH.
18
+ --auth MODE device | auth-json | token | none. Defaults to device.
19
+ --start Start Seele Codex after bootstrap succeeds.
20
+ --skip-build Skip pnpm install/build.
21
+ -h, --help Show this help.
22
+
23
+ Typical first run:
24
+
25
+ cp scripts/deploy/seele.env.example seele.env
26
+ ./scripts/deploy/bootstrap.sh --env ./seele.env --auth device --start
27
+ EOF
28
+ }
29
+
30
+ main() {
31
+ while [ "$#" -gt 0 ]; do
32
+ case "$1" in
33
+ --env)
34
+ ENV_FILE="${2:-}"
35
+ shift 2
36
+ ;;
37
+ --auth)
38
+ CLI_AUTH_MODE="${2:-}"
39
+ shift 2
40
+ ;;
41
+ --start)
42
+ START_AFTER=1
43
+ shift
44
+ ;;
45
+ --skip-build)
46
+ SKIP_BUILD=1
47
+ shift
48
+ ;;
49
+ -h|--help)
50
+ usage
51
+ exit 0
52
+ ;;
53
+ *)
54
+ echo "Unknown option: $1" >&2
55
+ usage >&2
56
+ exit 1
57
+ ;;
58
+ esac
59
+ done
60
+
61
+ if [ -n "$ENV_FILE" ]; then
62
+ if [ ! -f "$ENV_FILE" ]; then
63
+ echo "Environment file not found: $ENV_FILE" >&2
64
+ exit 1
65
+ fi
66
+ set -a
67
+ # shellcheck disable=SC1090
68
+ . "$ENV_FILE"
69
+ set +a
70
+ fi
71
+
72
+ if [ -z "${SEELE_ROOT:-}" ]; then
73
+ echo "SEELE_ROOT is required for this deployment test." >&2
74
+ echo "Ask the package owner or target-environment owner for the Seele root directory and put it in seele.env." >&2
75
+ exit 1
76
+ fi
77
+ export SEELE_ROOT
78
+ AUTH_MODE="${CLI_AUTH_MODE:-${SEELE_DEPLOY_AUTH_MODE:-device}}"
79
+ RUNTIME_DIR="${SEELE_RUNTIME_DIR:-$SEELE_ROOT/.runtime}"
80
+ export SEELE_RUNTIME_DIR="$RUNTIME_DIR"
81
+ export CODEX_HOME="${CODEX_HOME:-$RUNTIME_DIR/codex-home}"
82
+ export CODEX_INSTALL_DIR="$RUNTIME_DIR/bin"
83
+ export SEELE_CODEX_WORKSPACE_ROOT="${SEELE_CODEX_WORKSPACE_ROOT:-$SEELE_ROOT/workspaces}"
84
+ export SEELE_CODEX_WEB_DIST="${SEELE_CODEX_WEB_DIST:-$ROOT_DIR/web/dist}"
85
+ export SEELE_PUBLIC_BASE_PATH="$(normalize_base_path "${SEELE_PUBLIC_BASE_PATH:-/}")"
86
+ export PATH="$CODEX_INSTALL_DIR:$PATH"
87
+
88
+ if [ -z "${SEELE_PROXY:-}" ]; then
89
+ echo "SEELE_PROXY is required for this deployment test." >&2
90
+ echo "Ask the package owner for the proxy value, put it in seele.env, then rerun bootstrap." >&2
91
+ exit 1
92
+ fi
93
+
94
+ normalize_proxy_env
95
+
96
+ mkdir -p "$RUNTIME_DIR" "$CODEX_HOME" "$CODEX_INSTALL_DIR" "$SEELE_CODEX_WORKSPACE_ROOT"
97
+ chmod 700 "$CODEX_HOME"
98
+
99
+ ensure_node
100
+ ensure_codex_cli
101
+ write_codex_config
102
+ authenticate_codex "$AUTH_MODE"
103
+
104
+ if [ "$SKIP_BUILD" -eq 0 ]; then
105
+ ensure_pnpm
106
+ pnpm install --frozen-lockfile
107
+ pnpm build
108
+ fi
109
+
110
+ cat <<EOF
111
+ Seele Codex bootstrap completed.
112
+
113
+ Runtime directory: $RUNTIME_DIR
114
+ Codex home: $CODEX_HOME
115
+ Codex install dir: $CODEX_INSTALL_DIR
116
+ Workspace root: $SEELE_CODEX_WORKSPACE_ROOT
117
+ EOF
118
+
119
+ if [ "$START_AFTER" -eq 1 ]; then
120
+ if [ -n "$ENV_FILE" ]; then
121
+ exec "$ROOT_DIR/scripts/deploy/start.sh" --env "$ENV_FILE"
122
+ fi
123
+ exec "$ROOT_DIR/scripts/deploy/start.sh"
124
+ fi
125
+ }
126
+
127
+ normalize_proxy_env() {
128
+ export NO_PROXY="${NO_PROXY:-127.0.0.1,localhost,.svc,.cluster.local}"
129
+ export no_proxy="$NO_PROXY"
130
+ }
131
+
132
+ with_runtime_proxy() {
133
+ if [ -n "${SEELE_PROXY:-}" ]; then
134
+ ALL_PROXY="$SEELE_PROXY" \
135
+ HTTP_PROXY="$SEELE_PROXY" \
136
+ HTTPS_PROXY="$SEELE_PROXY" \
137
+ all_proxy="$SEELE_PROXY" \
138
+ http_proxy="$SEELE_PROXY" \
139
+ https_proxy="$SEELE_PROXY" \
140
+ "$@"
141
+ return
142
+ fi
143
+
144
+ "$@"
145
+ }
146
+
147
+ normalize_base_path() {
148
+ local value="$1"
149
+ if [ -z "$value" ]; then
150
+ value="/"
151
+ fi
152
+ value="/${value#/}"
153
+ value="${value%/}/"
154
+ printf '%s' "$value"
155
+ }
156
+
157
+ replace_path_atomically() {
158
+ node -e 'require("node:fs").renameSync(process.argv[1], process.argv[2])' "$1" "$2"
159
+ }
160
+
161
+ ensure_node() {
162
+ if ! command -v node >/dev/null 2>&1; then
163
+ echo "node is required. Install Node.js 24 LTS before running this script." >&2
164
+ exit 1
165
+ fi
166
+
167
+ node -e 'const major = Number(process.versions.node.split(".")[0]); if (major !== 24) { console.error(`Node.js 24 LTS is required. Current: ${process.version}`); process.exit(1); }'
168
+ }
169
+
170
+ ensure_pnpm() {
171
+ if command -v pnpm >/dev/null 2>&1; then
172
+ return
173
+ fi
174
+
175
+ if ! command -v corepack >/dev/null 2>&1; then
176
+ echo "pnpm is required, or corepack must be available to install pnpm." >&2
177
+ exit 1
178
+ fi
179
+
180
+ corepack enable
181
+ corepack prepare pnpm@9.15.0 --activate
182
+ }
183
+
184
+ ensure_codex_cli() {
185
+ if [ -x "$CODEX_INSTALL_DIR/codex" ]; then
186
+ local current_version_output=""
187
+ if current_version_output="$("$CODEX_INSTALL_DIR/codex" --version 2>/dev/null)"; then
188
+ echo "Using Seele-managed Codex CLI: $current_version_output"
189
+ return
190
+ fi
191
+ echo "WARNING: The existing Seele-managed Codex CLI is not runnable on this platform." >&2
192
+ echo "Start Seele, open Settings > Runtime > Check Update, and explicitly start the reinstall." >&2
193
+ return
194
+ fi
195
+
196
+ if ! command -v npm >/dev/null 2>&1; then
197
+ echo "npm is required to install Codex CLI automatically." >&2
198
+ exit 1
199
+ fi
200
+
201
+ local codex_root="$RUNTIME_DIR/codex"
202
+ local versions_dir="$codex_root/versions"
203
+ local staging_dir="$codex_root/.staging-bootstrap-$$"
204
+ mkdir -p "$versions_dir"
205
+ rm -rf "$staging_dir"
206
+
207
+ echo "Installing Codex CLI into staging: $staging_dir"
208
+ with_runtime_proxy npm install \
209
+ --global \
210
+ --prefix "$staging_dir" \
211
+ --no-audit \
212
+ --no-fund \
213
+ @openai/codex@latest
214
+
215
+ local staging_bin="$staging_dir/bin/codex"
216
+ if [ ! -x "$staging_bin" ]; then
217
+ echo "Codex CLI installation completed, but the staged binary was not found at $staging_bin." >&2
218
+ exit 1
219
+ fi
220
+
221
+ local version_output
222
+ local version
223
+ version_output="$("$staging_bin" --version)"
224
+ version="${version_output#codex-cli }"
225
+ case "$version" in
226
+ ""|*[!0-9A-Za-z._-]*)
227
+ echo "Unable to determine a safe Codex CLI version from: $version_output" >&2
228
+ exit 1
229
+ ;;
230
+ esac
231
+
232
+ local platform
233
+ local architecture
234
+ platform="$(node -p 'process.platform')"
235
+ architecture="$(node -p 'process.arch')"
236
+ local version_dir="$versions_dir/$version-$platform-$architecture"
237
+ if [ -e "$version_dir" ]; then
238
+ if [ ! -x "$version_dir/bin/codex" ] || [ "$("$version_dir/bin/codex" --version)" != "$version_output" ]; then
239
+ echo "Existing Codex CLI version directory is invalid: $version_dir" >&2
240
+ exit 1
241
+ fi
242
+ rm -rf "$staging_dir"
243
+ else
244
+ mv "$staging_dir" "$version_dir"
245
+ fi
246
+
247
+ local current_next="$codex_root/current.next-$$"
248
+ local launcher_next="$CODEX_INSTALL_DIR/codex.next-$$"
249
+ ln -s "versions/$version" "$current_next"
250
+ replace_path_atomically "$current_next" "$codex_root/current"
251
+ ln -s "../codex/current/bin/codex" "$launcher_next"
252
+ replace_path_atomically "$launcher_next" "$CODEX_INSTALL_DIR/codex"
253
+ hash -r
254
+
255
+ if [ ! -x "$CODEX_INSTALL_DIR/codex" ]; then
256
+ echo "Codex CLI activation failed at $CODEX_INSTALL_DIR/codex." >&2
257
+ exit 1
258
+ fi
259
+ echo "Codex CLI: $("$CODEX_INSTALL_DIR/codex" --version)"
260
+ }
261
+
262
+ write_codex_config() {
263
+ local config_file="$CODEX_HOME/config.toml"
264
+ if [ -f "$config_file" ]; then
265
+ return
266
+ fi
267
+
268
+ cat > "$config_file" <<'EOF'
269
+ cli_auth_credentials_store = "file"
270
+ EOF
271
+ chmod 600 "$config_file"
272
+ }
273
+
274
+ authenticate_codex() {
275
+ local mode="$1"
276
+ local auth_file="$CODEX_HOME/auth.json"
277
+
278
+ if [ "${SEELE_FORCE_CODEX_LOGIN:-0}" != "1" ] && [ -s "$auth_file" ]; then
279
+ echo "Codex auth cache already exists at $auth_file; skipping login."
280
+ return
281
+ fi
282
+
283
+ case "$mode" in
284
+ device)
285
+ echo "Starting Codex device-code login."
286
+ echo "Open the printed URL in your local browser and enter the code shown by Codex."
287
+ with_runtime_proxy codex login --device-auth
288
+ ;;
289
+ auth-json)
290
+ if [ -z "${CODEX_AUTH_JSON:-}" ]; then
291
+ echo "CODEX_AUTH_JSON is required when --auth auth-json is used." >&2
292
+ exit 1
293
+ fi
294
+ if [ ! -f "$CODEX_AUTH_JSON" ]; then
295
+ echo "CODEX_AUTH_JSON file not found: $CODEX_AUTH_JSON" >&2
296
+ exit 1
297
+ fi
298
+ cp "$CODEX_AUTH_JSON" "$auth_file"
299
+ chmod 600 "$auth_file"
300
+ ;;
301
+ token)
302
+ if [ -z "${CODEX_ACCESS_TOKEN:-}" ]; then
303
+ echo "CODEX_ACCESS_TOKEN is required when --auth token is used." >&2
304
+ exit 1
305
+ fi
306
+ printf '%s' "$CODEX_ACCESS_TOKEN" | with_runtime_proxy codex login --with-access-token
307
+ ;;
308
+ none)
309
+ echo "Skipping Codex authentication."
310
+ ;;
311
+ *)
312
+ echo "Unknown auth mode: $mode" >&2
313
+ exit 1
314
+ ;;
315
+ esac
316
+ }
317
+
318
+ main "$@"
@@ -0,0 +1,10 @@
1
+ import { mkdir, rm, symlink } from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ const packageRoot = path.resolve(import.meta.dirname, "../../..");
5
+ const scopeDir = path.join(packageRoot, "node_modules", "@seele-codex");
6
+ const linkPath = path.join(scopeDir, "codex");
7
+
8
+ await mkdir(scopeDir, { recursive: true });
9
+ await rm(linkPath, { force: true, recursive: true });
10
+ await symlink(path.join(packageRoot, "codex"), linkPath, "dir");
@@ -0,0 +1,273 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # prepare-proxy.sh
5
+ #
6
+ # Prepare a clean LOCAL no-auth proxy entrypoint for Codex.
7
+ #
8
+ # Why this exists:
9
+ # Some Codex HTTP clients (models refresh, MCP / ps/mcp) issue a bare
10
+ # HTTP CONNECT to the configured proxy WITHOUT forwarding proxy credentials.
11
+ # If the upstream proxy requires authentication it answers 407 and resets
12
+ # the stream, surfacing as `stream disconnected before completion` /
13
+ # `Transport channel closed`. The main response path uses SOCKS5 with creds
14
+ # and works, which is why only those two auxiliary features break.
15
+ #
16
+ # Fix (no Codex change, purely at the proxy layer):
17
+ # Run a LOCAL no-auth proxy listener. Codex sends its bare CONNECT to this
18
+ # local listener (no auth required -> accepted). The local listener then
19
+ # forwards upstream WITH the credentials taken from SEELE_UPSTREAM_PROXY.
20
+ #
21
+ # codex --bare CONNECT (no creds)--> 127.0.0.1:<port> (no auth)
22
+ # --with creds--> SEELE_UPSTREAM_PROXY (socks5 exit) --> OpenAI
23
+ #
24
+ # IMPORTANT config model:
25
+ # The Seele server injects SEELE_PROXY into the Codex environment
26
+ # (ALL_PROXY/HTTP_PROXY/...). So Codex uses SEELE_PROXY directly. Therefore:
27
+ # SEELE_PROXY = the LOCAL no-auth entrypoint (http://127.0.0.1:<port>)
28
+ # SEELE_UPSTREAM_PROXY = the real credentialed upstream (socks5 exit)
29
+ # Codex talks to the local no-auth entrypoint; only this script holds the
30
+ # upstream credentials and forwards to the real exit.
31
+ #
32
+ # After running this, the Codex runtime (via SEELE_PROXY) and any other script
33
+ # can simply use:
34
+ # http://127.0.0.1:<port>
35
+ # as their proxy, without ever handling credentials themselves.
36
+ #
37
+ # This replaces all the network-layer workarounds explored earlier
38
+ # (WireGuard tunnel, MTU tweaks, custom routes): none of them are needed,
39
+ # the upstream SOCKS5 exit is directly reachable.
40
+
41
+ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
42
+ cd "$ROOT_DIR"
43
+
44
+ ENV_FILE=""
45
+ ACTION="start"
46
+
47
+ usage() {
48
+ cat <<'EOF'
49
+ Usage: ./scripts/deploy/prepare-proxy.sh [--env PATH] [--status|--stop]
50
+
51
+ Prepares a local no-auth proxy entrypoint that forwards to the credentialed
52
+ upstream (SEELE_UPSTREAM_PROXY), so Codex (via SEELE_PROXY) and other scripts
53
+ can use http://127.0.0.1:<port> without handling credentials.
54
+
55
+ Options:
56
+ --env PATH Load configuration from an env file (e.g. ./seele.env).
57
+ --status Show whether the local proxy is running and exit.
58
+ --stop Stop the local proxy and exit.
59
+ -h, --help Show this help.
60
+
61
+ Relevant variables (from --env file or environment):
62
+ SEELE_UPSTREAM_PROXY Real upstream proxy WITH credentials (required).
63
+ Format: scheme://user:pass@host:port
64
+ e.g. socks5h://user:pass@47.77.237.69:28888
65
+ SEELE_LOCAL_PROXY_PORT Local listen port for the no-auth entrypoint.
66
+ Default: 55860
67
+ SEELE_LOCAL_PROXY_ADDR Local proxy URL other components should use.
68
+ Default: http://127.0.0.1:<SEELE_LOCAL_PROXY_PORT>
69
+ Set SEELE_PROXY to this value so Codex uses it.
70
+ SEELE_GOST_BIN Path to the gost binary. Default: looked up on
71
+ PATH, then $SEELE_ROOT/gost, then ./gost.
72
+ SEELE_PROXY_PID_FILE PID file. Default: $SEELE_ROOT/.runtime/prepare-proxy.pid
73
+ (falls back to /tmp/seele-prepare-proxy.pid).
74
+ SEELE_PROXY_LOG_FILE Log file. Default: $SEELE_ROOT/.runtime/prepare-proxy.log
75
+ (falls back to /tmp/seele-prepare-proxy.log).
76
+ EOF
77
+ }
78
+
79
+ while [ "$#" -gt 0 ]; do
80
+ case "$1" in
81
+ --env)
82
+ ENV_FILE="${2:-}"
83
+ shift 2
84
+ ;;
85
+ --status)
86
+ ACTION="status"
87
+ shift
88
+ ;;
89
+ --stop)
90
+ ACTION="stop"
91
+ shift
92
+ ;;
93
+ -h|--help)
94
+ usage
95
+ exit 0
96
+ ;;
97
+ *)
98
+ echo "Unknown option: $1" >&2
99
+ usage >&2
100
+ exit 1
101
+ ;;
102
+ esac
103
+ done
104
+
105
+ if [ -n "$ENV_FILE" ]; then
106
+ if [ ! -f "$ENV_FILE" ]; then
107
+ echo "Environment file not found: $ENV_FILE" >&2
108
+ exit 1
109
+ fi
110
+ set -a
111
+ # shellcheck disable=SC1090
112
+ . "$ENV_FILE"
113
+ set +a
114
+ fi
115
+
116
+ LOCAL_PORT="${SEELE_LOCAL_PROXY_PORT:-55860}"
117
+ LOCAL_ADDR="${SEELE_LOCAL_PROXY_ADDR:-http://127.0.0.1:${LOCAL_PORT}}"
118
+
119
+ # Choose a writable runtime location for pid/log.
120
+ RUNTIME_BASE=""
121
+ if [ -n "${SEELE_ROOT:-}" ] && [ -d "${SEELE_ROOT}/.runtime" ]; then
122
+ RUNTIME_BASE="${SEELE_ROOT}/.runtime"
123
+ elif [ -n "${SEELE_RUNTIME_DIR:-}" ] && [ -d "${SEELE_RUNTIME_DIR}" ]; then
124
+ RUNTIME_BASE="${SEELE_RUNTIME_DIR}"
125
+ fi
126
+ if [ -n "$RUNTIME_BASE" ]; then
127
+ PID_FILE="${SEELE_PROXY_PID_FILE:-${RUNTIME_BASE}/prepare-proxy.pid}"
128
+ LOG_FILE="${SEELE_PROXY_LOG_FILE:-${RUNTIME_BASE}/prepare-proxy.log}"
129
+ else
130
+ PID_FILE="${SEELE_PROXY_PID_FILE:-/tmp/seele-prepare-proxy.pid}"
131
+ LOG_FILE="${SEELE_PROXY_LOG_FILE:-/tmp/seele-prepare-proxy.log}"
132
+ fi
133
+
134
+ is_running() {
135
+ # Returns 0 if a local proxy we manage is still alive.
136
+ if [ -f "$PID_FILE" ]; then
137
+ local pid
138
+ pid="$(cat "$PID_FILE" 2>/dev/null || true)"
139
+ if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
140
+ return 0
141
+ fi
142
+ fi
143
+ return 1
144
+ }
145
+
146
+ port_listening() {
147
+ if command -v ss >/dev/null 2>&1; then
148
+ ss -tlnH "( sport = :${LOCAL_PORT} )" 2>/dev/null | grep -q ":${LOCAL_PORT}"
149
+ else
150
+ return 1
151
+ fi
152
+ }
153
+
154
+ stop_proxy() {
155
+ if is_running; then
156
+ local pid
157
+ pid="$(cat "$PID_FILE")"
158
+ kill "$pid" 2>/dev/null || true
159
+ sleep 1
160
+ kill -9 "$pid" 2>/dev/null || true
161
+ fi
162
+ rm -f "$PID_FILE"
163
+ }
164
+
165
+ case "$ACTION" in
166
+ status)
167
+ if is_running; then
168
+ echo "local proxy: RUNNING (pid $(cat "$PID_FILE"), $LOCAL_ADDR)"
169
+ exit 0
170
+ fi
171
+ if port_listening; then
172
+ echo "local proxy: port ${LOCAL_PORT} is listening but not managed by this script"
173
+ exit 0
174
+ fi
175
+ echo "local proxy: NOT running"
176
+ exit 1
177
+ ;;
178
+ stop)
179
+ stop_proxy
180
+ echo "local proxy: stopped"
181
+ exit 0
182
+ ;;
183
+ esac
184
+
185
+ # --- start ---
186
+
187
+ if [ -z "${SEELE_UPSTREAM_PROXY:-}" ]; then
188
+ echo "SEELE_UPSTREAM_PROXY is required (real upstream proxy WITH credentials)." >&2
189
+ echo "Set it in seele.env, e.g.:" >&2
190
+ echo " SEELE_UPSTREAM_PROXY=socks5h://user:password@47.77.237.69:28888" >&2
191
+ echo "And set SEELE_PROXY to the local entrypoint so Codex uses it:" >&2
192
+ echo " SEELE_PROXY=${LOCAL_ADDR}" >&2
193
+ exit 1
194
+ fi
195
+
196
+ # Guard against a misconfiguration where the upstream points back at the
197
+ # local entrypoint (would create a forwarding loop).
198
+ case "$SEELE_UPSTREAM_PROXY" in
199
+ *127.0.0.1:${LOCAL_PORT}*|*localhost:${LOCAL_PORT}*)
200
+ echo "SEELE_UPSTREAM_PROXY must point at the real upstream exit, not the" >&2
201
+ echo "local entrypoint (${LOCAL_ADDR}). Fix seele.env." >&2
202
+ exit 1
203
+ ;;
204
+ esac
205
+
206
+ # Normalize the upstream URL into a gost -F forward URL.
207
+ # gost forwarder does not understand the "h" suffix (socks5h); it always
208
+ # resolves the destination at the proxy side, so socks5h -> socks5.
209
+ UPSTREAM="$SEELE_UPSTREAM_PROXY"
210
+ case "$UPSTREAM" in
211
+ socks5h://*) UPSTREAM="socks5://${UPSTREAM#socks5h://}" ;;
212
+ esac
213
+
214
+ # Locate gost binary.
215
+ GOST_BIN="${SEELE_GOST_BIN:-}"
216
+ if [ -z "$GOST_BIN" ]; then
217
+ if command -v gost >/dev/null 2>&1; then
218
+ GOST_BIN="$(command -v gost)"
219
+ elif [ -n "${SEELE_ROOT:-}" ] && [ -x "${SEELE_ROOT}/gost" ]; then
220
+ GOST_BIN="${SEELE_ROOT}/gost"
221
+ elif [ -x "${ROOT_DIR}/gost" ]; then
222
+ GOST_BIN="${ROOT_DIR}/gost"
223
+ fi
224
+ fi
225
+ if [ -z "$GOST_BIN" ] || [ ! -x "$GOST_BIN" ]; then
226
+ echo "gost binary not found." >&2
227
+ echo "Install gost and either put it on PATH, set SEELE_GOST_BIN," >&2
228
+ echo "or place it at \$SEELE_ROOT/gost." >&2
229
+ exit 1
230
+ fi
231
+
232
+ # Idempotent: if already running, restart cleanly to pick up config changes.
233
+ if is_running; then
234
+ echo "local proxy already running (pid $(cat "$PID_FILE")), restarting..."
235
+ stop_proxy
236
+ fi
237
+
238
+ if port_listening; then
239
+ echo "Port ${LOCAL_PORT} is already in use by another process." >&2
240
+ echo "Set SEELE_LOCAL_PROXY_PORT to a free port, or stop the other process." >&2
241
+ exit 1
242
+ fi
243
+
244
+ # Start the local no-auth HTTP+SOCKS entrypoint (-L=http://:PORT has no creds)
245
+ # forwarding to the credentialed upstream (-F).
246
+ nohup "$GOST_BIN" -L="http://:${LOCAL_PORT}" -F="$UPSTREAM" \
247
+ > "$LOG_FILE" 2>&1 &
248
+ echo $! > "$PID_FILE"
249
+
250
+ # Wait for the listener to come up.
251
+ ok=0
252
+ for _ in 1 2 3 4 5 6 7 8 9 10; do
253
+ if port_listening; then ok=1; break; fi
254
+ sleep 0.3
255
+ done
256
+
257
+ if [ "$ok" != "1" ]; then
258
+ echo "local proxy failed to start; see $LOG_FILE" >&2
259
+ tail -n 20 "$LOG_FILE" >&2 || true
260
+ exit 1
261
+ fi
262
+
263
+ echo "local proxy ready."
264
+ echo " listen : ${LOCAL_ADDR} (no auth)"
265
+ echo " upstream: ${UPSTREAM%%@*}@*** (creds from SEELE_UPSTREAM_PROXY)"
266
+ echo " pid : $(cat "$PID_FILE")"
267
+ echo " log : ${LOG_FILE}"
268
+ echo
269
+ echo "Make sure seele.env has SEELE_PROXY pointing at this entrypoint:"
270
+ echo " SEELE_PROXY=${LOCAL_ADDR}"
271
+ echo
272
+ echo "Other scripts can use this proxy directly:"
273
+ echo " export HTTP_PROXY=${LOCAL_ADDR} HTTPS_PROXY=${LOCAL_ADDR} ALL_PROXY=${LOCAL_ADDR}"
@@ -0,0 +1,75 @@
1
+ # Copy this file to seele.env and edit it on the target Linux host or pod.
2
+ # Do not commit seele.env. It can contain proxy credentials and Codex auth data.
3
+
4
+ # Confirm these with the package owner or target-environment owner before
5
+ # running bootstrap.sh. Do not invent them.
6
+ #
7
+ # Public listen address and port for the single Seele Codex service.
8
+ # Use 0.0.0.0 only when the service must be reachable from outside the pod.
9
+ SEELE_CODEX_HOST=0.0.0.0
10
+ SEELE_CODEX_PORT=3000
11
+
12
+ # Required to bootstrap the first admin when SEELE_CODEX_HOST is not loopback.
13
+ # Store it in the deployment secret store or the uncommitted seele.env file.
14
+ SEELE_AUTH_USERNAME=admin
15
+ SEELE_AUTH_PASSWORD=
16
+ # SEELE_AUTH_SESSION_TTL_SECONDS=2592000
17
+
18
+ # Public base path used by the reverse proxy. Use "/" only when exposed at
19
+ # domain root. If exposed under a subpath, use the actual externally visible
20
+ # prefix confirmed by the deployment owner.
21
+ SEELE_PUBLIC_BASE_PATH=/
22
+
23
+ # Required: confirm this with the package owner or target-environment owner.
24
+ # SEELE_ROOT is the single root directory for this Seele deployment:
25
+ # Codex runtime state: $SEELE_ROOT/.runtime
26
+ # Seele workspace data: $SEELE_ROOT/workspaces
27
+ SEELE_ROOT=
28
+
29
+ # Advanced overrides. Leave these unset unless the package owner confirms a
30
+ # different layout.
31
+ # SEELE_RUNTIME_DIR=$SEELE_ROOT/.runtime
32
+ # SEELE_CODEX_WORKSPACE_ROOT=$SEELE_ROOT/workspaces
33
+
34
+ # SEELE_PROXY is injected into the Codex subprocess (ALL_PROXY/HTTP_PROXY/...).
35
+ # Some Codex HTTP clients (models refresh / MCP) issue a bare HTTP CONNECT
36
+ # WITHOUT proxy credentials; an upstream proxy that requires auth replies 407
37
+ # and resets the stream (models/MCP fail while the main answer still works).
38
+ #
39
+ # Solution: point SEELE_PROXY at a LOCAL no-auth entrypoint, and let
40
+ # scripts/deploy/prepare-proxy.sh run a local gost that forwards to the real
41
+ # authenticated upstream. Run prepare-proxy.sh before start.sh.
42
+ #
43
+ # SEELE_PROXY -> local no-auth entrypoint Codex talks to
44
+ # SEELE_UPSTREAM_PROXY -> real upstream with credentials (only the script holds it)
45
+ #
46
+ # Default local entrypoint port is 55860 (override via SEELE_LOCAL_PROXY_PORT).
47
+ SEELE_PROXY=http://127.0.0.1:55860
48
+
49
+ # Real upstream proxy with credentials. Used ONLY by prepare-proxy.sh as the
50
+ # gost forward target (-F). Ask the package owner for the exact value.
51
+ # Format: scheme://username:password@host:port (socks5h:// or http:// etc.)
52
+ # Example:
53
+ # SEELE_UPSTREAM_PROXY=socks5h://user:password@proxy.example.com:28888
54
+ SEELE_UPSTREAM_PROXY=
55
+ NO_PROXY=127.0.0.1,localhost,.svc,.cluster.local
56
+
57
+ # Authentication mode for bootstrap.sh:
58
+ # device Run `codex login --device-auth` if CODEX_HOME/auth.json is missing.
59
+ # auth-json Copy CODEX_AUTH_JSON into CODEX_HOME/auth.json.
60
+ # token Pipe CODEX_ACCESS_TOKEN to `codex login --with-access-token`.
61
+ # none Skip Codex authentication.
62
+ SEELE_DEPLOY_AUTH_MODE=device
63
+
64
+ # Required only for SEELE_DEPLOY_AUTH_MODE=auth-json.
65
+ # CODEX_AUTH_JSON=/path/to/auth.json
66
+
67
+ # Required only for SEELE_DEPLOY_AUTH_MODE=token.
68
+ # CODEX_ACCESS_TOKEN=
69
+
70
+ # Optional Codex home. The managed CLI path is always
71
+ # $SEELE_RUNTIME_DIR/bin/codex so bootstrap and Seele's updater use the same file.
72
+ # CODEX_HOME=$SEELE_ROOT/.runtime/codex-home
73
+
74
+ # Optional corporate CA bundle for Codex login and HTTPS calls.
75
+ # CODEX_CA_CERTIFICATE=/path/to/company-ca.pem