codeksei 0.1.0 → 0.1.1

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 (68) hide show
  1. package/LICENSE +661 -661
  2. package/README.en.md +109 -47
  3. package/README.md +79 -58
  4. package/bin/cyberboss.js +1 -1
  5. package/package.json +86 -86
  6. package/scripts/open_shared_wechat_thread.sh +77 -77
  7. package/scripts/open_wechat_thread.sh +108 -108
  8. package/scripts/shared-common.js +144 -144
  9. package/scripts/shared-open.js +14 -14
  10. package/scripts/shared-start.js +5 -5
  11. package/scripts/shared-status.js +27 -27
  12. package/scripts/show_shared_status.sh +45 -45
  13. package/scripts/start_shared_app_server.sh +52 -52
  14. package/scripts/start_shared_wechat.sh +94 -94
  15. package/scripts/timeline-screenshot.sh +14 -14
  16. package/src/adapters/channel/weixin/account-store.js +99 -99
  17. package/src/adapters/channel/weixin/api-v2.js +50 -50
  18. package/src/adapters/channel/weixin/api.js +169 -169
  19. package/src/adapters/channel/weixin/context-token-store.js +84 -84
  20. package/src/adapters/channel/weixin/index.js +618 -604
  21. package/src/adapters/channel/weixin/legacy.js +579 -566
  22. package/src/adapters/channel/weixin/media-mime.js +22 -22
  23. package/src/adapters/channel/weixin/media-receive.js +370 -370
  24. package/src/adapters/channel/weixin/media-send.js +102 -102
  25. package/src/adapters/channel/weixin/message-utils-v2.js +282 -282
  26. package/src/adapters/channel/weixin/message-utils.js +199 -199
  27. package/src/adapters/channel/weixin/redact.js +41 -41
  28. package/src/adapters/channel/weixin/reminder-queue-store.js +101 -101
  29. package/src/adapters/channel/weixin/sync-buffer-store.js +35 -35
  30. package/src/adapters/runtime/codex/events.js +215 -215
  31. package/src/adapters/runtime/codex/index.js +109 -104
  32. package/src/adapters/runtime/codex/message-utils.js +95 -95
  33. package/src/adapters/runtime/codex/model-catalog.js +106 -106
  34. package/src/adapters/runtime/codex/protocol-leak-monitor.js +75 -75
  35. package/src/adapters/runtime/codex/rpc-client.js +339 -339
  36. package/src/adapters/runtime/codex/session-store.js +286 -286
  37. package/src/app/channel-send-file-cli.js +57 -57
  38. package/src/app/diary-write-cli.js +236 -88
  39. package/src/app/note-sync-cli.js +2 -2
  40. package/src/app/reminder-write-cli.js +215 -210
  41. package/src/app/review-cli.js +7 -5
  42. package/src/app/system-checkin-poller.js +64 -64
  43. package/src/app/system-send-cli.js +129 -129
  44. package/src/app/timeline-event-cli.js +28 -25
  45. package/src/app/timeline-screenshot-cli.js +103 -100
  46. package/src/core/app.js +1763 -1763
  47. package/src/core/branding.js +2 -1
  48. package/src/core/command-registry.js +381 -369
  49. package/src/core/config.js +30 -14
  50. package/src/core/default-targets.js +163 -163
  51. package/src/core/durable-note-schema.js +9 -8
  52. package/src/core/instructions-template.js +17 -16
  53. package/src/core/note-sync.js +8 -7
  54. package/src/core/path-utils.js +54 -0
  55. package/src/core/project-radar.js +11 -10
  56. package/src/core/review.js +48 -50
  57. package/src/core/stream-delivery.js +1162 -983
  58. package/src/core/system-message-dispatcher.js +68 -68
  59. package/src/core/system-message-queue-store.js +128 -128
  60. package/src/core/thread-state-store.js +96 -96
  61. package/src/core/timeline-screenshot-queue-store.js +134 -134
  62. package/src/core/timezone.js +436 -0
  63. package/src/core/workspace-bootstrap.js +9 -1
  64. package/src/index.js +148 -146
  65. package/src/integrations/timeline/index.js +130 -74
  66. package/src/integrations/timeline/state-sync.js +240 -0
  67. package/templates/weixin-instructions.md +12 -38
  68. package/templates/weixin-operations.md +29 -31
