@agentsdock/server 1.0.7-beta.5 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -6
- package/package.json +1 -1
- package/server/VERSION +1 -1
- package/server/agent_server.py +5283 -698
- package/server/agentsdock_chats.py +2 -1
- package/server/chat_mailbox.py +23 -6
- package/server/claude_history_repair.py +45 -4
- package/server/claude_model_catalog.py +200 -0
- package/server/claude_sdk_client.py +63 -24
- package/server/claude_side_question.py +1 -8
- package/server/codex_app_server.py +90 -30
- package/server/codex_auth.py +119 -0
- package/server/codex_history_repair.py +79 -14
- package/server/codex_provider.py +160 -77
- package/server/codex_side_question.py +154 -57
- package/server/cursor_agent_client.py +27 -1
- package/server/cursor_api_key.py +64 -0
- package/server/cursor_history.py +219 -0
- package/server/cursor_provider_mcp.py +290 -0
- package/server/execution_durability.py +10 -6
- package/server/execution_preparation.py +6 -2
- package/server/install.sh +282 -78
- package/server/instances.sh +15 -0
- package/server/interactive_chat_native.py +4 -3
- package/server/interactive_chat_projection.py +6 -19
- package/server/interactive_chat_share_routes.py +71 -45
- package/server/interactive_chat_share_web.py +2 -2
- package/server/interactive_chat_shares.py +6 -11
- package/server/local_session_ownership.py +232 -0
- package/server/opencode_agent_client.py +685 -0
- package/server/provider_commands.py +579 -0
- package/server/provider_connections.py +665 -0
- package/server/provider_usage.py +241 -0
- package/server/public_chat_shares.py +60 -62
- package/server/public_chat_transcript.py +9 -31
- package/server/pyproject.toml +1 -0
- package/server/server_instances.py +931 -0
- package/server/shared_chat_video_stream.py +21 -2
- package/server/shared_chat_videos.py +54 -24
- package/server/side_questions.py +493 -10
- package/server/title_generation.py +4 -1
- package/server/uninstall.sh +95 -17
- package/server/update_preparation.py +4 -1
- package/server/update_runner.py +16 -0
- package/server/uv.lock +3 -1
package/server/install.sh
CHANGED
|
@@ -84,6 +84,10 @@ else
|
|
|
84
84
|
STATE_ROOT="$HOME/.agentsdock"
|
|
85
85
|
fi
|
|
86
86
|
SERVICE_NAME="agents-server"
|
|
87
|
+
INSTANCE_NAME="${AGENTS_SERVER_INSTANCE:-default}"
|
|
88
|
+
INSTANCE_EXPLICIT="false"
|
|
89
|
+
LABEL="com.agentsdock.server"
|
|
90
|
+
INSTANCE_LOG_DIR="$HOME/Library/Logs/AgentsServer"
|
|
87
91
|
LEGACY_SERVICE_NAME="zenithbot-agent"
|
|
88
92
|
# AgentsServer's cooperative shutdown has 18 independently bounded cleanup
|
|
89
93
|
# phases in addition to uvicorn's graceful window. Five seconds was shorter
|
|
@@ -141,7 +145,7 @@ SYSTEMD_MANAGED_STOP_ATTEMPTS=50
|
|
|
141
145
|
SYSTEMD_MANAGED_STOP_DELAY=0.1
|
|
142
146
|
SYSTEMD_MANAGED_KILL_ATTEMPTS=20
|
|
143
147
|
|
|
144
|
-
if [[ -t 1 ]] && [[ "${TERM:-}" != "dumb" ]] && [[ -z "${NO_COLOR
|
|
148
|
+
if [[ -t 1 ]] && [[ "${TERM:-}" != "dumb" ]] && [[ -z "${NO_COLOR+x}" ]]; then
|
|
145
149
|
COLOR_GREEN=$'\033[32m'
|
|
146
150
|
COLOR_RED=$'\033[31m'
|
|
147
151
|
COLOR_YELLOW=$'\033[33m'
|
|
@@ -162,13 +166,16 @@ usage() {
|
|
|
162
166
|
cat <<'USAGE'
|
|
163
167
|
Usage: ./install.sh [--port PORT] [--bind ADDRESS] [--release-version VERSION] [--team-hub-host|--reactivate-team-hub-host|--no-team-hub-host] [--team-hub-tailscale-serve-url URL] [--team-hub-direct-ip-url URL] [--non-interactive] [--allow-port-fallback|--no-port-fallback]
|
|
164
168
|
|
|
169
|
+
--instance NAME updates a named instance (use ./instances.sh new to create one
|
|
170
|
+
with an automatically selected name/port). No arguments retain default setup.
|
|
171
|
+
|
|
165
172
|
Installs or updates AgentsServer for the current user. Releases and Python
|
|
166
173
|
runtimes are versioned, the previous healthy release is retained for rollback,
|
|
167
174
|
and existing chat state and generated tokens are preserved. No sudo privileges
|
|
168
175
|
are required.
|
|
169
176
|
|
|
170
|
-
--non-interactive skips
|
|
171
|
-
|
|
177
|
+
--non-interactive skips optional prompts (including clipboard copy); use it for
|
|
178
|
+
unattended/SSH-driven runs.
|
|
172
179
|
|
|
173
180
|
--fresh-install-only refuses an existing installation, state, configuration or
|
|
174
181
|
service. The npm fresh-install command uses it; existing servers update through
|
|
@@ -214,7 +221,8 @@ never silently reactivates preserved state. Without an explicit host option, an
|
|
|
214
221
|
existing host/disabled setting is preserved; new installs default to disabled.
|
|
215
222
|
|
|
216
223
|
--show-token prints the current access token for an already-installed
|
|
217
|
-
AgentsServer
|
|
224
|
+
AgentsServer without reinstalling or restarting. Interactive terminals offer
|
|
225
|
+
optional clipboard copy; redirected output remains just the raw token.
|
|
218
226
|
USAGE
|
|
219
227
|
}
|
|
220
228
|
|
|
@@ -222,6 +230,7 @@ SHOW_TOKEN="false"
|
|
|
222
230
|
|
|
223
231
|
while (($#)); do
|
|
224
232
|
case "$1" in
|
|
233
|
+
--instance) INSTANCE_NAME="${2:?--instance requires a name}"; INSTANCE_EXPLICIT="true"; shift 2 ;;
|
|
225
234
|
--port) PORT="${2:-}"; PORT_EXPLICIT="true"; shift 2 ;;
|
|
226
235
|
--bind) BIND_ADDRESS="${2:-}"; BIND_EXPLICIT="true"; shift 2 ;;
|
|
227
236
|
--release-version) RELEASE_VERSION="${2:-}"; shift 2 ;;
|
|
@@ -340,6 +349,41 @@ while (($#)); do
|
|
|
340
349
|
esac
|
|
341
350
|
done
|
|
342
351
|
|
|
352
|
+
if [[ ! "$INSTANCE_NAME" =~ ^[a-z][a-z0-9-]{0,31}$ ]]; then
|
|
353
|
+
echo "Invalid instance name." >&2
|
|
354
|
+
exit 2
|
|
355
|
+
fi
|
|
356
|
+
if [[ "$INSTANCE_NAME" != "default" || ( "$INSTANCE_EXPLICIT" == "true" && "${AGENTS_SERVER_INSTANCE:-default}" != "default" ) ]]; then
|
|
357
|
+
INSTANCE_SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
358
|
+
instance_bindings="$(bash "$INSTANCE_SCRIPT_DIR/instances.sh" _bindings "$INSTANCE_NAME")" || exit 2
|
|
359
|
+
eval "$instance_bindings"
|
|
360
|
+
# Never inherit the default instance's token, Hub designation or history.
|
|
361
|
+
unset AGENTSDOCK_AGENT_TOKEN ZENITHDOCK_AGENT_TOKEN ZENITHBOT_AGENT_TOKEN
|
|
362
|
+
export AGENTS_SERVER_INSTANCE="$INSTANCE_NAME"
|
|
363
|
+
export AGENTS_SERVER_INSTALL_DIR="$INSTALL_ROOT" AGENTS_SERVER_CONFIG_DIR="$CONFIG_ROOT" AGENTSDOCK_STATE_DIR="$STATE_ROOT"
|
|
364
|
+
[[ -n "${AGENTSDOCK_SERVER_NAME:-}" ]] || export AGENTSDOCK_SERVER_NAME="$INSTANCE_NAME"
|
|
365
|
+
PORT_FALLBACK="false"
|
|
366
|
+
fi
|
|
367
|
+
# Named services keep their independently named legacy unit. The split service
|
|
368
|
+
# protocol currently reserves the default gateway labels; never take them over.
|
|
369
|
+
if [[ "$INSTANCE_NAME" != "default" ]]; then
|
|
370
|
+
if [[ "$EXECUTION_MODE_EXPLICIT" == "true" && "$EXECUTION_MODE" != "legacy" ]]; then
|
|
371
|
+
echo "Named instances currently require --execution-mode legacy; no services were changed." >&2
|
|
372
|
+
exit 2
|
|
373
|
+
fi
|
|
374
|
+
if [[ -e "$INSTALL_ROOT/execution-layout.json" || -L "$INSTALL_ROOT/execution-layout.json" ]]; then
|
|
375
|
+
echo "A named instance cannot use the default split service layout." >&2
|
|
376
|
+
exit 2
|
|
377
|
+
fi
|
|
378
|
+
EXECUTION_MODE="legacy"
|
|
379
|
+
EXECUTION_MODE_EXPLICIT="true"
|
|
380
|
+
fi
|
|
381
|
+
export AGENTS_SERVER_INSTANCE="$INSTANCE_NAME"
|
|
382
|
+
if [[ "$INSTANCE_NAME" != "default" && ! -f "$CONFIG_ROOT/env" && "$PORT_EXPLICIT" != "true" && "$SHOW_TOKEN" != "true" ]]; then
|
|
383
|
+
echo "A new named instance needs --port; use ./instances.sh new for automatic allocation." >&2
|
|
384
|
+
exit 2
|
|
385
|
+
fi
|
|
386
|
+
|
|
343
387
|
if [[ "$PORT_FALLBACK" == "auto" ]]; then
|
|
344
388
|
if [[ "$PORT_EXPLICIT" == "true" ]]; then
|
|
345
389
|
PORT_FALLBACK="false"
|
|
@@ -1278,7 +1322,7 @@ canonical_team_hub_direct_ipv4_url() {
|
|
|
1278
1322
|
|
|
1279
1323
|
LEGACY_ENV_FILE=""
|
|
1280
1324
|
LEGACY_SERVICE_CONTENTS=""
|
|
1281
|
-
if [[ -e "$LEGACY_SERVICE_FILE" || -L "$LEGACY_SERVICE_FILE" ]]; then
|
|
1325
|
+
if [[ "$INSTANCE_NAME" == "default" && ( -e "$LEGACY_SERVICE_FILE" || -L "$LEGACY_SERVICE_FILE" ) ]]; then
|
|
1282
1326
|
if ! LEGACY_SERVICE_CONTENTS="$(read_owned_config_file "$LEGACY_SERVICE_FILE")"; then
|
|
1283
1327
|
echo "$LEGACY_SERVICE_FILE is not a safe regular legacy service file." >&2
|
|
1284
1328
|
exit 1
|
|
@@ -1295,7 +1339,7 @@ if [[ -e "$LEGACY_SERVICE_FILE" || -L "$LEGACY_SERVICE_FILE" ]]; then
|
|
|
1295
1339
|
exit 1
|
|
1296
1340
|
fi
|
|
1297
1341
|
fi
|
|
1298
|
-
if [[ -z "$LEGACY_ENV_FILE" \
|
|
1342
|
+
if [[ "$INSTANCE_NAME" == "default" && -z "$LEGACY_ENV_FILE" \
|
|
1299
1343
|
&& ( -e "$HOME/Zenithbot/.env" || -L "$HOME/Zenithbot/.env" ) ]]; then
|
|
1300
1344
|
LEGACY_ENV_FILE="$HOME/Zenithbot/.env"
|
|
1301
1345
|
fi
|
|
@@ -1334,9 +1378,55 @@ find_existing_token() {
|
|
|
1334
1378
|
return 1
|
|
1335
1379
|
}
|
|
1336
1380
|
|
|
1381
|
+
interactive_token_output() {
|
|
1382
|
+
[[ "$NON_INTERACTIVE" != "true" && -t 0 && -t 1 && -z "$EXPECTED_SERVER_IDENTITY" ]]
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
print_token_for_copy() {
|
|
1386
|
+
local access_token="$1"
|
|
1387
|
+
local copy_reply=""
|
|
1388
|
+
local clipboard_command=()
|
|
1389
|
+
printf '\nAccess token (%s):\n%s\n\n' "$INSTANCE_NAME" "$access_token"
|
|
1390
|
+
# A remote clipboard is not the user's local clipboard. Do not emit OSC 52
|
|
1391
|
+
# sequences or attempt to modify a remote desktop's clipboard over SSH.
|
|
1392
|
+
if [[ -n "${SSH_CONNECTION:-}${SSH_CLIENT:-}${SSH_TTY:-}" ]]; then
|
|
1393
|
+
printf '%s\n' 'Clipboard copy is unavailable over SSH; copy the token line above manually.'
|
|
1394
|
+
return 0
|
|
1395
|
+
fi
|
|
1396
|
+
if [[ "$(uname -s)" == "Darwin" ]] && command -v pbcopy >/dev/null 2>&1; then
|
|
1397
|
+
clipboard_command=(pbcopy)
|
|
1398
|
+
elif [[ -n "${WAYLAND_DISPLAY:-}" ]] && command -v wl-copy >/dev/null 2>&1; then
|
|
1399
|
+
clipboard_command=(wl-copy)
|
|
1400
|
+
elif [[ -n "${DISPLAY:-}" ]] && command -v xclip >/dev/null 2>&1; then
|
|
1401
|
+
clipboard_command=(xclip -selection clipboard)
|
|
1402
|
+
elif [[ -n "${DISPLAY:-}" ]] && command -v xsel >/dev/null 2>&1; then
|
|
1403
|
+
clipboard_command=(xsel --clipboard --input)
|
|
1404
|
+
fi
|
|
1405
|
+
if ((${#clipboard_command[@]} == 0)); then
|
|
1406
|
+
printf '%s\n' 'Clipboard copy is unavailable here; copy the token line above manually.'
|
|
1407
|
+
return 0
|
|
1408
|
+
fi
|
|
1409
|
+
read -r -p "Copy token to this machine's clipboard? [y/N] " copy_reply || return 0
|
|
1410
|
+
case "$copy_reply" in
|
|
1411
|
+
y|Y|[yY][eE][sS]) ;;
|
|
1412
|
+
*) return 0 ;;
|
|
1413
|
+
esac
|
|
1414
|
+
# Pass the credential via stdin, never an external process's argv. Optional
|
|
1415
|
+
# clipboard failures must not turn a successful installation into a failure.
|
|
1416
|
+
if printf '%s' "$access_token" | "${clipboard_command[@]}" >/dev/null 2>&1; then
|
|
1417
|
+
printf '%s\n' 'Copied to your clipboard.'
|
|
1418
|
+
else
|
|
1419
|
+
printf '%s\n' 'Could not copy to the clipboard; copy the token line above manually.'
|
|
1420
|
+
fi
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1337
1423
|
if [[ "$SHOW_TOKEN" == "true" ]]; then
|
|
1338
1424
|
if TOKEN_TO_SHOW="$(find_existing_token)"; then
|
|
1339
|
-
|
|
1425
|
+
if interactive_token_output; then
|
|
1426
|
+
print_token_for_copy "$TOKEN_TO_SHOW"
|
|
1427
|
+
else
|
|
1428
|
+
printf '%s\n' "$TOKEN_TO_SHOW"
|
|
1429
|
+
fi
|
|
1340
1430
|
exit 0
|
|
1341
1431
|
fi
|
|
1342
1432
|
echo "No AgentsServer access token found at $ENV_FILE. Run install.sh first." >&2
|
|
@@ -1345,7 +1435,7 @@ fi
|
|
|
1345
1435
|
|
|
1346
1436
|
OS_NAME="$(uname -s)"
|
|
1347
1437
|
SYSTEMD_SERVICE_FILE="$HOME/.config/systemd/user/$SERVICE_NAME.service"
|
|
1348
|
-
LABEL="com.agentsdock.server"
|
|
1438
|
+
LABEL="${LABEL:-com.agentsdock.server}"
|
|
1349
1439
|
PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
|
|
1350
1440
|
|
|
1351
1441
|
validate_legacy_macos_update_roots() {
|
|
@@ -1749,7 +1839,7 @@ if [[ "$TEAM_HUB_MODE" == "host" && "$TEAM_HUB_OPERATION_PENDING" != "true" \
|
|
|
1749
1839
|
fi
|
|
1750
1840
|
fi
|
|
1751
1841
|
|
|
1752
|
-
RELEASE_FILES=(activation_transaction.py execution_activation.py execution_legacy_runner.py execution_preparation.py update_preparation.py update_handoff.py update_recovery.py execution_update_status.py execution_uninstall.py execution_recovery.py execution_recovery_status.py execution_http.py execution_durability.py execution_control.py execution_install.py execution_maintenance.py execution_manage.py execution_ownership.py execution_service.py execution_transport.py agent_server.py workspace_git.py team_hub_host.py secure_peer_runtime.py team_mail_runtime.py team_mail_websocket.py team_mail_grants.py secure_peer_delivery.py agentsdock_jobs.py agentsdock_chats.py chat_mailbox.py agentsdock_emergency.py agentsdock_publish.py agentsdock_mail.py agentsdock_team.py provider_commands.py claude_sdk_client.py claude_goals.py claude_background_reconciliation.py codex_app_server.py codex_auth.py codex_provider.py side_questions.py title_generation.py codex_side_question.py claude_side_question.py cursor_agent_client.py cursor_process_guard.py claude_history_repair.py claude_history_provenance.py codex_history_repair.py public_chat_shares.py public_chat_transcript.py public_chat_share_routes.py interactive_chat_shares.py interactive_chat_share_routes.py interactive_chat_share_web.py interactive_chat_projection.py interactive_chat_runtime.py interactive_chat_native.py shared_chat_videos.py shared_chat_video_stream.py interactive_chat_controls.py install.sh uninstall.sh update_runner.py pyproject.toml uv.lock VERSION release-public-key.pem LICENSE NOTICE)
|
|
1842
|
+
RELEASE_FILES=(activation_transaction.py execution_activation.py execution_legacy_runner.py execution_preparation.py update_preparation.py update_handoff.py update_recovery.py execution_update_status.py execution_uninstall.py execution_recovery.py execution_recovery_status.py execution_http.py execution_durability.py execution_control.py execution_install.py execution_maintenance.py execution_manage.py execution_ownership.py execution_service.py execution_transport.py agent_server.py local_session_ownership.py cursor_history.py workspace_git.py team_hub_host.py secure_peer_runtime.py team_mail_runtime.py team_mail_websocket.py team_mail_grants.py secure_peer_delivery.py agentsdock_jobs.py agentsdock_chats.py chat_mailbox.py agentsdock_emergency.py agentsdock_publish.py agentsdock_mail.py agentsdock_team.py provider_commands.py provider_usage.py claude_sdk_client.py claude_model_catalog.py claude_goals.py claude_background_reconciliation.py codex_app_server.py codex_auth.py codex_provider.py provider_connections.py cursor_api_key.py side_questions.py title_generation.py codex_side_question.py claude_side_question.py cursor_agent_client.py cursor_provider_mcp.py opencode_agent_client.py cursor_process_guard.py claude_history_repair.py claude_history_provenance.py codex_history_repair.py public_chat_shares.py public_chat_transcript.py public_chat_share_routes.py interactive_chat_shares.py interactive_chat_share_routes.py interactive_chat_share_web.py interactive_chat_projection.py interactive_chat_runtime.py interactive_chat_native.py shared_chat_videos.py shared_chat_video_stream.py interactive_chat_controls.py install.sh uninstall.sh instances.sh server_instances.py update_runner.py pyproject.toml uv.lock VERSION release-public-key.pem LICENSE NOTICE)
|
|
1753
1843
|
RELEASE_DIRECTORIES=(agentsdock_team_hub)
|
|
1754
1844
|
TEAM_HUB_RELEASE_FILES=(
|
|
1755
1845
|
__init__.py
|
|
@@ -1801,12 +1891,11 @@ for name in "${RELEASE_DIRECTORIES[@]}"; do
|
|
|
1801
1891
|
echo "$name is missing beside install.sh or is not a real directory." >&2
|
|
1802
1892
|
exit 1
|
|
1803
1893
|
fi
|
|
1894
|
+
# Local Python runs create bytecode caches. Never copy those (staging uses
|
|
1895
|
+
# the explicit manifest below), but still reject links/special files anywhere,
|
|
1896
|
+
# including inside a cache directory.
|
|
1804
1897
|
if find "$SOURCE_DIR/$name" \( -type l -o \( ! -type d ! -type f \) \) -print -quit | grep -q .; then
|
|
1805
|
-
echo "$name contains
|
|
1806
|
-
exit 1
|
|
1807
|
-
fi
|
|
1808
|
-
if [[ -z "$ACTIVATE_PREPARED" && "$RECOVER_ONLY" != "true" ]] && find "$SOURCE_DIR/$name" \( -type f \( -name '*.pyc' -o -name '*.pyo' \) -o -type d -name '__pycache__' \) -print -quit | grep -q .; then
|
|
1809
|
-
echo "$name contains linked or generated entries and cannot be installed." >&2
|
|
1898
|
+
echo "$name contains linked or special entries and cannot be installed." >&2
|
|
1810
1899
|
exit 1
|
|
1811
1900
|
fi
|
|
1812
1901
|
done
|
|
@@ -1820,13 +1909,13 @@ done
|
|
|
1820
1909
|
# bound by the receipt or owned recovery journal before activation; raw source
|
|
1821
1910
|
# archives continue to require the exact clean allowlist.
|
|
1822
1911
|
if [[ -z "$ACTIVATE_PREPARED" && "$RECOVER_ONLY" != "true" ]]; then
|
|
1823
|
-
TEAM_HUB_RELEASE_FILE_COUNT="$(find "$SOURCE_DIR/agentsdock_team_hub" -type f | wc -l)"
|
|
1912
|
+
TEAM_HUB_RELEASE_FILE_COUNT="$(find "$SOURCE_DIR/agentsdock_team_hub" -type d -name '__pycache__' -prune -o -type f ! -name '*.pyc' ! -name '*.pyo' -print | wc -l)"
|
|
1824
1913
|
TEAM_HUB_RELEASE_FILE_COUNT="${TEAM_HUB_RELEASE_FILE_COUNT//[[:space:]]/}"
|
|
1825
1914
|
if [[ "$TEAM_HUB_RELEASE_FILE_COUNT" != "${#TEAM_HUB_RELEASE_FILES[@]}" ]]; then
|
|
1826
1915
|
echo "agentsdock_team_hub contains unexpected release files." >&2
|
|
1827
1916
|
exit 1
|
|
1828
1917
|
fi
|
|
1829
|
-
TEAM_HUB_RELEASE_DIRECTORY_COUNT="$(find "$SOURCE_DIR/agentsdock_team_hub" -type d | wc -l)"
|
|
1918
|
+
TEAM_HUB_RELEASE_DIRECTORY_COUNT="$(find "$SOURCE_DIR/agentsdock_team_hub" -type d -name '__pycache__' -prune -o -type d -print | wc -l)"
|
|
1830
1919
|
TEAM_HUB_RELEASE_DIRECTORY_COUNT="${TEAM_HUB_RELEASE_DIRECTORY_COUNT//[[:space:]]/}"
|
|
1831
1920
|
if [[ "$TEAM_HUB_RELEASE_DIRECTORY_COUNT" != "2" ]]; then
|
|
1832
1921
|
echo "agentsdock_team_hub contains unexpected release directories." >&2
|
|
@@ -2459,7 +2548,7 @@ backup_runtime_configuration() {
|
|
|
2459
2548
|
current_snapshot="${current_snapshot#*|}"
|
|
2460
2549
|
PRIOR_SERVICE_ENABLED="${current_snapshot%%|*}"
|
|
2461
2550
|
fi
|
|
2462
|
-
if [[ "$OS_NAME" == "Linux" ]]; then
|
|
2551
|
+
if [[ "$OS_NAME" == "Linux" && "${INSTANCE_NAME:-default}" == "default" ]]; then
|
|
2463
2552
|
local legacy_exists="false"
|
|
2464
2553
|
local legacy_snapshot=""
|
|
2465
2554
|
if [[ -e "$LEGACY_SERVICE_FILE" || -L "$LEGACY_SERVICE_FILE" ]]; then
|
|
@@ -3496,6 +3585,7 @@ sync_release_dependencies() (
|
|
|
3496
3585
|
--project "$STAGE_DIR" \
|
|
3497
3586
|
--python '>=3.10' \
|
|
3498
3587
|
--no-dev \
|
|
3588
|
+
--quiet \
|
|
3499
3589
|
--frozen
|
|
3500
3590
|
)
|
|
3501
3591
|
|
|
@@ -3526,6 +3616,8 @@ validate_staged_release_runtime() (
|
|
|
3526
3616
|
"$STAGE_DIR/execution_service.py" \
|
|
3527
3617
|
"$STAGE_DIR/execution_transport.py" \
|
|
3528
3618
|
"$STAGE_DIR/agent_server.py" \
|
|
3619
|
+
"$STAGE_DIR/local_session_ownership.py" \
|
|
3620
|
+
"$STAGE_DIR/cursor_history.py" \
|
|
3529
3621
|
"$STAGE_DIR/team_hub_host.py" \
|
|
3530
3622
|
"$STAGE_DIR/secure_peer_runtime.py" \
|
|
3531
3623
|
"$STAGE_DIR/team_mail_runtime.py" \
|
|
@@ -3540,18 +3632,23 @@ validate_staged_release_runtime() (
|
|
|
3540
3632
|
"$STAGE_DIR/agentsdock_mail.py" \
|
|
3541
3633
|
"$STAGE_DIR/agentsdock_team.py" \
|
|
3542
3634
|
"$STAGE_DIR/provider_commands.py" \
|
|
3635
|
+
"$STAGE_DIR/provider_usage.py" \
|
|
3543
3636
|
"$STAGE_DIR/claude_sdk_client.py" \
|
|
3637
|
+
"$STAGE_DIR/claude_model_catalog.py" \
|
|
3544
3638
|
"$STAGE_DIR/claude_goals.py" \
|
|
3545
3639
|
"$STAGE_DIR/claude_background_reconciliation.py" \
|
|
3546
3640
|
"$STAGE_DIR/codex_app_server.py" \
|
|
3547
3641
|
"$STAGE_DIR/codex_auth.py" \
|
|
3548
3642
|
"$STAGE_DIR/codex_provider.py" \
|
|
3643
|
+
"$STAGE_DIR/provider_connections.py" "$STAGE_DIR/cursor_api_key.py" \
|
|
3549
3644
|
"$STAGE_DIR/side_questions.py" \
|
|
3550
3645
|
"$STAGE_DIR/workspace_git.py" \
|
|
3551
3646
|
"$STAGE_DIR/codex_side_question.py" \
|
|
3552
3647
|
"$STAGE_DIR/title_generation.py" \
|
|
3553
3648
|
"$STAGE_DIR/claude_side_question.py" \
|
|
3554
3649
|
"$STAGE_DIR/cursor_agent_client.py" \
|
|
3650
|
+
"$STAGE_DIR/cursor_provider_mcp.py" \
|
|
3651
|
+
"$STAGE_DIR/opencode_agent_client.py" \
|
|
3555
3652
|
"$STAGE_DIR/cursor_process_guard.py" \
|
|
3556
3653
|
"$STAGE_DIR/claude_history_repair.py" \
|
|
3557
3654
|
"$STAGE_DIR/claude_history_provenance.py" \
|
|
@@ -3569,8 +3666,9 @@ validate_staged_release_runtime() (
|
|
|
3569
3666
|
"$STAGE_DIR/shared_chat_video_stream.py" \
|
|
3570
3667
|
"$STAGE_DIR/interactive_chat_controls.py" \
|
|
3571
3668
|
"$STAGE_DIR/update_runner.py"
|
|
3669
|
+
"$STAGE_DIR/.venv/bin/python" -m py_compile "$STAGE_DIR/server_instances.py"
|
|
3572
3670
|
"$STAGE_DIR/.venv/bin/python" -m compileall -q "$STAGE_DIR/agentsdock_team_hub"
|
|
3573
|
-
PYTHONPATH="$STAGE_DIR" "$STAGE_DIR/.venv/bin/python" -c 'import execution_activation, execution_preparation, update_preparation, update_handoff, update_recovery, execution_update_status, execution_uninstall, execution_recovery, execution_recovery_status, execution_http, execution_durability, execution_control, execution_install, execution_maintenance, execution_manage, execution_ownership, execution_service, execution_transport; import workspace_git; import codex_auth, codex_provider, side_questions, title_generation, codex_side_question, claude_side_question, agentsdock_team_hub, cursor_agent_client, cursor_process_guard, secure_peer_delivery, secure_peer_runtime, team_mail_runtime, team_mail_websocket, team_mail_grants, team_hub_host, agentsdock_mail, agentsdock_team, claude_history_repair, claude_history_provenance, claude_goals, claude_background_reconciliation, codex_history_repair, public_chat_shares, public_chat_transcript, public_chat_share_routes, interactive_chat_shares, interactive_chat_share_routes, interactive_chat_share_web, interactive_chat_projection, interactive_chat_runtime, interactive_chat_native, shared_chat_videos, shared_chat_video_stream, interactive_chat_controls, chat_mailbox, provider_commands; from agentsdock_team_hub import secure_peer, secure_peer_hub' >/dev/null
|
|
3671
|
+
PYTHONPATH="$STAGE_DIR" "$STAGE_DIR/.venv/bin/python" -c 'import execution_activation, execution_preparation, update_preparation, update_handoff, update_recovery, execution_update_status, execution_uninstall, execution_recovery, execution_recovery_status, execution_http, execution_durability, execution_control, execution_install, execution_maintenance, execution_manage, execution_ownership, execution_service, execution_transport; import workspace_git, claude_model_catalog, server_instances, local_session_ownership, cursor_history; import codex_auth, codex_provider, provider_connections, cursor_api_key, side_questions, title_generation, codex_side_question, claude_side_question, agentsdock_team_hub, cursor_agent_client, cursor_provider_mcp, opencode_agent_client, cursor_process_guard, secure_peer_delivery, secure_peer_runtime, team_mail_runtime, team_mail_websocket, team_mail_grants, team_hub_host, agentsdock_mail, agentsdock_team, claude_history_repair, claude_history_provenance, claude_goals, claude_background_reconciliation, codex_history_repair, public_chat_shares, public_chat_transcript, public_chat_share_routes, interactive_chat_shares, interactive_chat_share_routes, interactive_chat_share_web, interactive_chat_projection, interactive_chat_runtime, interactive_chat_native, shared_chat_videos, shared_chat_video_stream, interactive_chat_controls, chat_mailbox, provider_commands, provider_usage; from agentsdock_team_hub import secure_peer, secure_peer_hub' >/dev/null
|
|
3574
3672
|
)
|
|
3575
3673
|
|
|
3576
3674
|
abort_unclaimed_team_hub_reactivation() {
|
|
@@ -3898,6 +3996,7 @@ for name in "${TEAM_HUB_RELEASE_FILES[@]}"; do
|
|
|
3898
3996
|
"$STAGE_DIR/agentsdock_team_hub/$name"
|
|
3899
3997
|
done
|
|
3900
3998
|
chmod 755 "$STAGE_DIR/agent_server.py" "$STAGE_DIR/agentsdock_jobs.py" "$STAGE_DIR/agentsdock_chats.py" "$STAGE_DIR/agentsdock_emergency.py" "$STAGE_DIR/agentsdock_publish.py" "$STAGE_DIR/agentsdock_mail.py" "$STAGE_DIR/agentsdock_team.py" "$STAGE_DIR/install.sh" "$STAGE_DIR/uninstall.sh" "$STAGE_DIR/update_runner.py"
|
|
3999
|
+
chmod 755 "$STAGE_DIR/instances.sh"
|
|
3901
4000
|
|
|
3902
4001
|
if [[ "$PREPARE_ONLY" == "true" ]]; then
|
|
3903
4002
|
source_inventory="$(mktemp "$INSTALL_ROOT/.prepared-inventory.XXXXXXXX")" || exit 1
|
|
@@ -3922,7 +4021,9 @@ with output.open("w") as stream:
|
|
|
3922
4021
|
PYINVENTORY
|
|
3923
4022
|
fi
|
|
3924
4023
|
|
|
3925
|
-
echo "[2/7]
|
|
4024
|
+
echo "[2/7] Preparing private Python dependencies for instance $INSTANCE_NAME"
|
|
4025
|
+
echo " Reusing uv's package cache where available; errors will still be shown."
|
|
4026
|
+
echo " This does not reinstall Claude Code, Codex, or tmux."
|
|
3926
4027
|
if run_timed_stage \
|
|
3927
4028
|
"dependency resolution" \
|
|
3928
4029
|
"$DEPENDENCY_SYNC_TIMEOUT_SECONDS" \
|
|
@@ -3998,7 +4099,7 @@ write_runtime_env() {
|
|
|
3998
4099
|
local filter_status=0
|
|
3999
4100
|
preserved_contents="$(read_owned_config_file "$PRESERVE_SOURCE")" || return 1
|
|
4000
4101
|
if printf '%s\n' "$preserved_contents" \
|
|
4001
|
-
| grep -Ev '^(AGENTSDOCK_(STATE_DIR|AGENT_CWD|AGENT_BIND|AGENT_PORT|AGENT_TOKEN|SERVER_NAME|TEAM_HUB_MODE|TEAM_HUB_TRANSPORT|TEAM_HUB_URL|TEAM_HUB_DIRECT_IP_URL|TEAM_HUB_REACTIVATION_HUB_ID|TEAM_HUB_REACTIVATION_OPERATION_ID|TEAM_HUB_REACTIVATION_SNAPSHOT|TEAM_HUB_UPDATE_HUB_ID|TEAM_HUB_UPDATE_OPERATION_ID|TEAM_HUB_UPDATE_SNAPSHOT)|AGENTS_SERVER_(STATE_DIR|INSTALL_DIR)|ZENITHBOT_AGENT_(DIR|CWD|BIND|PORT|TOKEN)|ZENITHDOCK_AGENT_TOKEN|PATH)=' \
|
|
4102
|
+
| grep -Ev '^(AGENTSDOCK_(STATE_DIR|AGENT_CWD|AGENT_BIND|AGENT_PORT|AGENT_TOKEN|SERVER_NAME|TEAM_HUB_MODE|TEAM_HUB_TRANSPORT|TEAM_HUB_URL|TEAM_HUB_DIRECT_IP_URL|TEAM_HUB_REACTIVATION_HUB_ID|TEAM_HUB_REACTIVATION_OPERATION_ID|TEAM_HUB_REACTIVATION_SNAPSHOT|TEAM_HUB_UPDATE_HUB_ID|TEAM_HUB_UPDATE_OPERATION_ID|TEAM_HUB_UPDATE_SNAPSHOT)|AGENTS_SERVER_(STATE_DIR|INSTALL_DIR|CONFIG_DIR|INSTANCE)|ZENITHBOT_AGENT_(DIR|CWD|BIND|PORT|TOKEN)|ZENITHDOCK_AGENT_TOKEN|PATH)=' \
|
|
4002
4103
|
> "$env_temp"; then
|
|
4003
4104
|
:
|
|
4004
4105
|
else
|
|
@@ -4024,6 +4125,8 @@ AGENTSDOCK_TEAM_HUB_TRANSPORT=$TEAM_HUB_TRANSPORT
|
|
|
4024
4125
|
AGENTSDOCK_TEAM_HUB_URL=$TEAM_HUB_URL
|
|
4025
4126
|
AGENTSDOCK_TEAM_HUB_DIRECT_IP_URL=$TEAM_HUB_DIRECT_IP_URL
|
|
4026
4127
|
AGENTS_SERVER_INSTALL_DIR=$INSTALL_ROOT
|
|
4128
|
+
AGENTS_SERVER_CONFIG_DIR=$CONFIG_ROOT
|
|
4129
|
+
AGENTS_SERVER_INSTANCE=${INSTANCE_NAME:-default}
|
|
4027
4130
|
PATH=$SERVER_PATH
|
|
4028
4131
|
EOF
|
|
4029
4132
|
if ! replace_activation_config env "$env_temp" 600; then
|
|
@@ -4181,21 +4284,23 @@ restart_service() {
|
|
|
4181
4284
|
return
|
|
4182
4285
|
fi
|
|
4183
4286
|
if [[ "$OS_NAME" == "Linux" ]]; then
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
&&
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
"$
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
"$
|
|
4197
|
-
|
|
4198
|
-
|
|
4287
|
+
if [[ "${INSTANCE_NAME:-default}" == "default" ]]; then
|
|
4288
|
+
local legacy_exists="false"
|
|
4289
|
+
local legacy_snapshot=""
|
|
4290
|
+
[[ -f "$LEGACY_SERVICE_FILE" && ! -L "$LEGACY_SERVICE_FILE" ]] \
|
|
4291
|
+
&& legacy_exists="true"
|
|
4292
|
+
if [[ "$PRIOR_LEGACY_SERVICE_STATE" == "absent" ]]; then
|
|
4293
|
+
legacy_snapshot="$(systemd_unit_snapshot \
|
|
4294
|
+
"$LEGACY_SERVICE_NAME.service" "$legacy_exists")" || return 1
|
|
4295
|
+
[[ "${legacy_snapshot%%|*}" == "absent" ]] || return 1
|
|
4296
|
+
else
|
|
4297
|
+
systemctl --user disable --now "$LEGACY_SERVICE_NAME.service" \
|
|
4298
|
+
>/dev/null || return 1
|
|
4299
|
+
legacy_snapshot="$(systemd_unit_snapshot \
|
|
4300
|
+
"$LEGACY_SERVICE_NAME.service" "$legacy_exists")" || return 1
|
|
4301
|
+
[[ "${legacy_snapshot%%|*}" == "stopped" \
|
|
4302
|
+
&& "${legacy_snapshot#*|}" == "false|"* ]] || return 1
|
|
4303
|
+
fi
|
|
4199
4304
|
fi
|
|
4200
4305
|
systemctl --user daemon-reload || return
|
|
4201
4306
|
systemctl --user enable "$SERVICE_NAME.service" >/dev/null || return
|
|
@@ -4527,19 +4632,21 @@ restore_prior_service_state() {
|
|
|
4527
4632
|
[[ "$PRIOR_SERVICE_STATE" == "absent" ]] || return 1
|
|
4528
4633
|
}
|
|
4529
4634
|
fi
|
|
4530
|
-
if [[ "$
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4635
|
+
if [[ "${INSTANCE_NAME:-default}" == "default" ]]; then
|
|
4636
|
+
if [[ "$PRIOR_LEGACY_SERVICE_ENABLED" == "true" ]]; then
|
|
4637
|
+
systemctl --user enable "$LEGACY_SERVICE_NAME.service" >/dev/null || return 1
|
|
4638
|
+
elif [[ "$PRIOR_LEGACY_SERVICE_STATE" == "absent" ]]; then
|
|
4639
|
+
systemctl --user disable "$LEGACY_SERVICE_NAME.service" >/dev/null 2>&1 || true
|
|
4640
|
+
else
|
|
4641
|
+
systemctl --user disable "$LEGACY_SERVICE_NAME.service" >/dev/null || return 1
|
|
4642
|
+
fi
|
|
4643
|
+
if [[ "$PRIOR_LEGACY_SERVICE_STATE" == "running" ]]; then
|
|
4644
|
+
systemctl --user start "$LEGACY_SERVICE_NAME.service" || return 1
|
|
4645
|
+
else
|
|
4646
|
+
systemctl --user stop "$LEGACY_SERVICE_NAME.service" >/dev/null 2>&1 || {
|
|
4647
|
+
[[ "$PRIOR_LEGACY_SERVICE_STATE" == "absent" ]] || return 1
|
|
4648
|
+
}
|
|
4649
|
+
fi
|
|
4543
4650
|
fi
|
|
4544
4651
|
local current_exists="false"
|
|
4545
4652
|
local legacy_exists="false"
|
|
@@ -4555,7 +4662,7 @@ restore_prior_service_state() {
|
|
|
4555
4662
|
&& "${observed_snapshot#*|}" == "$PRIOR_SERVICE_ENABLED|"* ]] \
|
|
4556
4663
|
|| return 1
|
|
4557
4664
|
fi
|
|
4558
|
-
if [[ "$PRIOR_LEGACY_SERVICE_STATE" != "running" ]]; then
|
|
4665
|
+
if [[ "${INSTANCE_NAME:-default}" == "default" && "$PRIOR_LEGACY_SERVICE_STATE" != "running" ]]; then
|
|
4559
4666
|
observed_snapshot="$(systemd_unit_snapshot \
|
|
4560
4667
|
"$LEGACY_SERVICE_NAME.service" "$legacy_exists")" || return 1
|
|
4561
4668
|
[[ "${observed_snapshot%%|*}" == "$PRIOR_LEGACY_SERVICE_STATE" \
|
|
@@ -4722,7 +4829,7 @@ write_service_files() {
|
|
|
4722
4829
|
if [[ "$OS_NAME" == "Linux" ]]; then
|
|
4723
4830
|
USER_SERVICE_DIR="$HOME/.config/systemd/user"
|
|
4724
4831
|
mkdir -p "$USER_SERVICE_DIR"
|
|
4725
|
-
service_temp="$USER_SERVICE_DIR
|
|
4832
|
+
service_temp="$USER_SERVICE_DIR/.$SERVICE_NAME.service.activation-$ACTIVATION_TRANSACTION_ID-service.source"
|
|
4726
4833
|
(umask 077; set -o noclobber; : > "$service_temp") 2>/dev/null || return 1
|
|
4727
4834
|
chmod 600 "$service_temp" || return 1
|
|
4728
4835
|
cat > "$service_temp" <<EOF
|
|
@@ -4756,8 +4863,9 @@ EOF
|
|
|
4756
4863
|
SERVICE_KIND="systemd-user"
|
|
4757
4864
|
elif [[ "$OS_NAME" == "Darwin" ]]; then
|
|
4758
4865
|
LAUNCH_AGENTS="$HOME/Library/LaunchAgents"
|
|
4759
|
-
|
|
4760
|
-
|
|
4866
|
+
local instance_log_dir="${INSTANCE_LOG_DIR:-$HOME/Library/Logs/AgentsServer}"
|
|
4867
|
+
mkdir -p "$LAUNCH_AGENTS" "$instance_log_dir"
|
|
4868
|
+
service_temp="$LAUNCH_AGENTS/.$LABEL.plist.activation-$ACTIVATION_TRANSACTION_ID-service.source"
|
|
4761
4869
|
(umask 077; set -o noclobber; : > "$service_temp") 2>/dev/null || return 1
|
|
4762
4870
|
chmod 600 "$service_temp" || return 1
|
|
4763
4871
|
local launchd_server_name_entry=""
|
|
@@ -4790,11 +4898,13 @@ $launchd_server_name_entry
|
|
|
4790
4898
|
<key>AGENTSDOCK_TEAM_HUB_URL</key><string>$TEAM_HUB_URL</string>
|
|
4791
4899
|
<key>AGENTSDOCK_TEAM_HUB_DIRECT_IP_URL</key><string>$TEAM_HUB_DIRECT_IP_URL</string>
|
|
4792
4900
|
<key>AGENTS_SERVER_INSTALL_DIR</key><string>$INSTALL_ROOT</string>
|
|
4901
|
+
<key>AGENTS_SERVER_CONFIG_DIR</key><string>$CONFIG_ROOT</string>
|
|
4902
|
+
<key>AGENTS_SERVER_INSTANCE</key><string>${INSTANCE_NAME:-default}</string>
|
|
4793
4903
|
<key>PATH</key><string>$SERVER_PATH</string>
|
|
4794
4904
|
</dict>
|
|
4795
4905
|
<key>RunAtLoad</key><true/><key>KeepAlive</key><true/>
|
|
4796
|
-
<key>StandardOutPath</key><string>$
|
|
4797
|
-
<key>StandardErrorPath</key><string>$
|
|
4906
|
+
<key>StandardOutPath</key><string>$instance_log_dir/server.log</string>
|
|
4907
|
+
<key>StandardErrorPath</key><string>$instance_log_dir/server-error.log</string>
|
|
4798
4908
|
</dict></plist>
|
|
4799
4909
|
EOF
|
|
4800
4910
|
if ! replace_activation_config service "$service_temp" 600; then
|
|
@@ -4928,7 +5038,8 @@ service_manager_owns_listener() {
|
|
|
4928
5038
|
services=("$LABEL")
|
|
4929
5039
|
[[ "$EXECUTION_MODE" != "split" ]] || services+=("com.agentsdock.gateway")
|
|
4930
5040
|
else
|
|
4931
|
-
services=("$SERVICE_NAME"
|
|
5041
|
+
services=("$SERVICE_NAME")
|
|
5042
|
+
[[ "${INSTANCE_NAME:-default}" != "default" ]] || services+=("${LEGACY_SERVICE_NAME:-}")
|
|
4932
5043
|
[[ "$EXECUTION_MODE" != "split" ]] || services+=("agents-server-gateway")
|
|
4933
5044
|
fi
|
|
4934
5045
|
for service in "${services[@]}"; do
|
|
@@ -4968,7 +5079,8 @@ pinned_managed_http_get() {
|
|
|
4968
5079
|
services=("$LABEL")
|
|
4969
5080
|
[[ "$EXECUTION_MODE" != "split" ]] || services+=("com.agentsdock.gateway")
|
|
4970
5081
|
else
|
|
4971
|
-
services=("$SERVICE_NAME"
|
|
5082
|
+
services=("$SERVICE_NAME")
|
|
5083
|
+
[[ "${INSTANCE_NAME:-default}" != "default" ]] || services+=("${LEGACY_SERVICE_NAME:-}")
|
|
4972
5084
|
[[ "$EXECUTION_MODE" != "split" ]] || services+=("agents-server-gateway")
|
|
4973
5085
|
fi
|
|
4974
5086
|
for service in "${services[@]}"; do
|
|
@@ -7013,36 +7125,125 @@ if [[ "$CLAUDE_READY" == "false" && "$CODEX_READY" == "false" ]]; then
|
|
|
7013
7125
|
echo " Sign in to at least one before starting a chat."
|
|
7014
7126
|
fi
|
|
7015
7127
|
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
SERVER_URL="
|
|
7023
|
-
|
|
7128
|
+
setup_network_summary() {
|
|
7129
|
+
TAILSCALE_IP=""
|
|
7130
|
+
TAILSCALE_STATUS="unknown"
|
|
7131
|
+
TAILSCALE_BIND_MATCH="false"
|
|
7132
|
+
SERVER_LOCAL_ONLY="false"
|
|
7133
|
+
NETWORK_URLS=""
|
|
7134
|
+
SERVER_URL="$(health_origin "$PORT")"
|
|
7135
|
+
local network_bindings=""
|
|
7136
|
+
# The shipped helper emits only fixed keys and shell-quoted validated values.
|
|
7137
|
+
# Optional network diagnostics must not fail an already healthy installation.
|
|
7138
|
+
if network_bindings="$("$CURRENT_LINK/.venv/bin/python" \
|
|
7139
|
+
"$CURRENT_LINK/server_instances.py" _setup-network \
|
|
7140
|
+
--bind "$BIND_ADDRESS" --port "$PORT" 2>/dev/null)" \
|
|
7141
|
+
&& [[ -n "$network_bindings" ]]; then
|
|
7142
|
+
eval "$network_bindings"
|
|
7143
|
+
fi
|
|
7144
|
+
}
|
|
7145
|
+
|
|
7146
|
+
print_tailscale_summary() {
|
|
7147
|
+
case "$TAILSCALE_STATUS" in
|
|
7148
|
+
connected)
|
|
7149
|
+
if [[ "$TAILSCALE_BIND_MATCH" == "true" ]]; then
|
|
7150
|
+
echo " $CHECK_MARK Tailscale already connected: http://$TAILSCALE_IP:$PORT (tailnet access rules still apply)"
|
|
7151
|
+
elif [[ "$SERVER_LOCAL_ONLY" == "true" ]]; then
|
|
7152
|
+
echo " $DOT_MARK Tailscale already connected; this server is bound to localhost only, so phones cannot connect directly."
|
|
7153
|
+
echo " For phone access, choose a reachable server bind: https://github.com/ZhengyiLuo/AgentsServer"
|
|
7154
|
+
else
|
|
7155
|
+
echo " $DOT_MARK Tailscale already connected; its IPv4 address is not available on this server's configured bind."
|
|
7156
|
+
echo " For tailnet access, review the server bind: https://github.com/ZhengyiLuo/AgentsServer"
|
|
7157
|
+
fi
|
|
7158
|
+
;;
|
|
7159
|
+
disconnected)
|
|
7160
|
+
echo " $DOT_MARK Tailscale already installed but not connected; no installation or configuration changes made."
|
|
7161
|
+
echo " To connect from other networks, open Tailscale and sign in/connect."
|
|
7162
|
+
;;
|
|
7163
|
+
not-installed)
|
|
7164
|
+
echo " $DOT_MARK optional: Tailscale was not found; use your LAN address on the same network, or see https://tailscale.com/download"
|
|
7165
|
+
;;
|
|
7166
|
+
unavailable)
|
|
7167
|
+
echo " $DOT_MARK Tailscale already installed; connection status could not be checked. No setup changes made."
|
|
7168
|
+
echo " Open Tailscale to check the connection, or try: tailscale status"
|
|
7169
|
+
;;
|
|
7170
|
+
*)
|
|
7171
|
+
echo " $DOT_MARK Tailscale connection status could not be checked; no installation or configuration changes made."
|
|
7172
|
+
echo " If you use Tailscale, check its app or try: tailscale status"
|
|
7173
|
+
;;
|
|
7174
|
+
esac
|
|
7175
|
+
}
|
|
7176
|
+
|
|
7177
|
+
print_setup_checklist() {
|
|
7178
|
+
local network_ready="false"
|
|
7179
|
+
[[ "$TAILSCALE_STATUS" != "connected" || "$TAILSCALE_BIND_MATCH" != "true" ]] || network_ready="true"
|
|
7180
|
+
if [[ -z "$TMUX_WARNING" && "$network_ready" == "true" \
|
|
7181
|
+
&& ( "$CLAUDE_READY" == "true" || "$CODEX_READY" == "true" ) ]]; then
|
|
7182
|
+
echo " ${COLOR_GREEN}${COLOR_BOLD}You are all set${COLOR_RESET}"
|
|
7183
|
+
echo " $CHECK_MARK tmux available"
|
|
7184
|
+
print_tailscale_summary
|
|
7185
|
+
return
|
|
7186
|
+
fi
|
|
7187
|
+
|
|
7188
|
+
echo " ${COLOR_BOLD}You already have${COLOR_RESET}"
|
|
7189
|
+
echo " $CHECK_MARK AgentsServer running"
|
|
7190
|
+
if [[ -z "$TMUX_WARNING" ]]; then
|
|
7191
|
+
echo " $CHECK_MARK tmux available"
|
|
7192
|
+
fi
|
|
7193
|
+
if [[ "$network_ready" == "true" ]]; then
|
|
7194
|
+
print_tailscale_summary
|
|
7195
|
+
elif [[ "$TAILSCALE_STATUS" == "connected" || "$TAILSCALE_STATUS" == "disconnected" || "$TAILSCALE_STATUS" == "unavailable" ]]; then
|
|
7196
|
+
echo " $CHECK_MARK Tailscale installed"
|
|
7197
|
+
fi
|
|
7198
|
+
|
|
7199
|
+
if [[ "$CLAUDE_READY" == "false" && "$CODEX_READY" == "false" ]]; then
|
|
7200
|
+
echo
|
|
7201
|
+
echo " ${COLOR_BOLD}To start chats${COLOR_RESET}"
|
|
7202
|
+
echo " $DOT_MARK Choose one agent CLI and sign in:"
|
|
7203
|
+
echo " Claude Code: npm install -g @anthropic-ai/claude-code, then run: claude"
|
|
7204
|
+
echo " Codex: npm install -g @openai/codex, then run: codex login"
|
|
7205
|
+
fi
|
|
7206
|
+
if [[ -n "$TMUX_WARNING" || "$network_ready" != "true" ]]; then
|
|
7207
|
+
echo
|
|
7208
|
+
echo " ${COLOR_BOLD}Optional next steps${COLOR_RESET}"
|
|
7209
|
+
echo " You can skip these unless you need the features below."
|
|
7210
|
+
if [[ -n "$TMUX_WARNING" ]]; then
|
|
7211
|
+
echo " $DOT_MARK For persistent terminals, pane inspection and in-app updates, install tmux:"
|
|
7212
|
+
if [[ "$OS_NAME" == "Darwin" ]]; then
|
|
7213
|
+
echo " With Homebrew: brew install tmux"
|
|
7214
|
+
else
|
|
7215
|
+
echo " Use your package manager, for example: sudo apt install tmux"
|
|
7216
|
+
fi
|
|
7217
|
+
fi
|
|
7218
|
+
if [[ "$network_ready" != "true" ]]; then
|
|
7219
|
+
print_tailscale_summary
|
|
7220
|
+
fi
|
|
7221
|
+
fi
|
|
7222
|
+
}
|
|
7223
|
+
|
|
7224
|
+
setup_network_summary
|
|
7024
7225
|
|
|
7025
7226
|
echo "[7/7] AgentsServer $RELEASE_VERSION is ready"
|
|
7227
|
+
if [[ "$PRIOR_SERVICE_STATE" == "absent" && "$PRIOR_LEGACY_SERVICE_STATE" == "absent" && -z "$EXPECTED_SERVER_IDENTITY" ]]; then
|
|
7228
|
+
printf '\n%s%s\n%s\n%s%s\n' \
|
|
7229
|
+
"$COLOR_GREEN" '================================' \
|
|
7230
|
+
'Your new service is up!' \
|
|
7231
|
+
'================================' "$COLOR_RESET"
|
|
7232
|
+
fi
|
|
7026
7233
|
echo
|
|
7027
7234
|
echo " ${COLOR_BOLD}Server URL${COLOR_RESET} $SERVER_URL"
|
|
7235
|
+
if [[ -n "$NETWORK_URLS" ]]; then
|
|
7236
|
+
echo " Other local/network addresses (reachability depends on network/firewall):"
|
|
7237
|
+
while IFS= read -r network_url; do
|
|
7238
|
+
[[ -z "$network_url" ]] || echo " $network_url"
|
|
7239
|
+
done <<< "$NETWORK_URLS"
|
|
7240
|
+
fi
|
|
7028
7241
|
echo
|
|
7029
|
-
|
|
7242
|
+
print_setup_checklist
|
|
7030
7243
|
if [[ "$PORT_AUTO_SELECTED" == "true" ]]; then
|
|
7244
|
+
echo
|
|
7031
7245
|
echo " $DOT_MARK port $ORIGINAL_PORT was already in use, installed on $PORT instead (--port pins an exact port unless --allow-port-fallback is supplied)"
|
|
7032
7246
|
fi
|
|
7033
|
-
if [[ "$CLAUDE_READY" == "false" && "$CODEX_READY" == "false" ]]; then
|
|
7034
|
-
echo " $CROSS_MARK install and sign in to Claude Code or Codex (see [6/7] above) before starting a chat"
|
|
7035
|
-
fi
|
|
7036
|
-
if [[ -n "$TMUX_WARNING" ]]; then
|
|
7037
|
-
echo " $CROSS_MARK tmux unavailable: persistent terminal, pane inspection, and in-app updates won't work - $TMUX_WARNING"
|
|
7038
|
-
else
|
|
7039
|
-
echo " $CHECK_MARK tmux available"
|
|
7040
|
-
fi
|
|
7041
|
-
if [[ -n "$TAILSCALE_IP" ]]; then
|
|
7042
|
-
echo " $CHECK_MARK reachable via Tailscale at $TAILSCALE_IP"
|
|
7043
|
-
else
|
|
7044
|
-
echo " $DOT_MARK optional: install and connect Tailscale to reach this server from another device or WiFi network: https://tailscale.com/download"
|
|
7045
|
-
fi
|
|
7046
7247
|
if [[ "$TEAM_HUB_MODE" == "host" ]]; then
|
|
7047
7248
|
echo
|
|
7048
7249
|
if [[ "$TEAM_HUB_TRANSPORT" == "tailscale_serve" ]]; then
|
|
@@ -7071,4 +7272,7 @@ echo
|
|
|
7071
7272
|
if [[ -z "$EXPECTED_SERVER_IDENTITY" ]]; then
|
|
7072
7273
|
printf 'AGENTSDOCK_SETUP_RESULT={"server_url":"%s","access_token":"%s","service":"%s","tailscale_ip":"%s","server_version":"%s"}\n' \
|
|
7073
7274
|
"$SERVER_URL" "$TOKEN" "$SERVICE_KIND" "$TAILSCALE_IP" "$RELEASE_VERSION"
|
|
7275
|
+
if interactive_token_output; then
|
|
7276
|
+
print_token_for_copy "$TOKEN"
|
|
7277
|
+
fi
|
|
7074
7278
|
fi
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# No downloads or package installation just to list/manage existing instances.
|
|
5
|
+
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
for instance_python in "$SCRIPT_DIR/.venv/bin/python" \
|
|
7
|
+
"$HOME/.local/share/agents-server/current/.venv/bin/python" \
|
|
8
|
+
"$(command -v python3 || true)"; do
|
|
9
|
+
if [[ -n "$instance_python" && -x "$instance_python" ]] \
|
|
10
|
+
&& "$instance_python" -c 'import sys; sys.exit(sys.version_info < (3, 10))'; then
|
|
11
|
+
exec "$instance_python" "$SCRIPT_DIR/server_instances.py" "$@"
|
|
12
|
+
fi
|
|
13
|
+
done
|
|
14
|
+
echo "Instance management needs Python 3.10+; run ./install.sh first or install Python." >&2
|
|
15
|
+
exit 1
|