codeksei 0.1.0
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/LICENSE +661 -0
- package/README.en.md +215 -0
- package/README.md +259 -0
- package/bin/codeksei.js +10 -0
- package/bin/cyberboss.js +11 -0
- package/package.json +86 -0
- package/scripts/install-background-tasks.ps1 +135 -0
- package/scripts/open_shared_wechat_thread.sh +94 -0
- package/scripts/open_wechat_thread.sh +117 -0
- package/scripts/shared-common.js +791 -0
- package/scripts/shared-open.js +46 -0
- package/scripts/shared-start.js +41 -0
- package/scripts/shared-status.js +74 -0
- package/scripts/shared-supervisor.js +141 -0
- package/scripts/shared-task-runner.ps1 +87 -0
- package/scripts/shared-watchdog.js +290 -0
- package/scripts/show_shared_status.sh +53 -0
- package/scripts/start_shared_app_server.sh +65 -0
- package/scripts/start_shared_wechat.sh +108 -0
- package/scripts/timeline-screenshot.sh +15 -0
- package/scripts/uninstall-background-tasks.ps1 +23 -0
- package/src/adapters/channel/weixin/account-store.js +135 -0
- package/src/adapters/channel/weixin/api-v2.js +258 -0
- package/src/adapters/channel/weixin/api.js +180 -0
- package/src/adapters/channel/weixin/context-token-store.js +84 -0
- package/src/adapters/channel/weixin/index.js +605 -0
- package/src/adapters/channel/weixin/legacy.js +567 -0
- package/src/adapters/channel/weixin/login-common.js +63 -0
- package/src/adapters/channel/weixin/login-legacy.js +124 -0
- package/src/adapters/channel/weixin/login-v2.js +186 -0
- package/src/adapters/channel/weixin/media-mime.js +22 -0
- package/src/adapters/channel/weixin/media-receive.js +370 -0
- package/src/adapters/channel/weixin/media-send.js +331 -0
- package/src/adapters/channel/weixin/message-utils-v2.js +282 -0
- package/src/adapters/channel/weixin/message-utils.js +199 -0
- package/src/adapters/channel/weixin/protocol.js +77 -0
- package/src/adapters/channel/weixin/redact.js +41 -0
- package/src/adapters/channel/weixin/reminder-queue-store.js +101 -0
- package/src/adapters/channel/weixin/sync-buffer-store.js +35 -0
- package/src/adapters/runtime/codex/events.js +252 -0
- package/src/adapters/runtime/codex/index.js +502 -0
- package/src/adapters/runtime/codex/message-utils.js +141 -0
- package/src/adapters/runtime/codex/model-catalog.js +106 -0
- package/src/adapters/runtime/codex/protocol-leak-monitor.js +75 -0
- package/src/adapters/runtime/codex/rpc-client.js +443 -0
- package/src/adapters/runtime/codex/session-store.js +376 -0
- package/src/app/channel-send-file-cli.js +57 -0
- package/src/app/diary-write-cli.js +620 -0
- package/src/app/note-auto-cli.js +201 -0
- package/src/app/note-sync-cli.js +130 -0
- package/src/app/project-radar-cli.js +165 -0
- package/src/app/reminder-write-cli.js +210 -0
- package/src/app/review-cli.js +134 -0
- package/src/app/system-checkin-poller.js +100 -0
- package/src/app/system-send-cli.js +129 -0
- package/src/app/timeline-event-cli.js +273 -0
- package/src/app/timeline-screenshot-cli.js +109 -0
- package/src/core/app.js +1810 -0
- package/src/core/branding.js +167 -0
- package/src/core/command-registry.js +609 -0
- package/src/core/config.js +84 -0
- package/src/core/default-targets.js +163 -0
- package/src/core/durable-note-schema.js +325 -0
- package/src/core/instructions-template.js +31 -0
- package/src/core/note-sync.js +433 -0
- package/src/core/project-radar.js +402 -0
- package/src/core/review-semantic.js +524 -0
- package/src/core/review.js +1081 -0
- package/src/core/shared-bridge-heartbeat.js +140 -0
- package/src/core/stream-delivery.js +990 -0
- package/src/core/system-message-dispatcher.js +68 -0
- package/src/core/system-message-queue-store.js +128 -0
- package/src/core/thread-state-store.js +135 -0
- package/src/core/timeline-screenshot-queue-store.js +134 -0
- package/src/core/workspace-alias.js +163 -0
- package/src/core/workspace-bootstrap.js +338 -0
- package/src/index.js +270 -0
- package/src/integrations/timeline/index.js +191 -0
- package/templates/weixin-instructions.md +53 -0
- package/templates/weixin-operations.md +69 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[int]$WatchdogMinutes = 5
|
|
3
|
+
)
|
|
4
|
+
|
|
5
|
+
$ErrorActionPreference = "Stop"
|
|
6
|
+
|
|
7
|
+
if ($WatchdogMinutes -lt 1) {
|
|
8
|
+
throw "WatchdogMinutes 必须大于等于 1"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
$runnerPath = Join-Path $PSScriptRoot "shared-task-runner.ps1"
|
|
12
|
+
$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
|
|
13
|
+
$taskNames = @{
|
|
14
|
+
start = "Codeksei Shared Start"
|
|
15
|
+
unlock = "Codeksei Shared Unlock"
|
|
16
|
+
resume = "Codeksei Shared Resume"
|
|
17
|
+
watchdog = "Codeksei Shared Watchdog"
|
|
18
|
+
}
|
|
19
|
+
$legacyTaskNames = @(
|
|
20
|
+
"Cyberboss Shared Start",
|
|
21
|
+
"Cyberboss Shared Unlock",
|
|
22
|
+
"Cyberboss Shared Resume",
|
|
23
|
+
"Cyberboss Shared Watchdog"
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
function Escape-XmlText {
|
|
27
|
+
param([string]$Value)
|
|
28
|
+
[System.Security.SecurityElement]::Escape($Value)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function Register-CyberbossTaskXml {
|
|
32
|
+
param(
|
|
33
|
+
[string]$TaskName,
|
|
34
|
+
[string]$TriggerXml,
|
|
35
|
+
[string]$ArgumentsXml
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
$escapedUser = Escape-XmlText $currentUser
|
|
39
|
+
$taskXml = @"
|
|
40
|
+
<?xml version="1.0" encoding="UTF-16"?>
|
|
41
|
+
<Task version="1.3" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
|
42
|
+
<RegistrationInfo>
|
|
43
|
+
<URI>\$TaskName</URI>
|
|
44
|
+
<SecurityDescriptor></SecurityDescriptor>
|
|
45
|
+
</RegistrationInfo>
|
|
46
|
+
<Triggers>
|
|
47
|
+
$TriggerXml
|
|
48
|
+
</Triggers>
|
|
49
|
+
<Principals>
|
|
50
|
+
<Principal id="Author">
|
|
51
|
+
<UserId>$escapedUser</UserId>
|
|
52
|
+
<LogonType>InteractiveToken</LogonType>
|
|
53
|
+
<RunLevel>LeastPrivilege</RunLevel>
|
|
54
|
+
</Principal>
|
|
55
|
+
</Principals>
|
|
56
|
+
<Settings>
|
|
57
|
+
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
|
|
58
|
+
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
|
|
59
|
+
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
|
|
60
|
+
<AllowHardTerminate>true</AllowHardTerminate>
|
|
61
|
+
<StartWhenAvailable>true</StartWhenAvailable>
|
|
62
|
+
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
|
|
63
|
+
<IdleSettings>
|
|
64
|
+
<Duration>PT10M</Duration>
|
|
65
|
+
<WaitTimeout>PT1H</WaitTimeout>
|
|
66
|
+
<StopOnIdleEnd>true</StopOnIdleEnd>
|
|
67
|
+
<RestartOnIdle>false</RestartOnIdle>
|
|
68
|
+
</IdleSettings>
|
|
69
|
+
<AllowStartOnDemand>true</AllowStartOnDemand>
|
|
70
|
+
<Enabled>true</Enabled>
|
|
71
|
+
<Hidden>false</Hidden>
|
|
72
|
+
<RunOnlyIfIdle>false</RunOnlyIfIdle>
|
|
73
|
+
<DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
|
|
74
|
+
<UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
|
|
75
|
+
<WakeToRun>false</WakeToRun>
|
|
76
|
+
<ExecutionTimeLimit>PT10M</ExecutionTimeLimit>
|
|
77
|
+
<Priority>7</Priority>
|
|
78
|
+
</Settings>
|
|
79
|
+
<Actions Context="Author">
|
|
80
|
+
<Exec>
|
|
81
|
+
<Command>powershell.exe</Command>
|
|
82
|
+
<Arguments>$ArgumentsXml</Arguments>
|
|
83
|
+
</Exec>
|
|
84
|
+
</Actions>
|
|
85
|
+
</Task>
|
|
86
|
+
"@
|
|
87
|
+
|
|
88
|
+
Register-ScheduledTask -TaskName $TaskName -Xml $taskXml -Force | Out-Null
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
foreach ($taskName in @($taskNames.start, $taskNames.unlock, $taskNames.resume, $taskNames.watchdog) + $legacyTaskNames) {
|
|
92
|
+
try {
|
|
93
|
+
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction Stop | Out-Null
|
|
94
|
+
} catch {
|
|
95
|
+
# best effort; task may not exist yet
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
$bootstrapArguments = Escape-XmlText "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$runnerPath`" -Mode Start -IntervalMinutes $WatchdogMinutes"
|
|
100
|
+
$escapedUser = Escape-XmlText $currentUser
|
|
101
|
+
$logonTriggerXml = @"
|
|
102
|
+
<LogonTrigger>
|
|
103
|
+
<Enabled>true</Enabled>
|
|
104
|
+
<UserId>$escapedUser</UserId>
|
|
105
|
+
</LogonTrigger>
|
|
106
|
+
"@
|
|
107
|
+
$unlockTriggerXml = @"
|
|
108
|
+
<SessionStateChangeTrigger>
|
|
109
|
+
<Enabled>true</Enabled>
|
|
110
|
+
<StateChange>SessionUnlock</StateChange>
|
|
111
|
+
<UserId>$escapedUser</UserId>
|
|
112
|
+
</SessionStateChangeTrigger>
|
|
113
|
+
"@
|
|
114
|
+
$resumeTriggerXml = @"
|
|
115
|
+
<EventTrigger>
|
|
116
|
+
<Enabled>true</Enabled>
|
|
117
|
+
<Subscription><![CDATA[<QueryList><Query Id="0" Path="System"><Select Path="System">*[System[Provider[@Name='Microsoft-Windows-Power-Troubleshooter'] and EventID=1]]</Select></Query></QueryList>]]></Subscription>
|
|
118
|
+
</EventTrigger>
|
|
119
|
+
"@
|
|
120
|
+
|
|
121
|
+
# Use short-lived event-driven bootstrap tasks instead of a periodic task.
|
|
122
|
+
# The detached supervisor keeps idle checks quiet, while logon/unlock/resume
|
|
123
|
+
# pokes recover quickly after session lifecycle changes without relaunching a
|
|
124
|
+
# watchdog shell every few minutes.
|
|
125
|
+
Register-CyberbossTaskXml -TaskName $taskNames.start -TriggerXml $logonTriggerXml -ArgumentsXml $bootstrapArguments
|
|
126
|
+
Register-CyberbossTaskXml -TaskName $taskNames.unlock -TriggerXml $unlockTriggerXml -ArgumentsXml $bootstrapArguments
|
|
127
|
+
Register-CyberbossTaskXml -TaskName $taskNames.resume -TriggerXml $resumeTriggerXml -ArgumentsXml $bootstrapArguments
|
|
128
|
+
|
|
129
|
+
Start-ScheduledTask -TaskName $taskNames.start
|
|
130
|
+
|
|
131
|
+
Write-Host "installed=$($taskNames.start)"
|
|
132
|
+
Write-Host "installed=$($taskNames.unlock)"
|
|
133
|
+
Write-Host "installed=$($taskNames.resume)"
|
|
134
|
+
Write-Host "removed=$($taskNames.watchdog)"
|
|
135
|
+
Write-Host "supervisor_interval_minutes=$WatchdogMinutes"
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/bin/zsh
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
5
|
+
PORT="${CODEKSEI_SHARED_PORT:-${CYBERBOSS_SHARED_PORT:-8765}}"
|
|
6
|
+
REMOTE_URL="ws://127.0.0.1:${PORT}"
|
|
7
|
+
STATE_DIR="${CODEKSEI_STATE_DIR:-${CYBERBOSS_STATE_DIR:-$HOME/.codeksei}}"
|
|
8
|
+
if [[ ! -d "${STATE_DIR}" && -d "$HOME/.cyberboss" ]]; then
|
|
9
|
+
STATE_DIR="$HOME/.cyberboss"
|
|
10
|
+
fi
|
|
11
|
+
LOG_DIR="${STATE_DIR}/logs"
|
|
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
|
+
|
|
21
|
+
function list_bridge_processes() {
|
|
22
|
+
ps -ax -o pid=,ppid=,command= | awk '/node \.\/bin\/(codeksei|cyberboss)\.js start --checkin/ { print }'
|
|
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
|
|
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
|
+
|
|
90
|
+
echo "shared codeksei running pid=${EXISTING_PID} endpoint=${REMOTE_URL}"
|
|
91
|
+
|
|
92
|
+
export CODEKSEI_CODEX_ENDPOINT="${REMOTE_URL}"
|
|
93
|
+
export CYBERBOSS_CODEX_ENDPOINT="${REMOTE_URL}"
|
|
94
|
+
exec "${ROOT_DIR}/scripts/open_wechat_thread.sh" "$@"
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/bin/zsh
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
PORT="${CODEKSEI_SHARED_PORT:-${CYBERBOSS_SHARED_PORT:-8765}}"
|
|
5
|
+
REMOTE_URL="${CODEKSEI_CODEX_ENDPOINT:-${CYBERBOSS_CODEX_ENDPOINT:-ws://127.0.0.1:${PORT}}}"
|
|
6
|
+
STATE_DIR="${CODEKSEI_STATE_DIR:-${CYBERBOSS_STATE_DIR:-$HOME/.codeksei}}"
|
|
7
|
+
if [[ ! -d "${STATE_DIR}" && -d "$HOME/.cyberboss" ]]; then
|
|
8
|
+
STATE_DIR="$HOME/.cyberboss"
|
|
9
|
+
fi
|
|
10
|
+
SESSION_FILE="${CODEKSEI_SESSIONS_FILE:-${CYBERBOSS_SESSIONS_FILE:-${STATE_DIR}/sessions.json}}"
|
|
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
|
+
|
|
117
|
+
exec codex resume "${THREAD_ID}" --remote "${REMOTE_URL}" -C "${RESOLVED_WORKSPACE_ROOT}" "$@"
|