package/package.json CHANGED
@@ -1,86 +1,86 @@
1
- {
2
- "name": "codeksei",
3
- "version": "0.1.0",
4
- "description": "Local-first life-assistant agent bridge for Codex, WeChat, timeline, diary, and review workflows.",
5
- "license": "AGPL-3.0-only",
6
- "private": false,
7
- "type": "commonjs",
8
- "main": "src/index.js",
9
- "repository": {
10
- "type": "git",
11
- "url": "git+https://github.com/Sapientropic/codeksei.git"
12
- },
13
- "homepage": "https://github.com/Sapientropic/codeksei#readme",
14
- "bugs": {
15
- "url": "https://github.com/Sapientropic/codeksei/issues"
16
- },
17
- "bin": {
18
- "codeksei": "bin/codeksei.js",
19
- "cyberboss": "bin/cyberboss.js"
20
- },
21
- "files": [
22
- "bin",
23
- "src",
24
- "scripts",
25
- "templates",
26
- "README.en.md"
27
- ],
28
- "keywords": [
29
- "codeksei",
30
- "codex",
31
- "wechat",
32
- "weixin",
33
- "timeline",
34
- "review",
35
- "life-assistant"
36
- ],
37
- "engines": {
38
- "node": ">=22"
39
- },
40
- "publishConfig": {
41
- "access": "public"
42
- },
43
- "scripts": {
44
- "start": "node ./bin/codeksei.js start",
45
- "start:checkin": "node ./bin/codeksei.js start --checkin",
46
- "login": "node ./bin/codeksei.js login",
47
- "accounts": "node ./bin/codeksei.js accounts",
48
- "doctor": "node ./bin/codeksei.js doctor",
49
- "help": "node ./bin/codeksei.js help",
50
- "shared:start": "node ./scripts/shared-start.js",
51
- "shared:open": "node ./scripts/shared-open.js",
52
- "shared:status": "node ./scripts/shared-status.js",
53
- "shared:supervisor": "node ./scripts/shared-supervisor.js",
54
- "shared:watchdog": "node ./scripts/shared-watchdog.js",
55
- "background:install": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File ./scripts/install-background-tasks.ps1",
56
- "background:uninstall": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File ./scripts/uninstall-background-tasks.ps1",
57
- "channel:send-file": "node ./bin/codeksei.js channel send-file",
58
- "note:auto": "node ./bin/codeksei.js note auto",
59
- "note:maybe": "node ./bin/codeksei.js note maybe",
60
- "note:sync": "node ./bin/codeksei.js note sync",
61
- "project:radar": "node ./bin/codeksei.js project radar",
62
- "review:nightly": "node ./bin/codeksei.js review nightly",
63
- "review:weekly": "node ./bin/codeksei.js review weekly",
64
- "review:monthly": "node ./bin/codeksei.js review monthly",
65
- "reminder:write": "node ./bin/codeksei.js reminder write",
66
- "diary:write": "node ./bin/codeksei.js diary write",
67
- "system:send": "node ./bin/codeksei.js system send",
68
- "system:checkin": "node ./bin/codeksei.js system checkin-poller",
69
- "timeline:event": "node ./bin/codeksei.js timeline event",
70
- "timeline:write": "node ./bin/codeksei.js timeline write",
71
- "timeline:read": "node ./bin/codeksei.js timeline read",
72
- "timeline:categories": "node ./bin/codeksei.js timeline categories",
73
- "timeline:proposals": "node ./bin/codeksei.js timeline proposals",
74
- "timeline:build": "node ./bin/codeksei.js timeline build",
75
- "timeline:serve": "node ./bin/codeksei.js timeline serve",
76
- "timeline:dev": "node ./bin/codeksei.js timeline dev",
77
- "timeline:screenshot": "node ./bin/codeksei.js timeline screenshot",
78
- "check": "node --check ./src/index.js && node --check ./src/core/config.js && node --check ./src/core/app.js && node --check ./src/core/default-targets.js && node --check ./src/core/thread-state-store.js && node --check ./src/core/stream-delivery.js && node --check ./src/core/command-registry.js && node --check ./src/core/system-message-queue-store.js && node --check ./src/core/system-message-dispatcher.js && node --check ./src/core/timeline-screenshot-queue-store.js && node --check ./src/core/workspace-alias.js && node --check ./src/core/shared-bridge-heartbeat.js && node --check ./src/core/workspace-bootstrap.js && node --check ./src/core/project-radar.js && node --check ./src/core/note-sync.js && node --check ./src/core/durable-note-schema.js && node --check ./src/core/review.js && node --check ./src/core/review-semantic.js && node --check ./src/app/channel-send-file-cli.js && node --check ./src/app/note-auto-cli.js && node --check ./src/app/note-sync-cli.js && node --check ./src/app/project-radar-cli.js && node --check ./src/app/review-cli.js && node --check ./src/app/diary-write-cli.js && node --check ./src/app/reminder-write-cli.js && node --check ./src/app/system-send-cli.js && node --check ./src/app/system-checkin-poller.js && node --check ./src/app/timeline-event-cli.js && node --check ./src/app/timeline-screenshot-cli.js && node --check ./src/adapters/channel/weixin/index.js && node --check ./src/adapters/channel/weixin/legacy.js && node --check ./src/adapters/channel/weixin/api.js && node --check ./src/adapters/channel/weixin/api-v2.js && node --check ./src/adapters/channel/weixin/protocol.js && node --check ./src/adapters/channel/weixin/login-common.js && node --check ./src/adapters/channel/weixin/login-legacy.js && node --check ./src/adapters/channel/weixin/login-v2.js && node --check ./src/adapters/channel/weixin/account-store.js && node --check ./src/adapters/channel/weixin/context-token-store.js && node --check ./src/adapters/channel/weixin/message-utils.js && node --check ./src/adapters/channel/weixin/message-utils-v2.js && node --check ./src/adapters/channel/weixin/sync-buffer-store.js && node --check ./src/adapters/channel/weixin/media-mime.js && node --check ./src/adapters/channel/weixin/media-send.js && node --check ./src/adapters/channel/weixin/redact.js && node --check ./src/adapters/channel/weixin/reminder-queue-store.js && node --check ./src/adapters/runtime/codex/index.js && node --check ./src/adapters/runtime/codex/events.js && node --check ./src/adapters/runtime/codex/model-catalog.js && node --check ./src/adapters/runtime/codex/message-utils.js && node --check ./src/adapters/runtime/codex/rpc-client.js && node --check ./src/adapters/runtime/codex/session-store.js && node --check ./src/integrations/timeline/index.js && node --check ./scripts/shared-common.js && node --check ./scripts/shared-start.js && node --check ./scripts/shared-open.js && node --check ./scripts/shared-status.js && node --check ./scripts/shared-supervisor.js && node --check ./scripts/shared-watchdog.js"
79
- },
80
- "dependencies": {
81
- "dotenv": "^16.4.7",
82
- "qrcode-terminal": "0.12.0",
83
- "timeline-for-agent": "github:WenXiaoWendy/timeline-for-agent#main",
84
- "ws": "^8.19.0"
85
- }
86
- }
1
+ {
2
+ "name": "codeksei",
3
+ "version": "0.1.1",
4
+ "description": "Local-first life-assistant agent bridge for Codex, WeChat, timeline, diary, and review workflows.",
5
+ "license": "AGPL-3.0-only",
6
+ "private": false,
7
+ "type": "commonjs",
8
+ "main": "src/index.js",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/Sapientropic/codeksei.git"
12
+ },
13
+ "homepage": "https://github.com/Sapientropic/codeksei#readme",
14
+ "bugs": {
15
+ "url": "https://github.com/Sapientropic/codeksei/issues"
16
+ },
17
+ "bin": {
18
+ "codeksei": "bin/codeksei.js",
19
+ "cyberboss": "bin/cyberboss.js"
20
+ },
21
+ "files": [
22
+ "bin",
23
+ "src",
24
+ "scripts",
25
+ "templates",
26
+ "README.en.md"
27
+ ],
28
+ "keywords": [
29
+ "codeksei",
30
+ "codex",
31
+ "wechat",
32
+ "weixin",
33
+ "timeline",
34
+ "review",
35
+ "life-assistant"
36
+ ],
37
+ "engines": {
38
+ "node": ">=22"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "scripts": {
44
+ "start": "node ./bin/codeksei.js start",
45
+ "start:checkin": "node ./bin/codeksei.js start --checkin",
46
+ "login": "node ./bin/codeksei.js login",
47
+ "accounts": "node ./bin/codeksei.js accounts",
48
+ "doctor": "node ./bin/codeksei.js doctor",
49
+ "help": "node ./bin/codeksei.js help",
50
+ "shared:start": "node ./scripts/shared-start.js",
51
+ "shared:open": "node ./scripts/shared-open.js",
52
+ "shared:status": "node ./scripts/shared-status.js",
53
+ "shared:supervisor": "node ./scripts/shared-supervisor.js",
54
+ "shared:watchdog": "node ./scripts/shared-watchdog.js",
55
+ "background:install": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File ./scripts/install-background-tasks.ps1",
56
+ "background:uninstall": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File ./scripts/uninstall-background-tasks.ps1",
57
+ "channel:send-file": "node ./bin/codeksei.js channel send-file",
58
+ "note:auto": "node ./bin/codeksei.js note auto",
59
+ "note:maybe": "node ./bin/codeksei.js note maybe",
60
+ "note:sync": "node ./bin/codeksei.js note sync",
61
+ "project:radar": "node ./bin/codeksei.js project radar",
62
+ "review:nightly": "node ./bin/codeksei.js review nightly",
63
+ "review:weekly": "node ./bin/codeksei.js review weekly",
64
+ "review:monthly": "node ./bin/codeksei.js review monthly",
65
+ "reminder:write": "node ./bin/codeksei.js reminder write",
66
+ "diary:write": "node ./bin/codeksei.js diary write",
67
+ "system:send": "node ./bin/codeksei.js system send",
68
+ "system:checkin": "node ./bin/codeksei.js system checkin-poller",
69
+ "timeline:event": "node ./bin/codeksei.js timeline event",
70
+ "timeline:write": "node ./bin/codeksei.js timeline write",
71
+ "timeline:read": "node ./bin/codeksei.js timeline read",
72
+ "timeline:categories": "node ./bin/codeksei.js timeline categories",
73
+ "timeline:proposals": "node ./bin/codeksei.js timeline proposals",
74
+ "timeline:build": "node ./bin/codeksei.js timeline build",
75
+ "timeline:serve": "node ./bin/codeksei.js timeline serve",
76
+ "timeline:dev": "node ./bin/codeksei.js timeline dev",
77
+ "timeline:screenshot": "node ./bin/codeksei.js timeline screenshot",
78
+ "check": "node --check ./src/index.js && node --check ./src/core/config.js && node --check ./src/core/timezone.js && node --check ./src/core/app.js && node --check ./src/core/default-targets.js && node --check ./src/core/thread-state-store.js && node --check ./src/core/stream-delivery.js && node --check ./src/core/command-registry.js && node --check ./src/core/system-message-queue-store.js && node --check ./src/core/system-message-dispatcher.js && node --check ./src/core/timeline-screenshot-queue-store.js && node --check ./src/core/workspace-alias.js && node --check ./src/core/shared-bridge-heartbeat.js && node --check ./src/core/workspace-bootstrap.js && node --check ./src/core/project-radar.js && node --check ./src/core/note-sync.js && node --check ./src/core/durable-note-schema.js && node --check ./src/core/review.js && node --check ./src/core/review-semantic.js && node --check ./src/app/channel-send-file-cli.js && node --check ./src/app/note-auto-cli.js && node --check ./src/app/note-sync-cli.js && node --check ./src/app/project-radar-cli.js && node --check ./src/app/review-cli.js && node --check ./src/app/diary-write-cli.js && node --check ./src/app/reminder-write-cli.js && node --check ./src/app/system-send-cli.js && node --check ./src/app/system-checkin-poller.js && node --check ./src/app/timeline-event-cli.js && node --check ./src/app/timeline-screenshot-cli.js && node --check ./src/adapters/channel/weixin/index.js && node --check ./src/adapters/channel/weixin/legacy.js && node --check ./src/adapters/channel/weixin/api.js && node --check ./src/adapters/channel/weixin/api-v2.js && node --check ./src/adapters/channel/weixin/protocol.js && node --check ./src/adapters/channel/weixin/login-common.js && node --check ./src/adapters/channel/weixin/login-legacy.js && node --check ./src/adapters/channel/weixin/login-v2.js && node --check ./src/adapters/channel/weixin/account-store.js && node --check ./src/adapters/channel/weixin/context-token-store.js && node --check ./src/adapters/channel/weixin/message-utils.js && node --check ./src/adapters/channel/weixin/message-utils-v2.js && node --check ./src/adapters/channel/weixin/sync-buffer-store.js && node --check ./src/adapters/channel/weixin/media-mime.js && node --check ./src/adapters/channel/weixin/media-send.js && node --check ./src/adapters/channel/weixin/redact.js && node --check ./src/adapters/channel/weixin/reminder-queue-store.js && node --check ./src/adapters/runtime/codex/index.js && node --check ./src/adapters/runtime/codex/events.js && node --check ./src/adapters/runtime/codex/model-catalog.js && node --check ./src/adapters/runtime/codex/message-utils.js && node --check ./src/adapters/runtime/codex/rpc-client.js && node --check ./src/adapters/runtime/codex/session-store.js && node --check ./src/integrations/timeline/index.js && node --check ./src/integrations/timeline/state-sync.js && node --check ./scripts/shared-common.js && node --check ./scripts/shared-start.js && node --check ./scripts/shared-open.js && node --check ./scripts/shared-status.js && node --check ./scripts/shared-supervisor.js && node --check ./scripts/shared-watchdog.js"
79
+ },
80
+ "dependencies": {
81
+ "dotenv": "^16.4.7",
82
+ "qrcode-terminal": "0.12.0",
83
+ "timeline-for-agent": "github:WenXiaoWendy/timeline-for-agent#main",
84
+ "ws": "^8.19.0"
85
+ }
86
+ }
@@ -1,7 +1,7 @@
1
- #!/bin/zsh
2
- set -euo pipefail
3
-
4
- ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
1
+ #!/bin/zsh
2
+ set -euo pipefail
3
+
4
+ ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
5
5
  PORT="${CODEKSEI_SHARED_PORT:-${CYBERBOSS_SHARED_PORT:-8765}}"
