direxio-deployer 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/AGENTS.md +92 -0
- package/LICENSE +21 -0
- package/README.md +221 -0
- package/README_zh.md +218 -0
- package/SKILL.md +722 -0
- package/agents/README.md +25 -0
- package/agents/openai.yaml +12 -0
- package/bin/direxio-deployer.mjs +375 -0
- package/package.json +28 -0
- package/references/agent-targets.md +128 -0
- package/references/architecture.md +44 -0
- package/references/bug-history.md +78 -0
- package/references/deployment-lessons.md +218 -0
- package/references/deployment-optimization-audit.md +317 -0
- package/references/deployment-workflow.md +341 -0
- package/references/iam-policy.json +52 -0
- package/references/runtime-wiring.md +209 -0
- package/references/state-machine.md +46 -0
- package/references/token-refresh.md +81 -0
- package/references/tooling.md +106 -0
- package/references/troubleshooting.md +26 -0
- package/references/user-journey.md +75 -0
- package/references/verification-recovery.md +84 -0
- package/references/voip-turn-runbook.md +154 -0
- package/references/windows-deployment-notes.md +119 -0
- package/scripts/aws-credentials.sh +195 -0
- package/scripts/cloud-init/Caddyfile +48 -0
- package/scripts/cloud-init/docker-compose.yml +125 -0
- package/scripts/cloud-init/init-tokens.sh +238 -0
- package/scripts/cloud-init/user-data.yaml +40 -0
- package/scripts/destroy.ps1 +77 -0
- package/scripts/destroy.sh +589 -0
- package/scripts/lib/aws.sh +73 -0
- package/scripts/lib/domain.sh +175 -0
- package/scripts/lib/operation_report.sh +240 -0
- package/scripts/lib/ops.sh +230 -0
- package/scripts/lib/paths.sh +35 -0
- package/scripts/lib/state.sh +137 -0
- package/scripts/mcp-tools-list.mjs +95 -0
- package/scripts/orchestrate.ps1 +112 -0
- package/scripts/orchestrate.sh +1126 -0
- package/scripts/phases/s0_prereq_aws.sh +39 -0
- package/scripts/phases/s1_preflight.sh +72 -0
- package/scripts/phases/s2_domain.sh +103 -0
- package/scripts/phases/s3_provision.sh +421 -0
- package/scripts/phases/s4_bootstrap_stack.sh +38 -0
- package/scripts/phases/s5_init_tokens.sh +118 -0
- package/scripts/phases/s6_wire_local.sh +1435 -0
- package/scripts/phases/s7_verify_e2e.sh +136 -0
- package/scripts/pricing-estimate.sh +256 -0
- package/scripts/render/render-userdata.sh +86 -0
- package/scripts/reset-app-data.sh +40 -0
- package/scripts/update.sh +30 -0
- package/tests/aws_credentials_test.sh +139 -0
- package/tests/connect_daemon_runtime_check_test.sh +120 -0
- package/tests/default_paths_test.sh +58 -0
- package/tests/destroy_local_bridge_test.sh +154 -0
- package/tests/destroy_root_identity_test.sh +91 -0
- package/tests/destroy_route53_zone_test.sh +80 -0
- package/tests/domain_authoritative_dns_test.sh +49 -0
- package/tests/mcp_doctor_runtime_check_test.sh +86 -0
- package/tests/mcp_smoke_runtime_check_test.sh +121 -0
- package/tests/mcp_tools_runtime_check_test.sh +123 -0
- package/tests/npm_skill_distribution_test.sh +95 -0
- package/tests/operation_report_test.sh +258 -0
- package/tests/orchestrate_status_recovery_test.sh +91 -0
- package/tests/phase_timeout_test.sh +88 -0
- package/tests/pricing_estimate_test.sh +159 -0
- package/tests/render_userdata_remote_nodes_test.sh +40 -0
- package/tests/root_volume_tracking_test.sh +41 -0
- package/tests/route53_overwrite_guard_test.sh +86 -0
- package/tests/route53_zone_auto_create_test.sh +66 -0
- package/tests/runtime_summary_check_test.sh +203 -0
- package/tests/s6_wire_local_test.sh +405 -0
- package/tests/skill_structure_test.sh +298 -0
- package/tests/update_reset_ops_test.sh +230 -0
- package/tests/user_confirmation_gates_test.sh +152 -0
|
@@ -0,0 +1,1435 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# S6 WIRE_LOCAL_CLIENT - write service-scoped credentials and cc-connect env.
|
|
3
|
+
#
|
|
4
|
+
# ① ~/.direxio/nodes/<service_id>/credentials.json
|
|
5
|
+
# ② ~/.direxio/nodes/<service_id>/env
|
|
6
|
+
# ③ cc-connect Matrix config and install guidance for the detected agent runtime
|
|
7
|
+
# ④ MCP client snippets for Codex/OpenClaw/Hermes under the service directory
|
|
8
|
+
#
|
|
9
|
+
# Tokens change on every rebuild, so local credentials and cc-connect env must be refreshed.
|
|
10
|
+
|
|
11
|
+
S6_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
12
|
+
# shellcheck disable=SC1090
|
|
13
|
+
source "$S6_DIR/../lib/paths.sh"
|
|
14
|
+
|
|
15
|
+
_direxio_home() {
|
|
16
|
+
direxio_home
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
_direxio_service_id() {
|
|
20
|
+
direxio_service_id "$1"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
_direxio_service_dir() {
|
|
24
|
+
direxio_service_dir "$1"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
_cc_connect_supported_agents() {
|
|
28
|
+
printf '%s\n' acp antigravity claudecode codex copilot cursor devin gemini iflow kimi opencode pi qoder reasonix tmux
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_cc_connect_supported_agents_csv() {
|
|
32
|
+
_cc_connect_supported_agents | paste -sd ',' - | sed 's/,/, /g'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
_cc_connect_agent_alias() {
|
|
36
|
+
case "$1" in
|
|
37
|
+
claude|claude-code|claudecode) printf 'claudecode\n' ;;
|
|
38
|
+
open-code|opencode) printf 'opencode\n' ;;
|
|
39
|
+
qodercli|qoder) printf 'qoder\n' ;;
|
|
40
|
+
agy|antigravity) printf 'antigravity\n' ;;
|
|
41
|
+
acp|codex|copilot|cursor|devin|gemini|iflow|kimi|pi|reasonix|tmux) printf '%s\n' "$1" ;;
|
|
42
|
+
*) return 1 ;;
|
|
43
|
+
esac
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
_validate_cc_connect_agent() {
|
|
47
|
+
local agent
|
|
48
|
+
agent=$(_cc_connect_agent_alias "$1" 2>/dev/null) || {
|
|
49
|
+
fail "cc-connect agent must be one of: $(_cc_connect_supported_agents_csv)."
|
|
50
|
+
return 1
|
|
51
|
+
}
|
|
52
|
+
printf '%s\n' "$agent"
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
_detect_agent_runtime() {
|
|
56
|
+
local active_runtime explicit_agent home_runtime
|
|
57
|
+
if [ -n "${DIREXIO_AGENT_PLATFORM:-}" ] && [ "${DIREXIO_AGENT_PLATFORM:-}" != "auto" ]; then
|
|
58
|
+
_validate_agent_platform "$DIREXIO_AGENT_PLATFORM"
|
|
59
|
+
printf '%s\n' "$DIREXIO_AGENT_PLATFORM"
|
|
60
|
+
return 0
|
|
61
|
+
fi
|
|
62
|
+
if [ -n "${DIREXIO_CC_CONNECT_AGENT:-}" ]; then
|
|
63
|
+
explicit_agent=$(_validate_cc_connect_agent "$DIREXIO_CC_CONNECT_AGENT")
|
|
64
|
+
printf '%s\n' "$explicit_agent"
|
|
65
|
+
return 0
|
|
66
|
+
fi
|
|
67
|
+
# Active-process signals are stronger than stale config directories from
|
|
68
|
+
# other agents that have used this WSL home before.
|
|
69
|
+
active_runtime=$(_active_agent_runtime)
|
|
70
|
+
if [ -n "$active_runtime" ]; then printf '%s\n' "$active_runtime"; return 0; fi
|
|
71
|
+
home_runtime=$(_single_runtime_from_home_vars)
|
|
72
|
+
if [ -n "$home_runtime" ]; then printf '%s\n' "$home_runtime"; return 0; fi
|
|
73
|
+
# Fallback: check for agent config directories on disk.
|
|
74
|
+
home_runtime=$(_single_runtime_from_config_dirs)
|
|
75
|
+
if [ -n "$home_runtime" ]; then printf '%s\n' "$home_runtime"; return 0; fi
|
|
76
|
+
printf 'unknown\n'
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
_active_agent_runtime() {
|
|
80
|
+
local runtime
|
|
81
|
+
for runtime in $(_detectable_agent_runtimes); do
|
|
82
|
+
if _runtime_has_env_signal "$runtime"; then
|
|
83
|
+
printf '%s\n' "$runtime"
|
|
84
|
+
return 0
|
|
85
|
+
fi
|
|
86
|
+
done
|
|
87
|
+
for runtime in $(_detectable_agent_runtimes); do
|
|
88
|
+
if _runtime_has_context_signal "$runtime"; then
|
|
89
|
+
printf '%s\n' "$runtime"
|
|
90
|
+
return 0
|
|
91
|
+
fi
|
|
92
|
+
done
|
|
93
|
+
return 0
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
_detectable_agent_runtimes() {
|
|
97
|
+
printf '%s\n' claudecode codex gemini cursor copilot devin kimi opencode iflow qoder pi antigravity acp reasonix tmux openclaw hermes
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
_runtime_has_active_signal() {
|
|
101
|
+
_runtime_has_env_signal "$1" || _runtime_has_context_signal "$1"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
_runtime_has_env_signal() {
|
|
105
|
+
local runtime=$1
|
|
106
|
+
case "$runtime" in
|
|
107
|
+
acp)
|
|
108
|
+
_env_name_matches '^ACP_'
|
|
109
|
+
;;
|
|
110
|
+
antigravity)
|
|
111
|
+
_env_name_matches '^(ANTIGRAVITY_|GOOGLE_ANTIGRAVITY_|AGY_)'
|
|
112
|
+
;;
|
|
113
|
+
codex)
|
|
114
|
+
_env_name_matches '^CODEX_'
|
|
115
|
+
;;
|
|
116
|
+
claudecode|claude-code)
|
|
117
|
+
_env_name_matches '^(CLAUDECODE|CLAUDECODE_|CLAUDE_CODE_)'
|
|
118
|
+
;;
|
|
119
|
+
gemini)
|
|
120
|
+
_env_name_matches '^(GEMINI_CLI|GEMINI_CLI_|GEMINI_AGENT_|GOOGLE_GEMINI_CLI_)'
|
|
121
|
+
;;
|
|
122
|
+
cursor)
|
|
123
|
+
_env_name_matches '^CURSOR_'
|
|
124
|
+
;;
|
|
125
|
+
copilot)
|
|
126
|
+
_env_name_matches '^(COPILOT_|GITHUB_COPILOT_)'
|
|
127
|
+
;;
|
|
128
|
+
devin)
|
|
129
|
+
_env_name_matches '^(DEVIN_|WINDSURF_)'
|
|
130
|
+
;;
|
|
131
|
+
iflow)
|
|
132
|
+
_env_name_matches '^IFLOW_'
|
|
133
|
+
;;
|
|
134
|
+
kimi)
|
|
135
|
+
_env_name_matches '^KIMI_'
|
|
136
|
+
;;
|
|
137
|
+
opencode)
|
|
138
|
+
_env_name_matches '^(OPENCODE_|OPEN_CODE_)'
|
|
139
|
+
;;
|
|
140
|
+
pi)
|
|
141
|
+
_env_name_matches '^(PI_CODING_AGENT_|PI_AGENT_)'
|
|
142
|
+
;;
|
|
143
|
+
qoder)
|
|
144
|
+
_env_name_matches '^QODER_'
|
|
145
|
+
;;
|
|
146
|
+
reasonix)
|
|
147
|
+
_env_name_matches '^REASONIX_'
|
|
148
|
+
;;
|
|
149
|
+
tmux)
|
|
150
|
+
_env_name_matches '^TMUX'
|
|
151
|
+
;;
|
|
152
|
+
openclaw)
|
|
153
|
+
_env_name_matches '^OPENCLAW_'
|
|
154
|
+
;;
|
|
155
|
+
hermes)
|
|
156
|
+
_env_name_matches '^HERMES_'
|
|
157
|
+
;;
|
|
158
|
+
*) return 1 ;;
|
|
159
|
+
esac
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
_runtime_has_context_signal() {
|
|
163
|
+
local runtime=$1
|
|
164
|
+
case "$runtime" in
|
|
165
|
+
acp)
|
|
166
|
+
_active_text_contains '/.acp/' ||
|
|
167
|
+
_active_text_contains '/.agents/' ||
|
|
168
|
+
_process_name_matches 'acp'
|
|
169
|
+
;;
|
|
170
|
+
antigravity)
|
|
171
|
+
_active_text_contains '/.antigravity/' ||
|
|
172
|
+
_active_text_contains 'antigravity' ||
|
|
173
|
+
_process_name_matches 'agy'
|
|
174
|
+
;;
|
|
175
|
+
codex)
|
|
176
|
+
_active_text_contains '/.codex/tmp/' ||
|
|
177
|
+
_active_text_contains 'openai/codex' ||
|
|
178
|
+
_active_text_contains 'openai.codex' ||
|
|
179
|
+
_active_text_contains '/.codex/' ||
|
|
180
|
+
_process_name_matches 'codex'
|
|
181
|
+
;;
|
|
182
|
+
claudecode|claude-code)
|
|
183
|
+
_active_text_contains '/.claude/tmp/' ||
|
|
184
|
+
_active_text_contains '/.claude/' ||
|
|
185
|
+
_active_text_contains 'claude-code' ||
|
|
186
|
+
_process_name_matches 'claude'
|
|
187
|
+
;;
|
|
188
|
+
gemini)
|
|
189
|
+
_active_text_contains '/.gemini/tmp/' ||
|
|
190
|
+
_active_text_contains '/.gemini/' ||
|
|
191
|
+
_process_name_matches 'gemini'
|
|
192
|
+
;;
|
|
193
|
+
cursor)
|
|
194
|
+
_active_text_contains '/.cursor/tmp/' ||
|
|
195
|
+
_active_text_contains '/.cursor/' ||
|
|
196
|
+
_active_text_contains 'cursor' ||
|
|
197
|
+
_process_name_matches 'cursor'
|
|
198
|
+
;;
|
|
199
|
+
copilot)
|
|
200
|
+
_active_text_contains '/.github/copilot/' ||
|
|
201
|
+
_active_text_contains '/.copilot/' ||
|
|
202
|
+
_process_name_matches 'copilot'
|
|
203
|
+
;;
|
|
204
|
+
devin)
|
|
205
|
+
_active_text_contains '/.devin/' ||
|
|
206
|
+
_process_name_matches 'devin'
|
|
207
|
+
;;
|
|
208
|
+
iflow)
|
|
209
|
+
_active_text_contains '/.iflow/' ||
|
|
210
|
+
_process_name_matches 'iflow'
|
|
211
|
+
;;
|
|
212
|
+
kimi)
|
|
213
|
+
_active_text_contains '/.kimi/' ||
|
|
214
|
+
_process_name_matches 'kimi'
|
|
215
|
+
;;
|
|
216
|
+
opencode)
|
|
217
|
+
_active_text_contains '/.opencode/' ||
|
|
218
|
+
_active_text_contains '/.open-code/' ||
|
|
219
|
+
_process_name_matches 'opencode'
|
|
220
|
+
;;
|
|
221
|
+
pi)
|
|
222
|
+
_active_text_contains '/.pi/agent/' ||
|
|
223
|
+
_process_name_matches 'pi'
|
|
224
|
+
;;
|
|
225
|
+
qoder)
|
|
226
|
+
_active_text_contains '/.qoder/' ||
|
|
227
|
+
_process_name_matches 'qoder'
|
|
228
|
+
;;
|
|
229
|
+
reasonix)
|
|
230
|
+
_active_text_contains '/.reasonix/' ||
|
|
231
|
+
_process_name_matches 'reasonix'
|
|
232
|
+
;;
|
|
233
|
+
tmux)
|
|
234
|
+
_process_name_matches 'tmux'
|
|
235
|
+
;;
|
|
236
|
+
openclaw)
|
|
237
|
+
_active_text_contains '/.openclaw/tmp/' ||
|
|
238
|
+
_active_text_contains '/.openclaw/' ||
|
|
239
|
+
_process_name_matches 'openclaw'
|
|
240
|
+
;;
|
|
241
|
+
hermes)
|
|
242
|
+
_active_text_contains '/.hermes/tmp/' ||
|
|
243
|
+
_active_text_contains '/.hermes/' ||
|
|
244
|
+
_process_name_matches 'hermes'
|
|
245
|
+
;;
|
|
246
|
+
*) return 1 ;;
|
|
247
|
+
esac
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
_single_runtime_from_home_vars() {
|
|
251
|
+
_single_runtime_from_sources vars
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
_single_runtime_from_config_dirs() {
|
|
255
|
+
_single_runtime_from_sources dirs
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
_single_runtime_from_sources() {
|
|
259
|
+
local source=$1 runtime match count=0
|
|
260
|
+
for runtime in $(_detectable_agent_runtimes); do
|
|
261
|
+
case "$source" in
|
|
262
|
+
vars)
|
|
263
|
+
_runtime_home_var_is_set "$runtime" || continue
|
|
264
|
+
;;
|
|
265
|
+
dirs)
|
|
266
|
+
_runtime_config_dir_exists "$runtime" || continue
|
|
267
|
+
;;
|
|
268
|
+
esac
|
|
269
|
+
match=$runtime
|
|
270
|
+
count=$((count+1))
|
|
271
|
+
done
|
|
272
|
+
if [ "$count" -eq 1 ]; then
|
|
273
|
+
printf '%s\n' "$match"
|
|
274
|
+
fi
|
|
275
|
+
return 0
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
_runtime_home_var_is_set() {
|
|
279
|
+
case "$1" in
|
|
280
|
+
acp) [ -n "${ACP_HOME:-}" ] ;;
|
|
281
|
+
antigravity) [ -n "${ANTIGRAVITY_HOME:-}" ] || [ -n "${AGY_HOME:-}" ] ;;
|
|
282
|
+
claudecode|claude-code) [ -n "${CLAUDE_HOME:-}" ] || [ -n "${CLAUDECODE_HOME:-}" ] ;;
|
|
283
|
+
codex) [ -n "${CODEX_HOME:-}" ] ;;
|
|
284
|
+
copilot) [ -n "${COPILOT_HOME:-}" ] ;;
|
|
285
|
+
cursor) [ -n "${CURSOR_HOME:-}" ] ;;
|
|
286
|
+
devin) [ -n "${DEVIN_HOME:-}" ] ;;
|
|
287
|
+
gemini) [ -n "${GEMINI_HOME:-}" ] ;;
|
|
288
|
+
iflow) [ -n "${IFLOW_HOME:-}" ] ;;
|
|
289
|
+
kimi) [ -n "${KIMI_HOME:-}" ] ;;
|
|
290
|
+
opencode) [ -n "${OPENCODE_HOME:-}" ] || [ -n "${OPEN_CODE_HOME:-}" ] ;;
|
|
291
|
+
pi) [ -n "${PI_CODING_AGENT_DIR:-}" ] || [ -n "${PI_HOME:-}" ] ;;
|
|
292
|
+
qoder) [ -n "${QODER_HOME:-}" ] ;;
|
|
293
|
+
reasonix) [ -n "${REASONIX_HOME:-}" ] ;;
|
|
294
|
+
tmux) [ -n "${TMUX_HOME:-}" ] ;;
|
|
295
|
+
openclaw) [ -n "${OPENCLAW_HOME:-}" ] ;;
|
|
296
|
+
hermes) [ -n "${HERMES_HOME:-}" ] ;;
|
|
297
|
+
*) return 1 ;;
|
|
298
|
+
esac
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
_runtime_config_dir_exists() {
|
|
302
|
+
case "$1" in
|
|
303
|
+
acp) [ -d "$HOME/.acp" ] ;;
|
|
304
|
+
antigravity) [ -d "$HOME/.antigravity" ] ;;
|
|
305
|
+
claudecode|claude-code) [ -d "$HOME/.claude" ] ;;
|
|
306
|
+
codex) [ -d "$HOME/.codex" ] ;;
|
|
307
|
+
copilot) [ -d "$HOME/.copilot" ] || [ -d "$HOME/.github/copilot" ] ;;
|
|
308
|
+
cursor) [ -d "$HOME/.cursor" ] ;;
|
|
309
|
+
devin) [ -d "$HOME/.devin" ] ;;
|
|
310
|
+
gemini) [ -d "$HOME/.gemini" ] ;;
|
|
311
|
+
iflow) [ -d "$HOME/.iflow" ] ;;
|
|
312
|
+
kimi) [ -d "$HOME/.kimi" ] ;;
|
|
313
|
+
opencode) [ -d "$HOME/.opencode" ] || [ -d "$HOME/.open-code" ] ;;
|
|
314
|
+
pi) [ -d "$HOME/.pi/agent" ] || [ -d "$HOME/.pi" ] ;;
|
|
315
|
+
qoder) [ -d "$HOME/.qoder" ] ;;
|
|
316
|
+
reasonix) [ -d "$HOME/.reasonix" ] ;;
|
|
317
|
+
tmux) [ -d "$HOME/.tmux" ] ;;
|
|
318
|
+
openclaw) [ -d "$HOME/.openclaw" ] ;;
|
|
319
|
+
hermes) [ -d "$HOME/.hermes" ] ;;
|
|
320
|
+
*) return 1 ;;
|
|
321
|
+
esac
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
_env_name_matches() {
|
|
325
|
+
env | sed -E 's/=.*$//' | grep -Eq "$1"
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
_active_text_contains() {
|
|
329
|
+
local needle=$1 text
|
|
330
|
+
text=$(printf '%s:%s' "${PATH:-}" "${PWD:-}" | tr '[:upper:]' '[:lower:]')
|
|
331
|
+
case "$text" in
|
|
332
|
+
*"$needle"*) return 0 ;;
|
|
333
|
+
*) return 1 ;;
|
|
334
|
+
esac
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
_process_name_matches() {
|
|
338
|
+
local needle=$1
|
|
339
|
+
[ "${DIREXIO_AGENT_DETECT_PROCESS:-1}" != "0" ] || return 1
|
|
340
|
+
_process_tree_names | tr '[:upper:]' '[:lower:]' | grep -Eq "(^|[^a-z0-9])${needle}([^a-z0-9]|$)"
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
_process_tree_names() {
|
|
344
|
+
local pid=${BASHPID:-$$} ppid depth=0
|
|
345
|
+
while [ -n "$pid" ] && [ "$pid" != "0" ] && [ "$depth" -lt 12 ]; do
|
|
346
|
+
ps -o comm= -p "$pid" 2>/dev/null || true
|
|
347
|
+
ppid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d '[:space:]')
|
|
348
|
+
[ -n "$ppid" ] && [ "$ppid" != "$pid" ] || break
|
|
349
|
+
pid=$ppid
|
|
350
|
+
depth=$((depth+1))
|
|
351
|
+
done
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
_validate_agent_platform() {
|
|
355
|
+
case "$1" in
|
|
356
|
+
auto|generic|unknown|openclaw|hermes) return 0 ;;
|
|
357
|
+
*)
|
|
358
|
+
_cc_connect_agent_alias "$1" >/dev/null 2>&1 && return 0
|
|
359
|
+
fail "DIREXIO_AGENT_PLATFORM must be auto, a cc-connect agent ($(_cc_connect_supported_agents_csv)), openclaw, hermes, generic, or unknown."
|
|
360
|
+
;;
|
|
361
|
+
esac
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
_agent_install_policy() {
|
|
365
|
+
local policy=${DIREXIO_AGENT_INSTALL:-recommend}
|
|
366
|
+
case "$policy" in
|
|
367
|
+
skip|recommend|auto) printf '%s\n' "$policy" ;;
|
|
368
|
+
*) fail "DIREXIO_AGENT_INSTALL must be skip, recommend, or auto." ;;
|
|
369
|
+
esac
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
_agent_install_mode() {
|
|
373
|
+
local runtime=$1 mode=${DIREXIO_AGENT_INSTALL_MODE:-recommended}
|
|
374
|
+
case "$mode" in
|
|
375
|
+
recommended)
|
|
376
|
+
printf 'cc-connect\n'
|
|
377
|
+
;;
|
|
378
|
+
cc-connect) printf '%s\n' "$mode" ;;
|
|
379
|
+
*) fail "DIREXIO_AGENT_INSTALL_MODE must be recommended or cc-connect." ;;
|
|
380
|
+
esac
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
_validate_real_agent_room_id() {
|
|
384
|
+
local room_id=$1
|
|
385
|
+
[ -n "$room_id" ] || fail "state is missing real agent_room_id; complete S5 against a current message-server build."
|
|
386
|
+
case "$room_id" in
|
|
387
|
+
\!agent:*) fail "legacy agent_room_id $room_id is not supported; redeploy or restart message-server so it creates a real agents room." ;;
|
|
388
|
+
\!*) return 0 ;;
|
|
389
|
+
*) fail "agent_room_id must be a Matrix room id beginning with !, got: $room_id" ;;
|
|
390
|
+
esac
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
_cc_connect_agent_type() {
|
|
394
|
+
local runtime=$1 explicit=${DIREXIO_CC_CONNECT_AGENT:-}
|
|
395
|
+
if [ -n "$explicit" ]; then
|
|
396
|
+
_validate_cc_connect_agent "$explicit"
|
|
397
|
+
return 0
|
|
398
|
+
fi
|
|
399
|
+
case "$runtime" in
|
|
400
|
+
openclaw|hermes) printf 'acp\n'; return 0 ;;
|
|
401
|
+
esac
|
|
402
|
+
_validate_cc_connect_agent "$runtime"
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
_cc_connect_agent_command() {
|
|
406
|
+
local agent runtime raw_key var value
|
|
407
|
+
runtime=${2:-$1}
|
|
408
|
+
agent=$(_cc_connect_agent_alias "$1" 2>/dev/null || printf '%s\n' "$1")
|
|
409
|
+
if [ -n "${DIREXIO_CC_CONNECT_AGENT_CMD:-}" ]; then
|
|
410
|
+
printf '%s\n' "$DIREXIO_CC_CONNECT_AGENT_CMD"
|
|
411
|
+
return 0
|
|
412
|
+
fi
|
|
413
|
+
if [ "$runtime" = "hermes" ] && [ "$agent" = "acp" ]; then
|
|
414
|
+
_local_connect_path "${DIREXIO_HERMES_ACP_ADAPTER_COMMAND:-${DIREXIO_CC_CONNECT_BIN:-direxio-connect}}"
|
|
415
|
+
return 0
|
|
416
|
+
fi
|
|
417
|
+
for raw_key in $(_cc_connect_runtime_command_aliases "$runtime") "$agent" $(_cc_connect_agent_command_aliases "$agent"); do
|
|
418
|
+
var="DIREXIO_$(printf '%s' "$raw_key" | tr '[:lower:]-' '[:upper:]_')_COMMAND"
|
|
419
|
+
value=$(printenv "$var" 2>/dev/null || true)
|
|
420
|
+
if [ -n "$value" ]; then
|
|
421
|
+
printf '%s\n' "$value"
|
|
422
|
+
return 0
|
|
423
|
+
fi
|
|
424
|
+
done
|
|
425
|
+
case "$runtime" in
|
|
426
|
+
openclaw|hermes) printf '%s\n' "$runtime" ;;
|
|
427
|
+
esac
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
_cc_connect_runtime_command_aliases() {
|
|
431
|
+
case "$1" in
|
|
432
|
+
openclaw) printf '%s\n' openclaw ;;
|
|
433
|
+
hermes) printf '%s\n' hermes ;;
|
|
434
|
+
esac
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
_cc_connect_agent_command_aliases() {
|
|
438
|
+
case "$1" in
|
|
439
|
+
claudecode) printf '%s\n' claude-code claude ;;
|
|
440
|
+
opencode) printf '%s\n' open-code ;;
|
|
441
|
+
antigravity) printf '%s\n' agy ;;
|
|
442
|
+
qoder) printf '%s\n' qodercli ;;
|
|
443
|
+
esac
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
_cc_connect_repo() {
|
|
447
|
+
printf '%s\n' "${DIREXIO_CC_CONNECT_REPO:-https://github.com/YingSuiAI/direxio-connect.git}"
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
_cc_connect_npm_package() {
|
|
451
|
+
printf '%s\n' "${DIREXIO_CC_CONNECT_NPM_PACKAGE:-direxio-connent@latest}"
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
_cc_connect_ref() {
|
|
455
|
+
printf '%s\n' "${DIREXIO_CC_CONNECT_REF:-main}"
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
_cc_connect_source_dir() {
|
|
459
|
+
local service_dir=$1
|
|
460
|
+
printf '%s\n' "${DIREXIO_CC_CONNECT_DIR:-$service_dir/cc-connect-src}"
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
_cc_connect_runtime_dir() {
|
|
464
|
+
local service_dir=$1
|
|
465
|
+
printf '%s/cc-connect\n' "$service_dir"
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
_agent_workspace() {
|
|
469
|
+
local service_dir=$1
|
|
470
|
+
if [ -n "${DIREXIO_AGENT_WORKSPACE:-}" ]; then
|
|
471
|
+
printf '%s\n' "$DIREXIO_AGENT_WORKSPACE"
|
|
472
|
+
return 0
|
|
473
|
+
fi
|
|
474
|
+
if [ -n "${DIREXIO_AGENT_WORKSPACE_WINDOWS:-}" ]; then
|
|
475
|
+
printf '%s\n' "$DIREXIO_AGENT_WORKSPACE_WINDOWS"
|
|
476
|
+
return 0
|
|
477
|
+
fi
|
|
478
|
+
printf '%s/workspace\n' "$service_dir"
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
_cc_connect_config_path() {
|
|
482
|
+
local service_dir=$1
|
|
483
|
+
printf '%s/config.toml\n' "$(_cc_connect_runtime_dir "$service_dir")"
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
_mcp_npm_package() {
|
|
487
|
+
printf '%s\n' "${DIREXIO_MCP_NPM_PACKAGE:-direxio-mcp@latest}"
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
_mcp_command() {
|
|
491
|
+
printf '%s\n' "${DIREXIO_MCP_COMMAND:-direxio-mcp}"
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
_mcp_runtime_dir() {
|
|
495
|
+
local service_dir=$1
|
|
496
|
+
printf '%s/mcp\n' "$service_dir"
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
_mcp_codex_config_path() {
|
|
500
|
+
local service_dir=$1
|
|
501
|
+
printf '%s/codex.toml\n' "$(_mcp_runtime_dir "$service_dir")"
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
_mcp_json_config_path() {
|
|
505
|
+
local service_dir=$1
|
|
506
|
+
printf '%s/mcp-servers.json\n' "$(_mcp_runtime_dir "$service_dir")"
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
_mcp_openclaw_config_path() {
|
|
510
|
+
local service_dir=$1
|
|
511
|
+
printf '%s/openclaw.md\n' "$(_mcp_runtime_dir "$service_dir")"
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
_mcp_openclaw_server_config_path() {
|
|
515
|
+
local service_dir=$1
|
|
516
|
+
printf '%s/openclaw-server.json\n' "$(_mcp_runtime_dir "$service_dir")"
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
_mcp_hermes_config_path() {
|
|
520
|
+
local service_dir=$1
|
|
521
|
+
printf '%s/hermes.mcp.json\n' "$(_mcp_runtime_dir "$service_dir")"
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
_mcp_env_file_path() {
|
|
525
|
+
local service_dir=$1
|
|
526
|
+
printf '%s/env\n' "$(_mcp_runtime_dir "$service_dir")"
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
_mcp_readme_path() {
|
|
530
|
+
local service_dir=$1
|
|
531
|
+
printf '%s/README.md\n' "$(_mcp_runtime_dir "$service_dir")"
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
_mcp_server_name() {
|
|
535
|
+
local service_id=${1:-local}
|
|
536
|
+
printf 'direxio-%s\n' "$service_id" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9_-]+/_/g; s/^_+//; s/_+$//; s/^$/direxio_local/'
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
_cc_connect_binary_path() {
|
|
540
|
+
local service_dir=$1
|
|
541
|
+
printf '%s\n' "${DIREXIO_CC_CONNECT_BIN:-direxio-connect}"
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
_cc_connect_agent_options_toml() {
|
|
545
|
+
local runtime=${1:-} agent=${2:-} args_toml q_display
|
|
546
|
+
if [ -n "${DIREXIO_CC_CONNECT_AGENT_OPTIONS_TOML:-}" ]; then
|
|
547
|
+
printf '%s\n' "$DIREXIO_CC_CONNECT_AGENT_OPTIONS_TOML"
|
|
548
|
+
return 0
|
|
549
|
+
fi
|
|
550
|
+
case "$runtime:$agent" in
|
|
551
|
+
openclaw:acp)
|
|
552
|
+
args_toml=$(_openclaw_acp_args_toml) || return 1
|
|
553
|
+
q_display=$(_toml_escape "OpenClaw ACP")
|
|
554
|
+
printf 'args = %s\n' "$args_toml"
|
|
555
|
+
printf 'display_name = "%s"\n' "$q_display"
|
|
556
|
+
;;
|
|
557
|
+
hermes:acp)
|
|
558
|
+
args_toml=$(_hermes_acp_args_toml)
|
|
559
|
+
q_display=$(_toml_escape "Hermes ACP")
|
|
560
|
+
printf 'args = %s\n' "$args_toml"
|
|
561
|
+
printf 'display_name = "%s"\n' "$q_display"
|
|
562
|
+
;;
|
|
563
|
+
esac
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
_openclaw_acp_args_toml() {
|
|
567
|
+
local url token_file session missing=
|
|
568
|
+
if [ -n "${DIREXIO_OPENCLAW_ACP_ARGS_TOML:-}" ]; then
|
|
569
|
+
printf '%s\n' "$DIREXIO_OPENCLAW_ACP_ARGS_TOML"
|
|
570
|
+
return 0
|
|
571
|
+
fi
|
|
572
|
+
url=${DIREXIO_OPENCLAW_ACP_URL:-}
|
|
573
|
+
token_file=${DIREXIO_OPENCLAW_ACP_TOKEN_FILE:-}
|
|
574
|
+
session=${DIREXIO_OPENCLAW_ACP_SESSION:-}
|
|
575
|
+
[ -n "$url" ] || missing="${missing} DIREXIO_OPENCLAW_ACP_URL"
|
|
576
|
+
[ -n "$token_file" ] || missing="${missing} DIREXIO_OPENCLAW_ACP_TOKEN_FILE"
|
|
577
|
+
[ -n "$session" ] || missing="${missing} DIREXIO_OPENCLAW_ACP_SESSION"
|
|
578
|
+
if [ -n "$missing" ]; then
|
|
579
|
+
fail "OpenClaw ACP requires real Gateway settings:${missing}. Set them from the current OpenClaw runtime, or provide DIREXIO_OPENCLAW_ACP_ARGS_TOML with the complete args array."
|
|
580
|
+
return 1
|
|
581
|
+
fi
|
|
582
|
+
token_file=$(_local_connect_path "$token_file")
|
|
583
|
+
_toml_array acp --url "$url" --token-file "$token_file" --session "$session"
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
_hermes_acp_args_toml() {
|
|
587
|
+
local hermes_cmd
|
|
588
|
+
hermes_cmd=${DIREXIO_HERMES_COMMAND:-hermes}
|
|
589
|
+
hermes_cmd=$(_local_connect_path "$hermes_cmd")
|
|
590
|
+
if [ -n "${DIREXIO_HERMES_ACP_ARGS_TOML:-}" ]; then
|
|
591
|
+
_toml_array_prepend "$DIREXIO_HERMES_ACP_ARGS_TOML" hermes-acp-adapter -- "$hermes_cmd"
|
|
592
|
+
return 0
|
|
593
|
+
fi
|
|
594
|
+
_toml_array hermes-acp-adapter -- "$hermes_cmd" acp
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
_toml_array() {
|
|
598
|
+
local first=1 value q_value
|
|
599
|
+
printf '['
|
|
600
|
+
for value in "$@"; do
|
|
601
|
+
q_value=$(_toml_escape "$value")
|
|
602
|
+
if [ "$first" -eq 0 ]; then
|
|
603
|
+
printf ', '
|
|
604
|
+
fi
|
|
605
|
+
printf '"%s"' "$q_value"
|
|
606
|
+
first=0
|
|
607
|
+
done
|
|
608
|
+
printf ']\n'
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
_toml_array_prepend() {
|
|
612
|
+
local suffix_toml=$1 prefix_toml suffix_inner
|
|
613
|
+
shift
|
|
614
|
+
prefix_toml=$(_toml_array "$@")
|
|
615
|
+
suffix_inner=$(printf '%s' "$suffix_toml" | sed -E 's/^[[:space:]]*\[[[:space:]]*//; s/[[:space:]]*\][[:space:]]*$//')
|
|
616
|
+
if [ -z "$suffix_inner" ]; then
|
|
617
|
+
printf '%s\n' "$prefix_toml"
|
|
618
|
+
return 0
|
|
619
|
+
fi
|
|
620
|
+
printf '%s, %s]\n' "${prefix_toml%]}" "$suffix_inner"
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
_toml_has_key() {
|
|
624
|
+
local toml=$1 key=$2
|
|
625
|
+
printf '%s\n' "$toml" | grep -Eq "^[[:space:]]*${key}[[:space:]]*="
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
_cc_connect_default_agent_options_toml() {
|
|
629
|
+
local agent=$1 custom_toml=${2:-}
|
|
630
|
+
case "$agent" in
|
|
631
|
+
codex)
|
|
632
|
+
_toml_has_key "$custom_toml" backend || printf 'backend = "app_server"\n'
|
|
633
|
+
_toml_has_key "$custom_toml" app_server_url || printf 'app_server_url = "stdio"\n'
|
|
634
|
+
_toml_has_key "$custom_toml" mode || printf 'mode = "yolo"\n'
|
|
635
|
+
;;
|
|
636
|
+
esac
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
_toml_escape() {
|
|
640
|
+
printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
_powershell_single_quote() {
|
|
644
|
+
printf '%s' "$1" | sed "s/'/''/g"
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
_env_first() {
|
|
648
|
+
local name value
|
|
649
|
+
for name in "$@"; do
|
|
650
|
+
value=${!name:-}
|
|
651
|
+
if [ -n "$value" ]; then
|
|
652
|
+
printf '%s\n' "$value"
|
|
653
|
+
return 0
|
|
654
|
+
fi
|
|
655
|
+
done
|
|
656
|
+
return 0
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
_lower() {
|
|
660
|
+
printf '%s' "$1" | tr '[:upper:]' '[:lower:]'
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
_cc_connect_speech_config_toml() {
|
|
664
|
+
local enabled provider language api_key base_url model
|
|
665
|
+
local q_provider q_language q_api_key q_base_url q_model
|
|
666
|
+
enabled=$(_lower "${DIREXIO_SPEECH_ENABLED:-auto}")
|
|
667
|
+
case "$enabled" in
|
|
668
|
+
0|false|off|no|disabled) return 0 ;;
|
|
669
|
+
""|1|true|on|yes|auto|enabled) ;;
|
|
670
|
+
*) fail "DIREXIO_SPEECH_ENABLED must be auto, true, or false." ;;
|
|
671
|
+
esac
|
|
672
|
+
|
|
673
|
+
provider=$(_lower "${DIREXIO_SPEECH_PROVIDER:-openai}")
|
|
674
|
+
language=${DIREXIO_SPEECH_LANGUAGE:-zh}
|
|
675
|
+
case "$provider" in
|
|
676
|
+
openai)
|
|
677
|
+
api_key=$(_env_first DIREXIO_SPEECH_OPENAI_API_KEY DIREXIO_SPEECH_API_KEY OPENAI_API_KEY)
|
|
678
|
+
base_url=$(_env_first DIREXIO_SPEECH_OPENAI_BASE_URL DIREXIO_SPEECH_BASE_URL OPENAI_BASE_URL)
|
|
679
|
+
model=$(_env_first DIREXIO_SPEECH_OPENAI_MODEL DIREXIO_SPEECH_MODEL)
|
|
680
|
+
;;
|
|
681
|
+
groq)
|
|
682
|
+
api_key=$(_env_first DIREXIO_SPEECH_GROQ_API_KEY DIREXIO_SPEECH_API_KEY GROQ_API_KEY)
|
|
683
|
+
model=$(_env_first DIREXIO_SPEECH_GROQ_MODEL DIREXIO_SPEECH_MODEL)
|
|
684
|
+
;;
|
|
685
|
+
qwen)
|
|
686
|
+
api_key=$(_env_first DIREXIO_SPEECH_QWEN_API_KEY DIREXIO_SPEECH_API_KEY DASHSCOPE_API_KEY DASH_SCOPE_API_KEY)
|
|
687
|
+
base_url=$(_env_first DIREXIO_SPEECH_QWEN_BASE_URL DIREXIO_SPEECH_BASE_URL)
|
|
688
|
+
model=$(_env_first DIREXIO_SPEECH_QWEN_MODEL DIREXIO_SPEECH_MODEL)
|
|
689
|
+
;;
|
|
690
|
+
gemini)
|
|
691
|
+
api_key=$(_env_first DIREXIO_SPEECH_GEMINI_API_KEY DIREXIO_SPEECH_API_KEY GEMINI_API_KEY GOOGLE_API_KEY)
|
|
692
|
+
model=$(_env_first DIREXIO_SPEECH_GEMINI_MODEL DIREXIO_SPEECH_MODEL)
|
|
693
|
+
;;
|
|
694
|
+
*) fail "DIREXIO_SPEECH_PROVIDER must be openai, groq, qwen, or gemini." ;;
|
|
695
|
+
esac
|
|
696
|
+
if [ -z "$api_key" ]; then
|
|
697
|
+
return 0
|
|
698
|
+
fi
|
|
699
|
+
|
|
700
|
+
q_provider=$(_toml_escape "$provider")
|
|
701
|
+
q_language=$(_toml_escape "$language")
|
|
702
|
+
q_api_key=$(_toml_escape "$api_key")
|
|
703
|
+
q_base_url=$(_toml_escape "$base_url")
|
|
704
|
+
q_model=$(_toml_escape "$model")
|
|
705
|
+
cat <<EOF
|
|
706
|
+
[speech]
|
|
707
|
+
enabled = true
|
|
708
|
+
provider = "$q_provider"
|
|
709
|
+
language = "$q_language"
|
|
710
|
+
|
|
711
|
+
[speech.$q_provider]
|
|
712
|
+
api_key = "$q_api_key"
|
|
713
|
+
EOF
|
|
714
|
+
if [ -n "$base_url" ]; then
|
|
715
|
+
printf 'base_url = "%s"\n' "$q_base_url"
|
|
716
|
+
fi
|
|
717
|
+
if [ -n "$model" ]; then
|
|
718
|
+
printf 'model = "%s"\n' "$q_model"
|
|
719
|
+
fi
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
_upper_drive() {
|
|
723
|
+
printf '%s' "$1" | tr '[:lower:]' '[:upper:]'
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
_local_path_style() {
|
|
727
|
+
printf '%s\n' "${DIREXIO_LOCAL_PATH_STYLE:-posix}"
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
_local_connect_path() {
|
|
731
|
+
local path=$1 drive rest
|
|
732
|
+
case "$(_local_path_style)" in
|
|
733
|
+
windows)
|
|
734
|
+
case "$path" in
|
|
735
|
+
[A-Za-z]:/*|[A-Za-z]:\\*) printf '%s\n' "$path" | sed 's#\\#/#g'; return 0 ;;
|
|
736
|
+
/mnt/[A-Za-z]/*)
|
|
737
|
+
drive=$(_upper_drive "$(printf '%s' "$path" | cut -d/ -f3)")
|
|
738
|
+
rest=$(printf '%s' "$path" | cut -d/ -f4-)
|
|
739
|
+
printf '%s:/%s\n' "$drive" "$rest"
|
|
740
|
+
return 0
|
|
741
|
+
;;
|
|
742
|
+
/[A-Za-z]/*)
|
|
743
|
+
drive=$(_upper_drive "$(printf '%s' "$path" | cut -d/ -f2)")
|
|
744
|
+
rest=$(printf '%s' "$path" | cut -d/ -f3-)
|
|
745
|
+
printf '%s:/%s\n' "$drive" "$rest"
|
|
746
|
+
return 0
|
|
747
|
+
;;
|
|
748
|
+
esac
|
|
749
|
+
;;
|
|
750
|
+
esac
|
|
751
|
+
printf '%s\n' "$path"
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
_mcp_install_command() {
|
|
755
|
+
printf 'npm install -g %q' "$(_mcp_npm_package)"
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
_mcp_doctor_command() {
|
|
759
|
+
local credentials_file=$1 node_id=${2:-}
|
|
760
|
+
printf 'DIREXIO_CREDENTIALS_FILE=%q' "$(_local_connect_path "$credentials_file")"
|
|
761
|
+
if [ -n "$node_id" ]; then
|
|
762
|
+
printf ' DIREXIO_AGENT_NODE_ID=%q' "$node_id"
|
|
763
|
+
fi
|
|
764
|
+
printf ' %q doctor --json\n' "$(_mcp_command)"
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
_write_mcp_json_config() {
|
|
768
|
+
local path=$1 server_name=$2 command=$3 credentials_file=$4 node_id=${5:-}
|
|
769
|
+
mkdir -p "$(dirname "$path")"
|
|
770
|
+
umask 077
|
|
771
|
+
jq -n \
|
|
772
|
+
--arg server_name "$server_name" \
|
|
773
|
+
--arg command "$command" \
|
|
774
|
+
--arg credentials_file "$credentials_file" \
|
|
775
|
+
--arg node_id "$node_id" \
|
|
776
|
+
'{
|
|
777
|
+
mcpServers: {
|
|
778
|
+
($server_name): {
|
|
779
|
+
command: $command,
|
|
780
|
+
env: {
|
|
781
|
+
DIREXIO_CREDENTIALS_FILE: $credentials_file,
|
|
782
|
+
DIREXIO_AGENT_NODE_ID: $node_id
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}' > "$path"
|
|
787
|
+
chmod 600 "$path" 2>/dev/null || true
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
_write_mcp_openclaw_server_config() {
|
|
791
|
+
local path=$1 command=$2 credentials_file=$3 node_id=${4:-}
|
|
792
|
+
mkdir -p "$(dirname "$path")"
|
|
793
|
+
umask 077
|
|
794
|
+
jq -n \
|
|
795
|
+
--arg command "$command" \
|
|
796
|
+
--arg credentials_file "$credentials_file" \
|
|
797
|
+
--arg node_id "$node_id" \
|
|
798
|
+
'{
|
|
799
|
+
command: $command,
|
|
800
|
+
env: {
|
|
801
|
+
DIREXIO_CREDENTIALS_FILE: $credentials_file,
|
|
802
|
+
DIREXIO_AGENT_NODE_ID: $node_id
|
|
803
|
+
}
|
|
804
|
+
}' > "$path"
|
|
805
|
+
chmod 600 "$path" 2>/dev/null || true
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
_write_mcp_config_artifacts() {
|
|
809
|
+
local service_id=$1 service_dir=$2 credentials_file=$3 node_id=${4:-}
|
|
810
|
+
local mcp_dir server_name command credentials_local q_server q_command q_credentials q_node
|
|
811
|
+
local codex_config json_config openclaw_config openclaw_server_config hermes_config env_file readme
|
|
812
|
+
local openclaw_server_config_local openclaw_server_config_bash openclaw_server_config_ps
|
|
813
|
+
mcp_dir=$(_mcp_runtime_dir "$service_dir")
|
|
814
|
+
server_name=$(_mcp_server_name "$service_id")
|
|
815
|
+
command=$(_mcp_command)
|
|
816
|
+
credentials_local=$(_local_connect_path "$credentials_file")
|
|
817
|
+
q_server=$(_toml_escape "$server_name")
|
|
818
|
+
q_command=$(_toml_escape "$command")
|
|
819
|
+
q_credentials=$(_toml_escape "$credentials_local")
|
|
820
|
+
q_node=$(_toml_escape "$node_id")
|
|
821
|
+
codex_config=$(_mcp_codex_config_path "$service_dir")
|
|
822
|
+
json_config=$(_mcp_json_config_path "$service_dir")
|
|
823
|
+
openclaw_config=$(_mcp_openclaw_config_path "$service_dir")
|
|
824
|
+
openclaw_server_config=$(_mcp_openclaw_server_config_path "$service_dir")
|
|
825
|
+
hermes_config=$(_mcp_hermes_config_path "$service_dir")
|
|
826
|
+
env_file=$(_mcp_env_file_path "$service_dir")
|
|
827
|
+
readme=$(_mcp_readme_path "$service_dir")
|
|
828
|
+
|
|
829
|
+
mkdir -p "$mcp_dir"
|
|
830
|
+
umask 077
|
|
831
|
+
cat > "$codex_config" <<EOF
|
|
832
|
+
[mcp_servers."$q_server"]
|
|
833
|
+
command = "$q_command"
|
|
834
|
+
env = { DIREXIO_CREDENTIALS_FILE = "$q_credentials", DIREXIO_AGENT_NODE_ID = "$q_node" }
|
|
835
|
+
EOF
|
|
836
|
+
chmod 600 "$codex_config" 2>/dev/null || true
|
|
837
|
+
|
|
838
|
+
rm -f "$mcp_dir/openclaw.mcp.json"
|
|
839
|
+
_write_mcp_json_config "$json_config" "$server_name" "$command" "$credentials_local" "$node_id"
|
|
840
|
+
_write_mcp_openclaw_server_config "$openclaw_server_config" "$command" "$credentials_local" "$node_id"
|
|
841
|
+
_write_mcp_json_config "$hermes_config" "$server_name" "$command" "$credentials_local" "$node_id"
|
|
842
|
+
|
|
843
|
+
openclaw_server_config_local=$(_local_connect_path "$openclaw_server_config")
|
|
844
|
+
openclaw_server_config_bash=$(printf '%q' "$openclaw_server_config_local")
|
|
845
|
+
openclaw_server_config_ps=$(_powershell_single_quote "$openclaw_server_config_local")
|
|
846
|
+
cat > "$openclaw_config" <<EOF
|
|
847
|
+
# OpenClaw MCP Setup
|
|
848
|
+
|
|
849
|
+
OpenClaw must manage MCP servers through its own CLI/schema. Do not paste Codex/Hermes mcpServers snippets, or any raw top-level mcp block from this directory, into openclaw.json.
|
|
850
|
+
|
|
851
|
+
Server object for openclaw mcp set:
|
|
852
|
+
|
|
853
|
+
$openclaw_server_config_local
|
|
854
|
+
|
|
855
|
+
POSIX/Git Bash:
|
|
856
|
+
|
|
857
|
+
\`\`\`bash
|
|
858
|
+
openclaw mcp set $server_name "\$(cat $openclaw_server_config_bash)"
|
|
859
|
+
openclaw mcp doctor
|
|
860
|
+
openclaw mcp reload
|
|
861
|
+
\`\`\`
|
|
862
|
+
|
|
863
|
+
PowerShell:
|
|
864
|
+
|
|
865
|
+
\`\`\`powershell
|
|
866
|
+
openclaw mcp set $server_name (Get-Content -Raw -LiteralPath '$openclaw_server_config_ps')
|
|
867
|
+
openclaw mcp doctor
|
|
868
|
+
openclaw mcp reload
|
|
869
|
+
\`\`\`
|
|
870
|
+
|
|
871
|
+
This writes the server under OpenClaw's mcp.servers schema after OpenClaw validates it.
|
|
872
|
+
EOF
|
|
873
|
+
chmod 644 "$openclaw_config" 2>/dev/null || true
|
|
874
|
+
|
|
875
|
+
{
|
|
876
|
+
printf 'export DIREXIO_CREDENTIALS_FILE=%q\n' "$credentials_local"
|
|
877
|
+
[ -n "$node_id" ] && printf 'export DIREXIO_AGENT_NODE_ID=%q\n' "$node_id"
|
|
878
|
+
} > "$env_file"
|
|
879
|
+
chmod 600 "$env_file" 2>/dev/null || true
|
|
880
|
+
|
|
881
|
+
cat > "$readme" <<EOF
|
|
882
|
+
# Direxio MCP Config
|
|
883
|
+
|
|
884
|
+
Install the local MCP package:
|
|
885
|
+
|
|
886
|
+
\`\`\`bash
|
|
887
|
+
$(_mcp_install_command)
|
|
888
|
+
\`\`\`
|
|
889
|
+
|
|
890
|
+
Check this service's MCP credentials:
|
|
891
|
+
|
|
892
|
+
\`\`\`bash
|
|
893
|
+
$(_mcp_doctor_command "$credentials_file" "$node_id")
|
|
894
|
+
\`\`\`
|
|
895
|
+
|
|
896
|
+
Config snippets:
|
|
897
|
+
|
|
898
|
+
- Codex TOML: $(_local_connect_path "$codex_config")
|
|
899
|
+
- OpenClaw CLI setup: $(_local_connect_path "$openclaw_config")
|
|
900
|
+
- Hermes JSON: $(_local_connect_path "$hermes_config")
|
|
901
|
+
- Generic JSON: $(_local_connect_path "$json_config")
|
|
902
|
+
EOF
|
|
903
|
+
chmod 644 "$readme" 2>/dev/null || true
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
_create_cc_connect_matrix_session() {
|
|
907
|
+
local asurl=$1 access_token=$2 device_id=$3 out=$4 body code http_body
|
|
908
|
+
body=$(jq -n --arg device_id "$device_id" '{action:"agent.matrix_session.create",params:{device_id:$device_id}}')
|
|
909
|
+
http_body=$(mktemp)
|
|
910
|
+
code=$(curl -sk -o "$http_body" -w '%{http_code}' -X POST "$asurl/_p2p/command" \
|
|
911
|
+
-H 'Content-Type: application/json' \
|
|
912
|
+
-H "Authorization: Bearer $access_token" \
|
|
913
|
+
-d "$body" 2>/dev/null || true)
|
|
914
|
+
if [ "$code" != "200" ]; then
|
|
915
|
+
warn "agent.matrix_session.create returned HTTP ${code:-000}: $(head -c 200 "$http_body" 2>/dev/null)"
|
|
916
|
+
rm -f "$http_body"
|
|
917
|
+
return 1
|
|
918
|
+
fi
|
|
919
|
+
if ! jq -e '.access_token and .device_id and .user_id and .homeserver' "$http_body" >/dev/null; then
|
|
920
|
+
warn "agent.matrix_session.create response is missing Matrix session fields: $(head -c 200 "$http_body" 2>/dev/null)"
|
|
921
|
+
rm -f "$http_body"
|
|
922
|
+
return 1
|
|
923
|
+
fi
|
|
924
|
+
mv "$http_body" "$out"
|
|
925
|
+
chmod 600 "$out" 2>/dev/null || true
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
_write_cc_connect_config() {
|
|
929
|
+
local config_path=$1 data_dir=$2 project=$3 agent=$4 workspace=$5 homeserver=$6 matrix_token=$7 matrix_user=$8 room_id=$9 admin_from=${10:-} agent_cmd=${11:-} agent_options_toml=${12:-}
|
|
930
|
+
local q_data q_project q_agent q_workspace q_homeserver q_token q_user q_room q_admin_from q_agent_cmd speech_toml default_agent_options_toml
|
|
931
|
+
mkdir -p "$(dirname "$config_path")" "$data_dir"
|
|
932
|
+
q_data=$(_toml_escape "$data_dir")
|
|
933
|
+
q_project=$(_toml_escape "$project")
|
|
934
|
+
q_agent=$(_toml_escape "$agent")
|
|
935
|
+
q_workspace=$(_toml_escape "$workspace")
|
|
936
|
+
q_homeserver=$(_toml_escape "$homeserver")
|
|
937
|
+
q_token=$(_toml_escape "$matrix_token")
|
|
938
|
+
q_user=$(_toml_escape "$matrix_user")
|
|
939
|
+
q_room=$(_toml_escape "$room_id")
|
|
940
|
+
q_admin_from=$(_toml_escape "$admin_from")
|
|
941
|
+
q_agent_cmd=$(_toml_escape "$agent_cmd")
|
|
942
|
+
speech_toml=$(_cc_connect_speech_config_toml)
|
|
943
|
+
default_agent_options_toml=$(_cc_connect_default_agent_options_toml "$agent" "$agent_options_toml")
|
|
944
|
+
umask 077
|
|
945
|
+
cat > "$config_path" <<EOF
|
|
946
|
+
language = "zh"
|
|
947
|
+
data_dir = "$q_data"
|
|
948
|
+
EOF
|
|
949
|
+
if [ -n "$speech_toml" ]; then
|
|
950
|
+
printf '\n%s\n' "$speech_toml" >> "$config_path"
|
|
951
|
+
fi
|
|
952
|
+
cat >> "$config_path" <<EOF
|
|
953
|
+
|
|
954
|
+
[[projects]]
|
|
955
|
+
name = "$q_project"
|
|
956
|
+
admin_from = "$q_admin_from"
|
|
957
|
+
|
|
958
|
+
[projects.agent]
|
|
959
|
+
type = "$q_agent"
|
|
960
|
+
|
|
961
|
+
[projects.agent.options]
|
|
962
|
+
work_dir = "$q_workspace"
|
|
963
|
+
EOF
|
|
964
|
+
if [ -n "$agent_cmd" ]; then
|
|
965
|
+
cat >> "$config_path" <<EOF
|
|
966
|
+
cmd = "$q_agent_cmd"
|
|
967
|
+
EOF
|
|
968
|
+
fi
|
|
969
|
+
if [ -n "$default_agent_options_toml" ]; then
|
|
970
|
+
printf '%s\n' "$default_agent_options_toml" >> "$config_path"
|
|
971
|
+
fi
|
|
972
|
+
if [ -n "$agent_options_toml" ]; then
|
|
973
|
+
printf '%s\n' "$agent_options_toml" >> "$config_path"
|
|
974
|
+
fi
|
|
975
|
+
cat >> "$config_path" <<EOF
|
|
976
|
+
|
|
977
|
+
[[projects.platforms]]
|
|
978
|
+
type = "matrix"
|
|
979
|
+
|
|
980
|
+
[projects.platforms.options]
|
|
981
|
+
homeserver = "$q_homeserver"
|
|
982
|
+
access_token = "$q_token"
|
|
983
|
+
user_id = "$q_user"
|
|
984
|
+
room_id = "$q_room"
|
|
985
|
+
share_session_in_channel = true
|
|
986
|
+
group_reply_all = true
|
|
987
|
+
auto_join = false
|
|
988
|
+
auto_verify = false
|
|
989
|
+
EOF
|
|
990
|
+
chmod 600 "$config_path"
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
_cc_connect_install_command() {
|
|
994
|
+
local binary=$1 config=$2 service_name=$3
|
|
995
|
+
[ -n "$service_name" ] || service_name=cc-connect
|
|
996
|
+
printf 'npm install -g %q && %q daemon install --config %q --service-name %q --force' "$(_cc_connect_npm_package)" "$binary" "$(_local_connect_path "$config")" "$service_name"
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
_cc_connect_daemon_is_running() {
|
|
1000
|
+
local binary=$1 service_name=$2 status
|
|
1001
|
+
[ -n "$service_name" ] || service_name=cc-connect
|
|
1002
|
+
status=$("$binary" daemon status --service-name "$service_name" 2>/dev/null || true)
|
|
1003
|
+
printf '%s\n' "$status" | grep -Eq 'Status:[[:space:]]*Running'
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
_cc_connect_daemon_has_agent_startup_error() {
|
|
1007
|
+
local binary=$1 service_name=$2 logs
|
|
1008
|
+
[ -n "$service_name" ] || service_name=cc-connect
|
|
1009
|
+
logs=$("$binary" daemon logs --service-name "$service_name" -n "${DIREXIO_CONNECT_LOG_TAIL_LINES:-120}" 2>/dev/null || true)
|
|
1010
|
+
printf '%s\n' "$logs" | grep -Eiq 'ACP_SESSION_INIT_FAILED|ACP metadata is missing|Recreate this ACP session'
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
_maybe_auto_install_cc_connect() {
|
|
1014
|
+
local policy=$1 runtime=$2 cc_agent=$3 service_dir=$4 config_path=$5 binary=$6 service_name=$7
|
|
1015
|
+
local repo ref src commit config_arg
|
|
1016
|
+
[ -n "$service_name" ] || service_name=$(basename "$service_dir")
|
|
1017
|
+
if [ "$policy" != "auto" ]; then
|
|
1018
|
+
state_set agent_install_status "$policy" 2>/dev/null || true
|
|
1019
|
+
return 0
|
|
1020
|
+
fi
|
|
1021
|
+
config_arg=$(_local_connect_path "$config_path")
|
|
1022
|
+
if [ "${DIREXIO_CC_CONNECT_INSTALL_FROM:-npm}" != "source" ]; then
|
|
1023
|
+
if ! command -v npm >/dev/null 2>&1; then
|
|
1024
|
+
warn "DIREXIO_AGENT_INSTALL=auto requested, but npm is not on PATH. Install Node.js or set DIREXIO_CC_CONNECT_INSTALL_FROM=source."
|
|
1025
|
+
state_set agent_install_status "npm_missing" 2>/dev/null || true
|
|
1026
|
+
return 0
|
|
1027
|
+
fi
|
|
1028
|
+
if npm install -g "$(_cc_connect_npm_package)" && "$binary" daemon install --config "$config_arg" --service-name "$service_name" --force; then
|
|
1029
|
+
if ! _cc_connect_daemon_is_running "$binary" "$service_name"; then
|
|
1030
|
+
state_set agent_install_status "install_failed" 2>/dev/null || true
|
|
1031
|
+
warn "cc-connect daemon install returned success, but daemon status is not Running. Check the local agent command and cc-connect logs."
|
|
1032
|
+
return 0
|
|
1033
|
+
fi
|
|
1034
|
+
if _cc_connect_daemon_has_agent_startup_error "$binary" "$service_name"; then
|
|
1035
|
+
state_set agent_install_status "install_failed" 2>/dev/null || true
|
|
1036
|
+
warn "cc-connect daemon is Running, but logs show ACP session initialization failed. Check OpenClaw ACP URL, token-file, and session."
|
|
1037
|
+
return 0
|
|
1038
|
+
fi
|
|
1039
|
+
state_set agent_install_status "installed" 2>/dev/null || true
|
|
1040
|
+
ok "cc-connect daemon installed from npm for $runtime using Matrix room bridge."
|
|
1041
|
+
else
|
|
1042
|
+
state_set agent_install_status "install_failed" 2>/dev/null || true
|
|
1043
|
+
warn "cc-connect npm install or daemon install failed. Config is available for manual start."
|
|
1044
|
+
fi
|
|
1045
|
+
return 0
|
|
1046
|
+
fi
|
|
1047
|
+
|
|
1048
|
+
repo=$(_cc_connect_repo)
|
|
1049
|
+
ref=$(_cc_connect_ref)
|
|
1050
|
+
src=$(_cc_connect_source_dir "$service_dir")
|
|
1051
|
+
if ! command -v git >/dev/null 2>&1 || ! command -v go >/dev/null 2>&1 || ! command -v make >/dev/null 2>&1; then
|
|
1052
|
+
warn "DIREXIO_CC_CONNECT_INSTALL_FROM=source requested, but git, go, and make are required to build cc-connect from source."
|
|
1053
|
+
state_set agent_install_status "build_tool_missing" 2>/dev/null || true
|
|
1054
|
+
return 0
|
|
1055
|
+
fi
|
|
1056
|
+
if [ ! -d "$src/.git" ]; then
|
|
1057
|
+
mkdir -p "$(dirname "$src")"
|
|
1058
|
+
if ! git clone "$repo" "$src"; then
|
|
1059
|
+
state_set agent_install_status "clone_failed" 2>/dev/null || true
|
|
1060
|
+
warn "cc-connect clone failed from $repo"
|
|
1061
|
+
return 0
|
|
1062
|
+
fi
|
|
1063
|
+
fi
|
|
1064
|
+
if ! git -C "$src" fetch --all --tags --prune; then
|
|
1065
|
+
state_set agent_install_status "fetch_failed" 2>/dev/null || true
|
|
1066
|
+
warn "cc-connect fetch failed in $src"
|
|
1067
|
+
return 0
|
|
1068
|
+
fi
|
|
1069
|
+
if ! git -C "$src" checkout "$ref"; then
|
|
1070
|
+
state_set agent_install_status "checkout_failed" 2>/dev/null || true
|
|
1071
|
+
warn "cc-connect checkout failed for ref $ref"
|
|
1072
|
+
return 0
|
|
1073
|
+
fi
|
|
1074
|
+
commit=$(git -C "$src" rev-parse --short HEAD 2>/dev/null || true)
|
|
1075
|
+
state_set cc_connect_commit "$commit" 2>/dev/null || true
|
|
1076
|
+
if ! (cd "$src" && AGENTS="$cc_agent" PLATFORMS_INCLUDE=matrix NO_WEB=1 make build-noweb); then
|
|
1077
|
+
state_set agent_install_status "build_failed" 2>/dev/null || true
|
|
1078
|
+
warn "cc-connect build failed for runtime=$runtime agent=$cc_agent"
|
|
1079
|
+
return 0
|
|
1080
|
+
fi
|
|
1081
|
+
binary="$(_cc_connect_runtime_dir "$service_dir")/bin/direxio-connect"
|
|
1082
|
+
mkdir -p "$(dirname "$binary")"
|
|
1083
|
+
if ! cp "$src/direxio-connect" "$binary" 2>/dev/null && ! cp "$src/direxio-connect.exe" "$binary" 2>/dev/null; then
|
|
1084
|
+
state_set agent_install_status "binary_copy_failed" 2>/dev/null || true
|
|
1085
|
+
warn "direxio-connect binary was not found after build in $src"
|
|
1086
|
+
return 0
|
|
1087
|
+
fi
|
|
1088
|
+
chmod 700 "$binary" 2>/dev/null || true
|
|
1089
|
+
if "$binary" daemon install --config "$config_arg" --service-name "$service_name" --force; then
|
|
1090
|
+
if ! _cc_connect_daemon_is_running "$binary" "$service_name"; then
|
|
1091
|
+
state_set agent_install_status "install_failed" 2>/dev/null || true
|
|
1092
|
+
warn "cc-connect daemon install returned success, but daemon status is not Running. Check the local agent command and cc-connect logs."
|
|
1093
|
+
return 0
|
|
1094
|
+
fi
|
|
1095
|
+
if _cc_connect_daemon_has_agent_startup_error "$binary" "$service_name"; then
|
|
1096
|
+
state_set agent_install_status "install_failed" 2>/dev/null || true
|
|
1097
|
+
warn "cc-connect daemon is Running, but logs show ACP session initialization failed. Check OpenClaw ACP URL, token-file, and session."
|
|
1098
|
+
return 0
|
|
1099
|
+
fi
|
|
1100
|
+
state_set agent_install_status "installed" 2>/dev/null || true
|
|
1101
|
+
ok "cc-connect daemon installed for $runtime using Matrix room bridge."
|
|
1102
|
+
else
|
|
1103
|
+
state_set agent_install_status "install_failed" 2>/dev/null || true
|
|
1104
|
+
warn "cc-connect daemon install failed. Config and binary are available for manual start."
|
|
1105
|
+
fi
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
_agent_skill_install_path() {
|
|
1109
|
+
local runtime=$1
|
|
1110
|
+
case "$runtime" in
|
|
1111
|
+
acp) printf 'PROJECT_ROOT/.agents/skills/direxio-deployer\n' ;;
|
|
1112
|
+
antigravity) printf 'PROJECT_ROOT/.antigravity/skills/direxio-deployer\n' ;;
|
|
1113
|
+
codex) printf 'PROJECT_ROOT/.codex/skills/direxio-deployer\n' ;;
|
|
1114
|
+
claude|claude-code|claudecode) printf 'PROJECT_ROOT/.claude/skills/direxio-deployer\n' ;;
|
|
1115
|
+
devin) printf 'PROJECT_ROOT/.devin/skills/direxio-deployer\n' ;;
|
|
1116
|
+
iflow) printf 'PROJECT_ROOT/.iflow/skills/direxio-deployer\n' ;;
|
|
1117
|
+
kimi) printf 'PROJECT_ROOT/.kimi/skills/direxio-deployer\n' ;;
|
|
1118
|
+
opencode) printf 'PROJECT_ROOT/.opencode/skills/direxio-deployer\n' ;;
|
|
1119
|
+
pi) printf 'PROJECT_ROOT/.pi/agent/skills/direxio-deployer\n' ;;
|
|
1120
|
+
qoder) printf 'PROJECT_ROOT/.qoder/skills/direxio-deployer\n' ;;
|
|
1121
|
+
reasonix) printf 'PROJECT_ROOT/.reasonix/skills/direxio-deployer\n' ;;
|
|
1122
|
+
tmux) printf 'PROJECT_ROOT/.agent/skills/direxio-deployer\n' ;;
|
|
1123
|
+
gemini) printf 'PROJECT_ROOT/.gemini/skills/direxio-deployer\n' ;;
|
|
1124
|
+
cursor) printf 'PROJECT_ROOT/.cursor/skills/direxio-deployer\n' ;;
|
|
1125
|
+
copilot) printf 'PROJECT_ROOT/.github/copilot/skills/direxio-deployer\n' ;;
|
|
1126
|
+
openclaw) printf 'PROJECT_ROOT/.openclaw/skills/direxio-deployer\n' ;;
|
|
1127
|
+
hermes) printf 'PROJECT_ROOT/.hermes/skills/direxio-deployer\n' ;;
|
|
1128
|
+
generic|unknown|*) printf 'PROJECT_ROOT/.agent/skills/direxio-deployer\n' ;;
|
|
1129
|
+
esac
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
_agent_global_skill_install_path() {
|
|
1133
|
+
local runtime=$1
|
|
1134
|
+
case "$runtime" in
|
|
1135
|
+
acp) printf '$HOME/.agents/skills/direxio-deployer\n' ;;
|
|
1136
|
+
antigravity) printf '${ANTIGRAVITY_HOME:-$HOME/.antigravity}/skills/direxio-deployer\n' ;;
|
|
1137
|
+
codex) printf '${CODEX_HOME:-$HOME/.codex}/skills/direxio-deployer\n' ;;
|
|
1138
|
+
claude|claude-code|claudecode) printf '${CLAUDE_HOME:-${CLAUDECODE_HOME:-$HOME/.claude}}/skills/direxio-deployer\n' ;;
|
|
1139
|
+
devin) printf '${DEVIN_HOME:-$HOME/.devin}/skills/direxio-deployer\n' ;;
|
|
1140
|
+
iflow) printf '${IFLOW_HOME:-$HOME/.iflow}/skills/direxio-deployer\n' ;;
|
|
1141
|
+
kimi) printf '${KIMI_HOME:-$HOME/.kimi}/skills/direxio-deployer\n' ;;
|
|
1142
|
+
opencode) printf '${OPENCODE_HOME:-$HOME/.opencode}/skills/direxio-deployer\n' ;;
|
|
1143
|
+
pi) printf '${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}/skills/direxio-deployer\n' ;;
|
|
1144
|
+
qoder) printf '${QODER_HOME:-$HOME/.qoder}/skills/direxio-deployer\n' ;;
|
|
1145
|
+
reasonix) printf '${REASONIX_HOME:-$HOME/.reasonix}/skills/direxio-deployer\n' ;;
|
|
1146
|
+
tmux) printf '$HOME/.agent/skills/direxio-deployer\n' ;;
|
|
1147
|
+
gemini) printf '${GEMINI_HOME:-$HOME/.gemini}/skills/direxio-deployer\n' ;;
|
|
1148
|
+
cursor) printf '${CURSOR_HOME:-$HOME/.cursor}/skills/direxio-deployer\n' ;;
|
|
1149
|
+
copilot) printf '$HOME/.github/copilot/skills/direxio-deployer\n' ;;
|
|
1150
|
+
openclaw) printf '${OPENCLAW_HOME:-$HOME/.openclaw}/skills/direxio-deployer\n' ;;
|
|
1151
|
+
hermes) printf '${HERMES_HOME:-$HOME/.hermes}/skills/direxio-deployer\n' ;;
|
|
1152
|
+
generic|unknown|*) printf '$HOME/.agent/skills/direxio-deployer\n' ;;
|
|
1153
|
+
esac
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
_agent_install_command() {
|
|
1157
|
+
local binary=$1 config=$2 service_name=$3
|
|
1158
|
+
_cc_connect_install_command "$binary" "$config" "$service_name"
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
_print_runtime_install_summary() {
|
|
1162
|
+
local runtime=$1 mode=$2 config_path=$3 binary=$4 cc_agent=$5 cc_agent_cmd=${6:-} service_name=${7:-}
|
|
1163
|
+
cat >&2 <<EOF
|
|
1164
|
+
Recommended cc-connect install:
|
|
1165
|
+
runtime: $runtime
|
|
1166
|
+
cc-connect agent: $cc_agent
|
|
1167
|
+
agent command: ${cc_agent_cmd:-default PATH lookup}
|
|
1168
|
+
mode: $mode
|
|
1169
|
+
service name: $service_name
|
|
1170
|
+
config: $config_path
|
|
1171
|
+
binary: $binary
|
|
1172
|
+
daemon install: $(_cc_connect_install_command "$binary" "$config_path" "$service_name")
|
|
1173
|
+
EOF
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
_maybe_auto_install_agent() {
|
|
1177
|
+
_maybe_auto_install_cc_connect "$@"
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
_write_agent_env_file() {
|
|
1181
|
+
local asurl=$1 token=$2 access_token=$3 agent_room_id=$4 envfile=${5:-"$(_direxio_home)/env"} node_id=${6:-}
|
|
1182
|
+
mkdir -p "$(dirname "$envfile")"
|
|
1183
|
+
umask 077
|
|
1184
|
+
{
|
|
1185
|
+
[ -n "$node_id" ] && printf 'export DIREXIO_AGENT_NODE_ID=%q\n' "$node_id"
|
|
1186
|
+
printf 'export DIREXIO_DOMAIN=%q\n' "$asurl"
|
|
1187
|
+
printf 'export DIREXIO_AGENT_TOKEN=%q\n' "$token"
|
|
1188
|
+
printf 'export DIREXIO_AGENT_ROOM_ID=%q\n' "$agent_room_id"
|
|
1189
|
+
} > "$envfile"
|
|
1190
|
+
chmod 600 "$envfile"
|
|
1191
|
+
echo "$envfile"
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
_agent_node_id() {
|
|
1195
|
+
local runtime=$1 domain=$2 room=$3 explicit host digest raw
|
|
1196
|
+
explicit=${DIREXIO_AGENT_NODE_ID:-}
|
|
1197
|
+
host=${domain#http://}
|
|
1198
|
+
host=${host#https://}
|
|
1199
|
+
host=${host%%/*}
|
|
1200
|
+
host=${host%%:*}
|
|
1201
|
+
if [ -n "$explicit" ] && { [ "${DIREXIO_AGENT_NODE_ID_FORCE:-}" = "1" ] || _agent_node_id_matches_host "$explicit" "$host"; }; then
|
|
1202
|
+
raw=$explicit
|
|
1203
|
+
else
|
|
1204
|
+
if command -v sha256sum >/dev/null 2>&1; then
|
|
1205
|
+
digest=$(printf '%s\n%s\n' "$domain" "$room" | sha256sum | awk '{print substr($1,1,10)}')
|
|
1206
|
+
else
|
|
1207
|
+
digest=$(printf '%s\n%s\n' "$domain" "$room" | shasum -a 256 | awk '{print substr($1,1,10)}')
|
|
1208
|
+
fi
|
|
1209
|
+
raw="${runtime:-agent}-${host:-direxio}-$digest"
|
|
1210
|
+
fi
|
|
1211
|
+
printf '%s\n' "$raw" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9._-]+/-/g; s/^-+//; s/-+$//; s/^$/direxio-agent/'
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
_agent_node_id_matches_host() {
|
|
1215
|
+
local node_id=$1 host=$2 normalized_node normalized_host
|
|
1216
|
+
normalized_node=$(printf '%s\n' "$node_id" | tr '[:upper:]' '[:lower:]')
|
|
1217
|
+
normalized_host=$(printf '%s\n' "$host" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9._-]+/-/g; s/^-+//; s/-+$//')
|
|
1218
|
+
[ -n "$normalized_host" ] && [[ "$normalized_node" == *"$normalized_host"* ]]
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
_write_credentials_file() {
|
|
1222
|
+
local cred=$1 domain=$2 asurl=$3 token=$4 password=$5 access_token=$6 agent_room_id=$7 node_id=$8
|
|
1223
|
+
mkdir -p "$(dirname "$cred")"
|
|
1224
|
+
jq -n --arg domain "$domain" --arg url "$asurl" --arg tok "$token" --arg password "$password" --arg access "$access_token" --arg room "$agent_room_id" --arg node_id "$node_id" \
|
|
1225
|
+
'{profiles:{default:{domain:$domain,password:$password,access_token:$access,agent_room_id:$room,direxio_domain:$url,direxio_agent_token:$tok,direxio_agent_room_id:$room,direxio_agent_node_id:$node_id}}}' > "$cred"
|
|
1226
|
+
chmod 600 "$cred"
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
_persist_agent_env() {
|
|
1230
|
+
local asurl=$1 token=$2 access_token=$3 agent_room_id=$4 envfile=${5:-"$(_direxio_home)/env"} node_id=${6:-}
|
|
1231
|
+
envfile=$(_write_agent_env_file "$asurl" "$token" "$access_token" "$agent_room_id" "$envfile" "$node_id")
|
|
1232
|
+
[ -n "$node_id" ] && export DIREXIO_AGENT_NODE_ID="$node_id"
|
|
1233
|
+
export DIREXIO_DOMAIN="$asurl"
|
|
1234
|
+
export DIREXIO_AGENT_TOKEN="$token"
|
|
1235
|
+
export DIREXIO_AGENT_ROOM_ID="$agent_room_id"
|
|
1236
|
+
ok "Persisted Direxio cc-connect env vars via $envfile."
|
|
1237
|
+
echo "$envfile"
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
_print_cc_connect_guidance() {
|
|
1241
|
+
local runtime=$1 asurl=$2 cred=$3 envfile=$4 policy=$5 mode=$6 install_command=$7 node_id=$8 cc_config=$9 cc_binary=${10} cc_agent=${11} cc_agent_cmd=${12:-} service_name=${13:-}
|
|
1242
|
+
local skill_path global_skill_path
|
|
1243
|
+
skill_path=$(_agent_skill_install_path "$runtime")
|
|
1244
|
+
global_skill_path=$(_agent_global_skill_install_path "$runtime")
|
|
1245
|
+
if [ "$policy" = "skip" ]; then
|
|
1246
|
+
warn "Direxio cc-connect install guidance skipped by DIREXIO_AGENT_INSTALL=skip."
|
|
1247
|
+
return 0
|
|
1248
|
+
fi
|
|
1249
|
+
warn "Direxio cc-connect install policy: $policy; platform=$runtime; mode=$mode."
|
|
1250
|
+
cat >&2 <<EOF
|
|
1251
|
+
Detected agent runtime: $runtime
|
|
1252
|
+
cc-connect agent: $cc_agent
|
|
1253
|
+
Local env file: $envfile
|
|
1254
|
+
Credential file: $cred
|
|
1255
|
+
cc-connect config: $cc_config
|
|
1256
|
+
cc-connect binary: $cc_binary
|
|
1257
|
+
cc-connect agent cmd: ${cc_agent_cmd:-default PATH lookup}
|
|
1258
|
+
cc-connect service: $service_name
|
|
1259
|
+
Install command: $install_command
|
|
1260
|
+
Project skill clone: $skill_path
|
|
1261
|
+
Global skill fallback: $global_skill_path
|
|
1262
|
+
Env keys: DIREXIO_DOMAIN, DIREXIO_AGENT_TOKEN, DIREXIO_AGENT_ROOM_ID, DIREXIO_AGENT_NODE_ID
|
|
1263
|
+
|
|
1264
|
+
cc-connect will use Matrix Client-Server sync as @agent:<server> and is restricted to DIREXIO_AGENT_ROOM_ID.
|
|
1265
|
+
It talks directly to the Direxio homeserver for the agents room conversation.
|
|
1266
|
+
EOF
|
|
1267
|
+
_print_runtime_install_summary "$runtime" "$mode" "$cc_config" "$cc_binary" "$cc_agent" "$cc_agent_cmd" "$service_name"
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
_print_mcp_guidance() {
|
|
1271
|
+
local runtime=$1 service_name=$2 server_name=$3 credentials_file=$4 config_dir=$5 codex_config=$6 openclaw_config=$7 hermes_config=$8 install_command=$9 doctor_command=${10}
|
|
1272
|
+
warn "Direxio MCP artifacts written for runtime=$runtime service=$service_name."
|
|
1273
|
+
cat >&2 <<EOF
|
|
1274
|
+
MCP server name: $server_name
|
|
1275
|
+
MCP config directory: $config_dir
|
|
1276
|
+
MCP credential file: $credentials_file
|
|
1277
|
+
MCP install command: $install_command
|
|
1278
|
+
MCP doctor command: $doctor_command
|
|
1279
|
+
Codex TOML snippet: $codex_config
|
|
1280
|
+
OpenClaw CLI setup: $openclaw_config
|
|
1281
|
+
Hermes JSON snippet: $hermes_config
|
|
1282
|
+
|
|
1283
|
+
These artifacts use direxio-mcp over stdio and point to the service-scoped DIREXIO_CREDENTIALS_FILE.
|
|
1284
|
+
For OpenClaw, use the CLI setup note so OpenClaw validates and writes mcp.servers itself; do not paste MCP JSON into openclaw.json.
|
|
1285
|
+
EOF
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
run_phase() {
|
|
1289
|
+
phase_set S6_WIRE_LOCAL in_progress "writing credentials and cc-connect Matrix bridge config"
|
|
1290
|
+
local domain asurl token access_token password agent_room_id envfile runtime install_policy install_mode install_command
|
|
1291
|
+
local node_id service_dir node_cred workspace workspace_local service_id cc_agent cc_agent_cmd cc_agent_options_toml cc_runtime_dir cc_config cc_config_local cc_data cc_data_local cc_binary cc_session cc_source
|
|
1292
|
+
local mcp_dir mcp_dir_local mcp_server_name mcp_install_command mcp_doctor_command mcp_codex_config mcp_openclaw_config mcp_hermes_config mcp_json_config mcp_env_file mcp_readme
|
|
1293
|
+
local mcp_codex_config_local mcp_openclaw_config_local mcp_hermes_config_local mcp_json_config_local mcp_env_file_local mcp_readme_local node_cred_local
|
|
1294
|
+
local matrix_token matrix_user matrix_device matrix_homeserver
|
|
1295
|
+
local skill_path global_skill_path
|
|
1296
|
+
domain=$(state_get domain)
|
|
1297
|
+
asurl=$(state_get as_url)
|
|
1298
|
+
token=$(state_get agent_token)
|
|
1299
|
+
access_token=$(state_get access_token)
|
|
1300
|
+
password=$(state_get password)
|
|
1301
|
+
agent_room_id=$(state_get agent_room_id)
|
|
1302
|
+
[ -n "$domain" ] && [ -n "$asurl" ] && [ -n "$token" ] || { phase_set S6_WIRE_LOCAL failed "missing domain/as_url/token"; fail "state is missing domain/as_url/agent_token; complete S5 first."; }
|
|
1303
|
+
[ -n "$access_token" ] && [ -n "$password" ] || { phase_set S6_WIRE_LOCAL failed "missing bootstrap credentials"; fail "state is missing password/access_token; complete S5 first."; }
|
|
1304
|
+
_validate_real_agent_room_id "$agent_room_id"
|
|
1305
|
+
|
|
1306
|
+
runtime=$(_detect_agent_runtime)
|
|
1307
|
+
cc_agent=$(_cc_connect_agent_type "$runtime")
|
|
1308
|
+
cc_agent_cmd=$(_cc_connect_agent_command "$cc_agent" "$runtime")
|
|
1309
|
+
cc_agent_options_toml=$(_cc_connect_agent_options_toml "$runtime" "$cc_agent")
|
|
1310
|
+
node_id=$(_agent_node_id "$runtime" "$domain" "$agent_room_id")
|
|
1311
|
+
service_id=$(_direxio_service_id "${asurl:-$domain}")
|
|
1312
|
+
service_dir=$(_direxio_service_dir "${asurl:-$domain}")
|
|
1313
|
+
node_cred="$service_dir/credentials.json"
|
|
1314
|
+
envfile="$service_dir/env"
|
|
1315
|
+
workspace=$(_agent_workspace "$service_dir")
|
|
1316
|
+
admin_from="@owner:$domain"
|
|
1317
|
+
cc_runtime_dir=$(_cc_connect_runtime_dir "$service_dir")
|
|
1318
|
+
cc_config=$(_cc_connect_config_path "$service_dir")
|
|
1319
|
+
cc_config_local=$(_local_connect_path "$cc_config")
|
|
1320
|
+
cc_data="$cc_runtime_dir/data"
|
|
1321
|
+
cc_data_local=$(_local_connect_path "$cc_data")
|
|
1322
|
+
cc_binary=$(_cc_connect_binary_path "$service_dir")
|
|
1323
|
+
cc_session="$cc_runtime_dir/matrix-session.json"
|
|
1324
|
+
cc_source=$(_cc_connect_source_dir "$service_dir")
|
|
1325
|
+
|
|
1326
|
+
_write_credentials_file "$node_cred" "$domain" "$asurl" "$token" "$password" "$access_token" "$agent_room_id" "$node_id"
|
|
1327
|
+
ok "Wrote $node_cred (0600)."
|
|
1328
|
+
node_cred_local=$(_local_connect_path "$node_cred")
|
|
1329
|
+
|
|
1330
|
+
_write_mcp_config_artifacts "$service_id" "$service_dir" "$node_cred" "$node_id"
|
|
1331
|
+
mcp_dir=$(_mcp_runtime_dir "$service_dir")
|
|
1332
|
+
mcp_dir_local=$(_local_connect_path "$mcp_dir")
|
|
1333
|
+
mcp_server_name=$(_mcp_server_name "$service_id")
|
|
1334
|
+
mcp_codex_config=$(_mcp_codex_config_path "$service_dir")
|
|
1335
|
+
mcp_openclaw_config=$(_mcp_openclaw_config_path "$service_dir")
|
|
1336
|
+
mcp_hermes_config=$(_mcp_hermes_config_path "$service_dir")
|
|
1337
|
+
mcp_json_config=$(_mcp_json_config_path "$service_dir")
|
|
1338
|
+
mcp_env_file=$(_mcp_env_file_path "$service_dir")
|
|
1339
|
+
mcp_readme=$(_mcp_readme_path "$service_dir")
|
|
1340
|
+
mcp_codex_config_local=$(_local_connect_path "$mcp_codex_config")
|
|
1341
|
+
mcp_openclaw_config_local=$(_local_connect_path "$mcp_openclaw_config")
|
|
1342
|
+
mcp_hermes_config_local=$(_local_connect_path "$mcp_hermes_config")
|
|
1343
|
+
mcp_json_config_local=$(_local_connect_path "$mcp_json_config")
|
|
1344
|
+
mcp_env_file_local=$(_local_connect_path "$mcp_env_file")
|
|
1345
|
+
mcp_readme_local=$(_local_connect_path "$mcp_readme")
|
|
1346
|
+
mcp_install_command=$(_mcp_install_command)
|
|
1347
|
+
mcp_doctor_command=$(_mcp_doctor_command "$node_cred" "$node_id")
|
|
1348
|
+
ok "Wrote MCP config snippets under $mcp_dir."
|
|
1349
|
+
|
|
1350
|
+
if ! envfile=$(_persist_agent_env "$asurl" "$token" "$access_token" "$agent_room_id" "$envfile" "$node_id"); then
|
|
1351
|
+
phase_set S6_WIRE_LOCAL failed "persistent env write failed"
|
|
1352
|
+
fail "failed to persist Direxio cc-connect env vars."
|
|
1353
|
+
fi
|
|
1354
|
+
|
|
1355
|
+
mkdir -p "$workspace"
|
|
1356
|
+
mkdir -p "$cc_runtime_dir"
|
|
1357
|
+
if ! _create_cc_connect_matrix_session "$asurl" "$access_token" "DIREXIO_CC_CONNECT_${node_id}" "$cc_session"; then
|
|
1358
|
+
phase_set S6_WIRE_LOCAL failed "agent Matrix session creation failed"
|
|
1359
|
+
fail "failed to create cc-connect Matrix session via agent.matrix_session.create."
|
|
1360
|
+
fi
|
|
1361
|
+
matrix_token=$(jq -r '.access_token' "$cc_session")
|
|
1362
|
+
matrix_user=$(jq -r '.user_id' "$cc_session")
|
|
1363
|
+
matrix_device=$(jq -r '.device_id' "$cc_session")
|
|
1364
|
+
matrix_homeserver=$(jq -r '.homeserver' "$cc_session")
|
|
1365
|
+
if [ "$matrix_user" = "@owner:$domain" ]; then
|
|
1366
|
+
phase_set S6_WIRE_LOCAL failed "agent Matrix session returned owner user"
|
|
1367
|
+
fail "agent.matrix_session.create returned owner Matrix user; deploy a message-server build with agent Matrix session support."
|
|
1368
|
+
fi
|
|
1369
|
+
case "$matrix_user" in
|
|
1370
|
+
@agent:*) ;;
|
|
1371
|
+
*) warn "agent.matrix_session.create returned non-standard agent user_id: $matrix_user" ;;
|
|
1372
|
+
esac
|
|
1373
|
+
workspace_local=$(_local_connect_path "$workspace")
|
|
1374
|
+
_write_cc_connect_config "$cc_config" "$cc_data_local" "$node_id" "$cc_agent" "$workspace_local" "$matrix_homeserver" "$matrix_token" "$matrix_user" "$agent_room_id" "$admin_from" "$cc_agent_cmd" "$cc_agent_options_toml"
|
|
1375
|
+
ok "Wrote cc-connect Matrix config $cc_config (0600)."
|
|
1376
|
+
|
|
1377
|
+
state_set agent_env_file "$envfile" 2>/dev/null || true
|
|
1378
|
+
state_set agent_node_id "$node_id" 2>/dev/null || true
|
|
1379
|
+
state_set agent_service_id "$service_id" 2>/dev/null || true
|
|
1380
|
+
state_set agent_service_dir "$service_dir" 2>/dev/null || true
|
|
1381
|
+
state_set agent_credentials_file "$node_cred" 2>/dev/null || true
|
|
1382
|
+
state_set mcp_npm_package "$(_mcp_npm_package)" 2>/dev/null || true
|
|
1383
|
+
state_set mcp_command "$(_mcp_command)" 2>/dev/null || true
|
|
1384
|
+
state_set mcp_server_name "$mcp_server_name" 2>/dev/null || true
|
|
1385
|
+
state_set mcp_config_dir "$mcp_dir_local" 2>/dev/null || true
|
|
1386
|
+
state_set mcp_credentials_file "$node_cred_local" 2>/dev/null || true
|
|
1387
|
+
state_set mcp_codex_config "$mcp_codex_config_local" 2>/dev/null || true
|
|
1388
|
+
state_set mcp_openclaw_config "$mcp_openclaw_config_local" 2>/dev/null || true
|
|
1389
|
+
state_set mcp_hermes_config "$mcp_hermes_config_local" 2>/dev/null || true
|
|
1390
|
+
state_set mcp_json_config "$mcp_json_config_local" 2>/dev/null || true
|
|
1391
|
+
state_set mcp_env_file "$mcp_env_file_local" 2>/dev/null || true
|
|
1392
|
+
state_set mcp_readme "$mcp_readme_local" 2>/dev/null || true
|
|
1393
|
+
state_set mcp_install_command "$mcp_install_command" 2>/dev/null || true
|
|
1394
|
+
state_set mcp_doctor_command "$mcp_doctor_command" 2>/dev/null || true
|
|
1395
|
+
state_set agent_workspace "$workspace" 2>/dev/null || true
|
|
1396
|
+
state_set cc_connect_agent "$cc_agent" 2>/dev/null || true
|
|
1397
|
+
state_set cc_connect_agent_cmd "$cc_agent_cmd" 2>/dev/null || true
|
|
1398
|
+
if [ -n "$cc_agent_options_toml" ]; then
|
|
1399
|
+
state_set cc_connect_agent_options_toml_present "true" 2>/dev/null || true
|
|
1400
|
+
else
|
|
1401
|
+
state_set cc_connect_agent_options_toml_present "false" 2>/dev/null || true
|
|
1402
|
+
fi
|
|
1403
|
+
state_set cc_connect_npm_package "$(_cc_connect_npm_package)" 2>/dev/null || true
|
|
1404
|
+
state_set cc_connect_repo "$(_cc_connect_repo)" 2>/dev/null || true
|
|
1405
|
+
state_set cc_connect_ref "$(_cc_connect_ref)" 2>/dev/null || true
|
|
1406
|
+
state_set cc_connect_source_dir "$cc_source" 2>/dev/null || true
|
|
1407
|
+
state_set cc_connect_runtime_dir "$cc_runtime_dir" 2>/dev/null || true
|
|
1408
|
+
state_set cc_connect_config "$cc_config_local" 2>/dev/null || true
|
|
1409
|
+
state_set cc_connect_binary "$cc_binary" 2>/dev/null || true
|
|
1410
|
+
state_set cc_connect_data_dir "$cc_data_local" 2>/dev/null || true
|
|
1411
|
+
state_set cc_connect_admin_from "$admin_from" 2>/dev/null || true
|
|
1412
|
+
state_set cc_connect_matrix_session_file "$cc_session" 2>/dev/null || true
|
|
1413
|
+
state_set cc_connect_matrix_user "$matrix_user" 2>/dev/null || true
|
|
1414
|
+
state_set cc_connect_matrix_device "$matrix_device" 2>/dev/null || true
|
|
1415
|
+
state_set cc_connect_matrix_homeserver "$matrix_homeserver" 2>/dev/null || true
|
|
1416
|
+
|
|
1417
|
+
install_policy=$(_agent_install_policy)
|
|
1418
|
+
install_mode=$(_agent_install_mode "$runtime")
|
|
1419
|
+
install_command=$(_agent_install_command "$cc_binary" "$cc_config" "$service_id")
|
|
1420
|
+
skill_path=$(_agent_skill_install_path "$runtime")
|
|
1421
|
+
global_skill_path=$(_agent_global_skill_install_path "$runtime")
|
|
1422
|
+
state_set agent_runtime "$runtime" 2>/dev/null || true
|
|
1423
|
+
state_set agent_install_policy "$install_policy" 2>/dev/null || true
|
|
1424
|
+
state_set agent_install_mode "$install_mode" 2>/dev/null || true
|
|
1425
|
+
state_set agent_install_command "$install_command" 2>/dev/null || true
|
|
1426
|
+
state_set agent_skill_install_path "$skill_path" 2>/dev/null || true
|
|
1427
|
+
state_set agent_global_skill_install_path "$global_skill_path" 2>/dev/null || true
|
|
1428
|
+
state_set direxio_agent_bridge "cc-connect" 2>/dev/null || true
|
|
1429
|
+
_print_cc_connect_guidance "$runtime" "$asurl" "$node_cred" "$envfile" "$install_policy" "$install_mode" "$install_command" "$node_id" "$cc_config_local" "$cc_binary" "$cc_agent" "$cc_agent_cmd" "$service_id"
|
|
1430
|
+
_print_mcp_guidance "$runtime" "$service_id" "$mcp_server_name" "$node_cred_local" "$mcp_dir_local" "$mcp_codex_config_local" "$mcp_openclaw_config_local" "$mcp_hermes_config_local" "$mcp_install_command" "$mcp_doctor_command"
|
|
1431
|
+
_maybe_auto_install_agent "$install_policy" "$runtime" "$cc_agent" "$service_dir" "$cc_config" "$cc_binary" "$service_id"
|
|
1432
|
+
|
|
1433
|
+
phase_set S6_WIRE_LOCAL done "credentials.json written;node_id=$node_id;service_id=$service_id;env_file=$envfile;runtime=$runtime;install_policy=$install_policy;install_mode=$install_mode;cc_connect_config=$cc_config;mcp_config_dir=$mcp_dir;cc_connect_agent=$cc_agent"
|
|
1434
|
+
return 0
|
|
1435
|
+
}
|