6
6
  REMOTE_URL="ws://127.0.0.1:${PORT}"
7
7
  STATE_DIR="${CODEKSEI_STATE_DIR:-${CYBERBOSS_STATE_DIR:-$HOME/.codeksei}}"
@@ -10,83 +10,83 @@ if [[ ! -d "${STATE_DIR}" && -d "$HOME/.cyberboss" ]]; then
10
10
  fi
11
11
  LOG_DIR="${STATE_DIR}/logs"
12
12
  PID_FILE="${LOG_DIR}/shared-wechat.pid"
13
-
14
- mkdir -p "${LOG_DIR}"
15
-
16
- function resolve_pid_cwd() {
17
- local pid="$1"
18
- lsof -a -p "${pid}" -d cwd -Fn 2>/dev/null | sed -n 's/^n//p' | head -n 1
19
- }
20
-
13
+
14
+ mkdir -p "${LOG_DIR}"
15
+
16
+ function resolve_pid_cwd() {
17
+ local pid="$1"
18
+ lsof -a -p "${pid}" -d cwd -Fn 2>/dev/null | sed -n 's/^n//p' | head -n 1
19
+ }
20
+
21
21
  function list_bridge_processes() {
22
22
  ps -ax -o pid=,ppid=,command= | awk '/node \.\/bin\/(codeksei|cyberboss)\.js start --checkin/ { print }'
23
23
  }
24
-
25
- function find_bridge_child_pid() {
26
- local parent_pid="$1"
27
- list_bridge_processes | awk -v target_ppid="${parent_pid}" '$2 == target_ppid { print $1; exit }'
28
- }
29
-
30
- function resolve_bridge_pid() {
31
- local candidate_pid="$1"
32
- [[ -n "${candidate_pid}" ]] || return 1
33
- if ! kill -0 "${candidate_pid}" 2>/dev/null; then
34
- return 1
35
- fi
36
-
37
- local child_pid
38
- child_pid="$(find_bridge_child_pid "${candidate_pid}")"
39
- if [[ -n "${child_pid}" ]]; then
40
- echo "${child_pid}"
41
- return 0
42
- fi
43
-
44
- if [[ "$(resolve_pid_cwd "${candidate_pid}")" == "${ROOT_DIR}" ]]; then
45
- echo "${candidate_pid}"
46
- return 0
47
- fi
48
-
49
- return 1
50
- }
51
-
52
- function find_existing_bridge_pid() {
53
- if [[ -f "${PID_FILE}" ]]; then
54
- local pid_from_file
55
- pid_from_file="$(cat "${PID_FILE}" 2>/dev/null || true)"
56
- local resolved_from_file
57
- resolved_from_file="$(resolve_bridge_pid "${pid_from_file}" || true)"
58
- if [[ -n "${resolved_from_file}" ]]; then
59
- echo "${resolved_from_file}"
60
- return 0
61
- fi
62
- fi
63
-
64
- local pid
65
- while read -r pid _; do
66
- [[ -n "${pid}" ]] || continue
67
- if [[ "$(resolve_pid_cwd "${pid}")" == "${ROOT_DIR}" ]]; then
68
- echo "${pid}"
69
- return 0
70
- fi
71
- done < <(list_bridge_processes)
72
-
73
- return 1
74
- }
75
-
76
- "${ROOT_DIR}/scripts/start_shared_app_server.sh"
77
-
78
- EXISTING_PID="$(find_existing_bridge_pid || true)"
79
-
80
- if [[ -z "${EXISTING_PID}" ]]; then
24
+
25
+ function find_bridge_child_pid() {
26
+ local parent_pid="$1"
27
+ list_bridge_processes | awk -v target_ppid="${parent_pid}" '$2 == target_ppid { print $1; exit }'
28
+ }
29
+
30
+ function resolve_bridge_pid() {
31
+ local candidate_pid="$1"
32
+ [[ -n "${candidate_pid}" ]] || return 1
33
+ if ! kill -0 "${candidate_pid}" 2>/dev/null; then
34
+ return 1
35
+ fi
36
+
37
+ local child_pid
38
+ child_pid="$(find_bridge_child_pid "${candidate_pid}")"
39
+ if [[ -n "${child_pid}" ]]; then
40
+ echo "${child_pid}"
41
+ return 0
42
+ fi
43
+
44
+ if [[ "$(resolve_pid_cwd "${candidate_pid}")" == "${ROOT_DIR}" ]]; then
45
+ echo "${candidate_pid}"
46
+ return 0
47
+ fi
48
+
49
+ return 1
50
+ }
51
+
52
+ function find_existing_bridge_pid() {
53
+ if [[ -f "${PID_FILE}" ]]; then
54
+ local pid_from_file
55
+ pid_from_file="$(cat "${PID_FILE}" 2>/dev/null || true)"
56
+ local resolved_from_file
57
+ resolved_from_file="$(resolve_bridge_pid "${pid_from_file}" || true)"
58
+ if [[ -n "${resolved_from_file}" ]]; then
59
+ echo "${resolved_from_file}"
60
+ return 0
61
+ fi
62
+ fi
63
+
64
+ local pid
65
+ while read -r pid _; do
66
+ [[ -n "${pid}" ]] || continue
67
+ if [[ "$(resolve_pid_cwd "${pid}")" == "${ROOT_DIR}" ]]; then
68
+ echo "${pid}"
69
+ return 0
70
+ fi
71
+ done < <(list_bridge_processes)
72
+
73
+ return 1
74
+ }
75
+
76
+ "${ROOT_DIR}/scripts/start_shared_app_server.sh"
77
+
78
+ EXISTING_PID="$(find_existing_bridge_pid || true)"
79
+
80
+ if [[ -z "${EXISTING_PID}" ]]; then
81
81
  echo "shared codeksei is not running." >&2
82
- echo "start it in a separate terminal and keep it in the foreground:" >&2
83
- echo " cd ${ROOT_DIR}" >&2
84
- echo " ./scripts/start_shared_wechat.sh" >&2
85
- exit 1
86
- fi
87
-
88
- echo "${EXISTING_PID}" > "${PID_FILE}"
89
-
82
+ echo "start it in a separate terminal and keep it in the foreground:" >&2
83
+ echo " cd ${ROOT_DIR}" >&2
84
+ echo " ./scripts/start_shared_wechat.sh" >&2
85
+ exit 1
86
+ fi
87
+
88
+ echo "${EXISTING_PID}" > "${PID_FILE}"
89
+
90
90
  echo "shared codeksei running pid=${EXISTING_PID} endpoint=${REMOTE_URL}"
91
91
 
92
92
  export CODEKSEI_CODEX_ENDPOINT="${REMOTE_URL}"
@@ -1,6 +1,6 @@
1
- #!/bin/zsh
2
- set -euo pipefail
3
-
1
+ #!/bin/zsh
2
+ set -euo pipefail
3
+
4
4
  PORT="${CODEKSEI_SHARED_PORT:-${CYBERBOSS_SHARED_PORT:-8765}}"
5
5
  REMOTE_URL="${CODEKSEI_CODEX_ENDPOINT:-${CYBERBOSS_CODEX_ENDPOINT:-ws://127.0.0.1:${PORT}}}"
6
6
  STATE_DIR="${CODEKSEI_STATE_DIR:-${CYBERBOSS_STATE_DIR:-$HOME/.codeksei}}"
@@ -9,109 +9,109 @@ if [[ ! -d "${STATE_DIR}" && -d "$HOME/.cyberboss" ]]; then
9
9
  fi
10
10
  SESSION_FILE="${CODEKSEI_SESSIONS_FILE:-${CYBERBOSS_SESSIONS_FILE:-${STATE_DIR}/sessions.json}}"
11
11
  WORKSPACE_ROOT="${CODEKSEI_WORKSPACE_ROOT:-${CYBERBOSS_WORKSPACE_ROOT:-$PWD}}"
12
- ACCOUNT_DIR="${STATE_DIR}/accounts"
13
-
14
- if [[ ! -f "${SESSION_FILE}" ]]; then
15
- echo "session file not found: ${SESSION_FILE}" >&2
16
- exit 1
17
- fi
18
-
19
- RESOLVED="$(
20
- node -e '
21
- const fs = require("fs");
22
- const path = require("path");
23
-
24
- const sessionFile = process.argv[1];
25
- const workspaceRoot = process.argv[2];
26
- const accountDir = process.argv[3];
27
- const data = JSON.parse(fs.readFileSync(sessionFile, "utf8"));
28
- const bindings = Object.entries(data.bindings || {}).map(([bindingKey, binding]) => ({ bindingKey, ...(binding || {}) }));
29
-
30
- function normalize(value) {
31
- return typeof value === "string" ? value.trim() : "";
32
- }
33
-
34
- function toTimestamp(value) {
35
- const parsed = Date.parse(normalize(value));
36
- return Number.isFinite(parsed) ? parsed : 0;
37
- }
38
-
39
- function resolveCurrentAccountId(dir) {
40
- const normalizedDir = normalize(dir);
41
- if (!normalizedDir || !fs.existsSync(normalizedDir)) {
42
- return "";
43
- }
44
-
45
- const entries = fs.readdirSync(normalizedDir)
46
- .filter((name) => name.endsWith(".json") && !name.endsWith(".context-tokens.json"))
47
- .map((name) => {
48
- const fullPath = path.join(normalizedDir, name);
49
- try {
50
- const parsed = JSON.parse(fs.readFileSync(fullPath, "utf8"));
51
- return {
52
- accountId: normalize(parsed && parsed.accountId),
53
- savedAt: toTimestamp(parsed && parsed.savedAt),
54
- };
55
- } catch {
56
- return null;
57
- }
58
- })
59
- .filter(Boolean)
60
- .filter((entry) => entry.accountId);
61
-
62
- entries.sort((left, right) => right.savedAt - left.savedAt);
63
- return entries[0]?.accountId || "";
64
- }
65
-
66
- function getThreadId(binding, root) {
67
- const normalizedRoot = normalize(root);
68
- if (!normalizedRoot) {
69
- return "";
70
- }
71
- const map = binding && typeof binding.threadIdByWorkspaceRoot === "object"
72
- ? binding.threadIdByWorkspaceRoot
73
- : {};
74
- return normalize(map[normalizedRoot]);
75
- }
76
-
77
- const normalizedWorkspaceRoot = normalize(workspaceRoot);
78
- const currentAccountId = resolveCurrentAccountId(accountDir);
79
-
80
- const filteredBindings = bindings
81
- .filter((binding) => !currentAccountId || normalize(binding.accountId) === currentAccountId)
82
- .sort((left, right) => toTimestamp(right.updatedAt) - toTimestamp(left.updatedAt));
83
-
84
- const exactBinding = filteredBindings.find((binding) => getThreadId(binding, normalizedWorkspaceRoot));
85
- if (exactBinding) {
86
- process.stdout.write(`${getThreadId(exactBinding, normalizedWorkspaceRoot)}\n${normalizedWorkspaceRoot}`);
87
- process.exit(0);
88
- }
89
-
90
- const activeBinding = filteredBindings.find((binding) => {
91
- const activeWorkspaceRoot = normalize(binding && binding.activeWorkspaceRoot);
92
- return activeWorkspaceRoot && getThreadId(binding, activeWorkspaceRoot);
93
- });
94
- if (activeBinding) {
95
- const activeWorkspaceRoot = normalize(activeBinding.activeWorkspaceRoot);
96
- process.stdout.write(`${getThreadId(activeBinding, activeWorkspaceRoot)}\n${activeWorkspaceRoot}`);
97
- process.exit(0);
98
- }
99
-
100
- process.exit(1);
101
- ' "${SESSION_FILE}" "${WORKSPACE_ROOT}" "${ACCOUNT_DIR}"
102
- )"
103
-
104
- if [[ -z "${RESOLVED}" ]]; then
105
- echo "no bound WeChat thread found for workspace: ${WORKSPACE_ROOT}" >&2
106
- exit 1
107
- fi
108
-
109
- THREAD_ID="${RESOLVED%%$'\n'*}"
110
- RESOLVED_WORKSPACE_ROOT="${RESOLVED#*$'\n'}"
111
-
112
- if [[ -z "${THREAD_ID}" || -z "${RESOLVED_WORKSPACE_ROOT}" ]]; then
113
- echo "failed to resolve bound WeChat thread from: ${SESSION_FILE}" >&2
114
- exit 1
115
- fi
116
-
12
+ ACCOUNT_DIR="${STATE_DIR}/accounts"
13
+
14
+ if [[ ! -f "${SESSION_FILE}" ]]; then
15
+ echo "session file not found: ${SESSION_FILE}" >&2
16
+ exit 1
17
+ fi
18
+
19
+ RESOLVED="$(
20
+ node -e '
21
+ const fs = require("fs");
22
+ const path = require("path");
23
+
24
+ const sessionFile = process.argv[1];
25
+ const workspaceRoot = process.argv[2];
26
+ const accountDir = process.argv[3];
27
+ const data = JSON.parse(fs.readFileSync(sessionFile, "utf8"));
28
+ const bindings = Object.entries(data.bindings || {}).map(([bindingKey, binding]) => ({ bindingKey, ...(binding || {}) }));
29
+
30
+ function normalize(value) {
31
+ return typeof value === "string" ? value.trim() : "";
32
+ }
33
+
34
+ function toTimestamp(value) {
35
+ const parsed = Date.parse(normalize(value));
36
+ return Number.isFinite(parsed) ? parsed : 0;
37
+ }
38
+
39
+ function resolveCurrentAccountId(dir) {
40
+ const normalizedDir = normalize(dir);
41
+ if (!normalizedDir || !fs.existsSync(normalizedDir)) {
42
+ return "";
43
+ }
44
+
45
+ const entries = fs.readdirSync(normalizedDir)
46
+ .filter((name) => name.endsWith(".json") && !name.endsWith(".context-tokens.json"))
47
+ .map((name) => {
48
+ const fullPath = path.join(normalizedDir, name);
49
+ try {
50
+ const parsed = JSON.parse(fs.readFileSync(fullPath, "utf8"));
51
+ return {
52
+ accountId: normalize(parsed && parsed.accountId),
53
+ savedAt: toTimestamp(parsed && parsed.savedAt),
54
+ };
55
+ } catch {
56
+ return null;
57
+ }
58
+ })
59
+ .filter(Boolean)
60
+ .filter((entry) => entry.accountId);
61
+
62
+ entries.sort((left, right) => right.savedAt - left.savedAt);
63
+ return entries[0]?.accountId || "";
64
+ }
65
+
66
+ function getThreadId(binding, root) {
67
+ const normalizedRoot = normalize(root);
68
+ if (!normalizedRoot) {
69
+ return "";
70
+ }
71
+ const map = binding && typeof binding.threadIdByWorkspaceRoot === "object"
72
+ ? binding.threadIdByWorkspaceRoot
73
+ : {};
74
+ return normalize(map[normalizedRoot]);
75
+ }
76
+
77
+ const normalizedWorkspaceRoot = normalize(workspaceRoot);
78
+ const currentAccountId = resolveCurrentAccountId(accountDir);
79
+
80
+ const filteredBindings = bindings
81
+ .filter((binding) => !currentAccountId || normalize(binding.accountId) === currentAccountId)
82
+ .sort((left, right) => toTimestamp(right.updatedAt) - toTimestamp(left.updatedAt));
83
+
84
+ const exactBinding = filteredBindings.find((binding) => getThreadId(binding, normalizedWorkspaceRoot));
85
+ if (exactBinding) {
86
+ process.stdout.write(`${getThreadId(exactBinding, normalizedWorkspaceRoot)}\n${normalizedWorkspaceRoot}`);
87
+ process.exit(0);
88
+ }
89
+
90
+ const activeBinding = filteredBindings.find((binding) => {
91
+ const activeWorkspaceRoot = normalize(binding && binding.activeWorkspaceRoot);
92
+ return activeWorkspaceRoot && getThreadId(binding, activeWorkspaceRoot);
93
+ });
94
+ if (activeBinding) {
95
+ const activeWorkspaceRoot = normalize(activeBinding.activeWorkspaceRoot);
96
+ process.stdout.write(`${getThreadId(activeBinding, activeWorkspaceRoot)}\n${activeWorkspaceRoot}`);
97
+ process.exit(0);
98
+ }
99
+
100
+ process.exit(1);
101
+ ' "${SESSION_FILE}" "${WORKSPACE_ROOT}" "${ACCOUNT_DIR}"
102
+ )"
103
+
104
+ if [[ -z "${RESOLVED}" ]]; then
105
+ echo "no bound WeChat thread found for workspace: ${WORKSPACE_ROOT}" >&2
106
+ exit 1
107
+ fi
108
+
109
+ THREAD_ID="${RESOLVED%%$'\n'*}"
110
+ RESOLVED_WORKSPACE_ROOT="${RESOLVED#*$'\n'}"
111
+
112
+ if [[ -z "${THREAD_ID}" || -z "${RESOLVED_WORKSPACE_ROOT}" ]]; then
113
+ echo "failed to resolve bound WeChat thread from: ${SESSION_FILE}" >&2
114
+ exit 1
115
+ fi
116
+
117
117
  exec codex resume "${THREAD_ID}" --remote "${REMOTE_URL}" -C "${RESOLVED_WORKSPACE_ROOT}" "$@"