openclaw-opencode-bridge 2.1.1 → 2.1.3
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
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
[](package.json)
|
|
6
6
|
|
|
7
|
-
>
|
|
7
|
+
> Liked this project? Consider donating!
|
|
8
|
+
|
|
9
|
+
> EVM Address: 0xe81c32383C8F21A14E6C2264939dA512e9F9bb42
|
|
8
10
|
|
|
9
11
|
Bridge [OpenClaw](https://openclaw.ai) messaging channels to [OpenCode](https://opencode.ai) via persistent tmux sessions.
|
|
10
12
|
|
|
@@ -98,6 +100,8 @@ Removes all installed components — plugin, shell scripts, OPENCODE.md addition
|
|
|
98
100
|
| Delivery confirmed but no reply | Check `tmux ls` — session may have crashed |
|
|
99
101
|
| Multiline sends only first line | Re-run `openclaw-opencode-bridge onboard` (v2.0.6+) |
|
|
100
102
|
|
|
103
|
+
> Forked from [openclaw-claude-bridge](https://github.com/bettep-dev/openclaw-claude-bridge) by [@bettep-dev](https://github.com/bettep-dev) — modified to work with OpenCode instead of Claude CLI.
|
|
104
|
+
|
|
101
105
|
## License
|
|
102
106
|
|
|
103
107
|
[MIT](LICENSE)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-opencode-bridge",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"description": "Bridge OpenClaw messaging channels to OpenCode via tmux persistent sessions",
|
|
5
5
|
"main": "./lib/onboard.js",
|
|
6
6
|
"bin": {
|
|
@@ -37,10 +37,10 @@
|
|
|
37
37
|
"name": "Febrian",
|
|
38
38
|
"email": "febro.aw20@gmail.com"
|
|
39
39
|
},
|
|
40
|
-
"homepage": "
|
|
40
|
+
"homepage": "http://febro.fun",
|
|
41
41
|
"license": "MIT",
|
|
42
42
|
"repository": {
|
|
43
43
|
"type": "git",
|
|
44
|
-
"url": "https://github.com/
|
|
44
|
+
"url": "https://github.com/AganFebro/openclaw-opencode-bridge"
|
|
45
45
|
}
|
|
46
46
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# bridge-version:
|
|
2
|
+
# bridge-version: 9
|
|
3
3
|
# Start fresh session asynchronously and send instruction
|
|
4
4
|
MSG="$1"
|
|
5
5
|
OPENCODE="{{OPENCODE_BIN}}"
|
|
@@ -9,6 +9,7 @@ WORKSPACE="{{WORKSPACE}}"
|
|
|
9
9
|
LOG_FILE="/tmp/opencode-bridge-send.log"
|
|
10
10
|
BASE_TIMEOUT_SEC=45
|
|
11
11
|
MAX_TIMEOUT_SEC=300
|
|
12
|
+
LOCK_WAIT_SEC=600
|
|
12
13
|
|
|
13
14
|
if [ -z "$MSG" ]; then
|
|
14
15
|
echo "ERROR: No message provided"
|
|
@@ -28,6 +29,21 @@ normalize_text() {
|
|
|
28
29
|
| sed -E 's/^🔗[[:space:]]*//; s/^["'\''`]+|["'\''`]+$//g; s/[[:space:]]+/ /g; s/^[[:space:]]+|[[:space:]]+$//g'
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
acquire_bridge_lock() {
|
|
33
|
+
local safe_channel safe_target lock_file
|
|
34
|
+
safe_channel="$(printf '%s' "$CHANNEL" | sed -E 's/[^a-zA-Z0-9._-]/_/g')"
|
|
35
|
+
safe_target="$(printf '%s' "$TARGET" | sed -E 's/[^a-zA-Z0-9._-]/_/g')"
|
|
36
|
+
lock_file="/tmp/opencode-bridge-${safe_channel}-${safe_target}.lock"
|
|
37
|
+
|
|
38
|
+
if command -v flock >/dev/null 2>&1; then
|
|
39
|
+
exec 200>"$lock_file"
|
|
40
|
+
flock -w "$LOCK_WAIT_SEC" 200
|
|
41
|
+
return $?
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
return 0
|
|
45
|
+
}
|
|
46
|
+
|
|
31
47
|
compute_timeout() {
|
|
32
48
|
local msg="$1"
|
|
33
49
|
local timeout="$BASE_TIMEOUT_SEC"
|
|
@@ -62,49 +78,100 @@ is_trivial_echo() {
|
|
|
62
78
|
[ -n "$message_norm" ] && [ "$output_norm" = "$message_norm" ]
|
|
63
79
|
}
|
|
64
80
|
|
|
65
|
-
|
|
81
|
+
has_external_delivery_success() {
|
|
66
82
|
local raw="$1"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
line="$(printf '%s\n' "$raw" | grep -E 'openclaw message send --channel' | tail -n 1)"
|
|
70
|
-
[ -z "$line" ] && return 0
|
|
83
|
+
printf '%s\n' "$raw" | grep -Eqi 'Sent via [A-Za-z]+|Message ID:[[:space:]]*[0-9]+'
|
|
84
|
+
}
|
|
71
85
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
86
|
+
extract_last_marked_block() {
|
|
87
|
+
local raw="$1"
|
|
88
|
+
if ! printf '%s' "$raw" | grep -q '🔗'; then
|
|
89
|
+
return 0
|
|
76
90
|
fi
|
|
77
91
|
|
|
78
|
-
printf '%s' "$
|
|
92
|
+
printf '%s\n' "$raw" | awk '
|
|
93
|
+
{
|
|
94
|
+
pos = index($0, "🔗");
|
|
95
|
+
if (pos > 0) {
|
|
96
|
+
out = substr($0, pos);
|
|
97
|
+
capture = 1;
|
|
98
|
+
next;
|
|
99
|
+
}
|
|
100
|
+
if (capture) {
|
|
101
|
+
out = out "\n" $0;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
END {
|
|
105
|
+
if (capture) print out;
|
|
106
|
+
}'
|
|
79
107
|
}
|
|
80
108
|
|
|
81
109
|
sanitize_output() {
|
|
82
110
|
local raw="$1"
|
|
83
|
-
local
|
|
84
|
-
|
|
85
|
-
extracted="$(extract_embedded_send_message "$raw")"
|
|
86
|
-
if [ -n "$extracted" ]; then
|
|
87
|
-
printf '%s' "$extracted"
|
|
88
|
-
return 0
|
|
89
|
-
fi
|
|
111
|
+
local cleaned marked
|
|
90
112
|
|
|
91
113
|
cleaned="$(printf '%s' "$raw" \
|
|
92
114
|
| tr '\r' '\n' \
|
|
93
115
|
| sed -E $'s/\x1B\\[[0-9;?]*[ -/]*[@-~]//g; s/\x1B\\][^\a]*(\a|\x1B\\\\)//g')"
|
|
94
116
|
|
|
117
|
+
cleaned="$(printf '%s\n' "$cleaned" | sed -E 's/\[[0-9]{1,3}m//g')"
|
|
118
|
+
|
|
95
119
|
cleaned="$(printf '%s\n' "$cleaned" | grep -Ev \
|
|
96
|
-
'^[[:space:]]*$|^[[:space:]]*(build
|
|
120
|
+
'^[[:space:]]*$|^[[:space:]]*(build[[:space:]]*·|◇[[:space:]]+Doctor warnings)[[:space:]]*$|^[[:space:]]*◇[[:space:]]+|^[[:space:]]*[←→↳].*|^[[:space:]]*Wrote file successfully\.?$|^[[:space:]]*(\$[[:space:]]*)?openclaw message send --channel[[:space:]]+|^[[:space:]]*error:[[:space:]]*too many arguments for '\''send'\''.*$|^[[:space:]]*Sent via Telegram|^[[:space:]]*\[(telegram|discord|slack|whatsapp|signal|irc|matrix|line|mattermost|teams)\]|autoSelectFamily=|dnsResultOrder=|^[[:space:]]*[│┌┐└┘├┤┬┴┼─═╭╮╰╯]+[[:space:]]*$')"
|
|
121
|
+
|
|
122
|
+
marked="$(extract_last_marked_block "$cleaned")"
|
|
123
|
+
if [ -n "$marked" ]; then
|
|
124
|
+
cleaned="$marked"
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
cleaned="$(printf '%s\n' "$cleaned" | sed -E 's/^🔗[[:space:]]*//')"
|
|
97
128
|
|
|
98
129
|
printf '%s' "$(trim_text "$cleaned")"
|
|
99
130
|
}
|
|
100
131
|
|
|
132
|
+
sentence_case_first() {
|
|
133
|
+
local text="$1"
|
|
134
|
+
printf '%s' "$text" | awk '
|
|
135
|
+
BEGIN { done = 0 }
|
|
136
|
+
{
|
|
137
|
+
if (done) { print; next }
|
|
138
|
+
line = $0
|
|
139
|
+
for (i = 1; i <= length(line); i++) {
|
|
140
|
+
ch = substr(line, i, 1)
|
|
141
|
+
if (ch ~ /[a-z]/) {
|
|
142
|
+
pre = substr(line, 1, i - 1)
|
|
143
|
+
post = substr(line, i + 1)
|
|
144
|
+
line = pre toupper(ch) post
|
|
145
|
+
done = 1
|
|
146
|
+
break
|
|
147
|
+
} else if (ch ~ /[A-Z]/) {
|
|
148
|
+
done = 1
|
|
149
|
+
break
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
print line
|
|
153
|
+
}'
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
apply_reply_style() {
|
|
157
|
+
local text="$1"
|
|
158
|
+
text="$(trim_text "$text")"
|
|
159
|
+
[ -z "$text" ] && { printf '%s' "$text"; return; }
|
|
160
|
+
text="$(sentence_case_first "$text")"
|
|
161
|
+
printf '%s' "$text"
|
|
162
|
+
}
|
|
163
|
+
|
|
101
164
|
run_with_timeout() {
|
|
102
165
|
local mode="$1"
|
|
103
166
|
local prompt="$2"
|
|
104
167
|
local output rc tmp pid watchdog
|
|
105
168
|
|
|
106
169
|
tmp="$(mktemp /tmp/opencode-run.XXXXXX)"
|
|
107
|
-
|
|
170
|
+
if [ -n "$mode" ]; then
|
|
171
|
+
"$OPENCODE" run "$mode" "$prompt" >"$tmp" 2>&1 &
|
|
172
|
+
else
|
|
173
|
+
"$OPENCODE" run "$prompt" >"$tmp" 2>&1 &
|
|
174
|
+
fi
|
|
108
175
|
pid=$!
|
|
109
176
|
|
|
110
177
|
(
|
|
@@ -140,10 +207,17 @@ run_with_timeout() {
|
|
|
140
207
|
cd "$WORKSPACE" || exit 1
|
|
141
208
|
FULL_MSG="[${CHANNEL}:${TARGET}] $MSG"
|
|
142
209
|
|
|
143
|
-
|
|
210
|
+
if ! acquire_bridge_lock; then
|
|
211
|
+
openclaw message send --channel "$CHANNEL" --target "$TARGET" -m "Bridge is still processing a previous request. Please retry in a moment."
|
|
212
|
+
printf '[%s] /ccn lock timeout after %ss\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$LOCK_WAIT_SEC"
|
|
213
|
+
exit 0
|
|
214
|
+
fi
|
|
215
|
+
|
|
216
|
+
# Fresh request: run without --continue to avoid session carryover.
|
|
217
|
+
run_result="$(run_with_timeout "" "$FULL_MSG")"
|
|
144
218
|
rc="$(printf '%s' "$run_result" | head -n 1)"
|
|
145
|
-
|
|
146
|
-
output="$(sanitize_output "$
|
|
219
|
+
raw_output="$(printf '%s' "$run_result" | tail -n +2)"
|
|
220
|
+
output="$(sanitize_output "$raw_output")"
|
|
147
221
|
|
|
148
222
|
if [ "$rc" -eq 124 ] || [ "$rc" -eq 137 ]; then
|
|
149
223
|
output="OpenCode timed out after ${RUN_TIMEOUT_SEC}s. Task may still be running. Try waiting a bit or send a follow-up."
|
|
@@ -153,7 +227,13 @@ run_with_timeout() {
|
|
|
153
227
|
output="OpenCode ran, but returned a non-informative echo. Please retry with a more specific prompt."
|
|
154
228
|
fi
|
|
155
229
|
|
|
156
|
-
|
|
230
|
+
output="$(apply_reply_style "$output")"
|
|
231
|
+
|
|
232
|
+
if has_external_delivery_success "$raw_output"; then
|
|
233
|
+
printf '[%s] /ccn skipped bridge send (already sent by OpenCode)\n' "$(date '+%Y-%m-%d %H:%M:%S')"
|
|
234
|
+
else
|
|
235
|
+
openclaw message send --channel "$CHANNEL" --target "$TARGET" -m "$output"
|
|
236
|
+
fi
|
|
157
237
|
|
|
158
238
|
ended_at=$(date +%s)
|
|
159
239
|
elapsed=$((ended_at - started_at))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# bridge-version:
|
|
2
|
+
# bridge-version: 9
|
|
3
3
|
# Dispatch instruction to OpenCode asynchronously and relay response
|
|
4
4
|
MSG="$1"
|
|
5
5
|
OPENCODE="{{OPENCODE_BIN}}"
|
|
@@ -9,6 +9,7 @@ WORKSPACE="{{WORKSPACE}}"
|
|
|
9
9
|
LOG_FILE="/tmp/opencode-bridge-send.log"
|
|
10
10
|
BASE_TIMEOUT_SEC=45
|
|
11
11
|
MAX_TIMEOUT_SEC=300
|
|
12
|
+
LOCK_WAIT_SEC=600
|
|
12
13
|
|
|
13
14
|
if [ -z "$MSG" ]; then
|
|
14
15
|
echo "ERROR: No message provided"
|
|
@@ -28,6 +29,21 @@ normalize_text() {
|
|
|
28
29
|
| sed -E 's/^🔗[[:space:]]*//; s/^["'\''`]+|["'\''`]+$//g; s/[[:space:]]+/ /g; s/^[[:space:]]+|[[:space:]]+$//g'
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
acquire_bridge_lock() {
|
|
33
|
+
local safe_channel safe_target lock_file
|
|
34
|
+
safe_channel="$(printf '%s' "$CHANNEL" | sed -E 's/[^a-zA-Z0-9._-]/_/g')"
|
|
35
|
+
safe_target="$(printf '%s' "$TARGET" | sed -E 's/[^a-zA-Z0-9._-]/_/g')"
|
|
36
|
+
lock_file="/tmp/opencode-bridge-${safe_channel}-${safe_target}.lock"
|
|
37
|
+
|
|
38
|
+
if command -v flock >/dev/null 2>&1; then
|
|
39
|
+
exec 200>"$lock_file"
|
|
40
|
+
flock -w "$LOCK_WAIT_SEC" 200
|
|
41
|
+
return $?
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
return 0
|
|
45
|
+
}
|
|
46
|
+
|
|
31
47
|
compute_timeout() {
|
|
32
48
|
local msg="$1"
|
|
33
49
|
local timeout="$BASE_TIMEOUT_SEC"
|
|
@@ -62,42 +78,89 @@ is_trivial_echo() {
|
|
|
62
78
|
[ -n "$message_norm" ] && [ "$output_norm" = "$message_norm" ]
|
|
63
79
|
}
|
|
64
80
|
|
|
65
|
-
|
|
81
|
+
has_external_delivery_success() {
|
|
66
82
|
local raw="$1"
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
line="$(printf '%s\n' "$raw" | grep -E 'openclaw message send --channel' | tail -n 1)"
|
|
70
|
-
[ -z "$line" ] && return 0
|
|
83
|
+
printf '%s\n' "$raw" | grep -Eqi 'Sent via [A-Za-z]+|Message ID:[[:space:]]*[0-9]+'
|
|
84
|
+
}
|
|
71
85
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
86
|
+
extract_last_marked_block() {
|
|
87
|
+
local raw="$1"
|
|
88
|
+
if ! printf '%s' "$raw" | grep -q '🔗'; then
|
|
89
|
+
return 0
|
|
76
90
|
fi
|
|
77
91
|
|
|
78
|
-
printf '%s' "$
|
|
92
|
+
printf '%s\n' "$raw" | awk '
|
|
93
|
+
{
|
|
94
|
+
pos = index($0, "🔗");
|
|
95
|
+
if (pos > 0) {
|
|
96
|
+
out = substr($0, pos);
|
|
97
|
+
capture = 1;
|
|
98
|
+
next;
|
|
99
|
+
}
|
|
100
|
+
if (capture) {
|
|
101
|
+
out = out "\n" $0;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
END {
|
|
105
|
+
if (capture) print out;
|
|
106
|
+
}'
|
|
79
107
|
}
|
|
80
108
|
|
|
81
109
|
sanitize_output() {
|
|
82
110
|
local raw="$1"
|
|
83
|
-
local
|
|
84
|
-
|
|
85
|
-
extracted="$(extract_embedded_send_message "$raw")"
|
|
86
|
-
if [ -n "$extracted" ]; then
|
|
87
|
-
printf '%s' "$extracted"
|
|
88
|
-
return 0
|
|
89
|
-
fi
|
|
111
|
+
local cleaned marked
|
|
90
112
|
|
|
91
113
|
cleaned="$(printf '%s' "$raw" \
|
|
92
114
|
| tr '\r' '\n' \
|
|
93
115
|
| sed -E $'s/\x1B\\[[0-9;?]*[ -/]*[@-~]//g; s/\x1B\\][^\a]*(\a|\x1B\\\\)//g')"
|
|
94
116
|
|
|
117
|
+
cleaned="$(printf '%s\n' "$cleaned" | sed -E 's/\[[0-9]{1,3}m//g')"
|
|
118
|
+
|
|
95
119
|
cleaned="$(printf '%s\n' "$cleaned" | grep -Ev \
|
|
96
|
-
'^[[:space:]]*$|^[[:space:]]*(build
|
|
120
|
+
'^[[:space:]]*$|^[[:space:]]*(build[[:space:]]*·|◇[[:space:]]+Doctor warnings)[[:space:]]*$|^[[:space:]]*◇[[:space:]]+|^[[:space:]]*[←→↳].*|^[[:space:]]*Wrote file successfully\.?$|^[[:space:]]*(\$[[:space:]]*)?openclaw message send --channel[[:space:]]+|^[[:space:]]*error:[[:space:]]*too many arguments for '\''send'\''.*$|^[[:space:]]*Sent via Telegram|^[[:space:]]*\[(telegram|discord|slack|whatsapp|signal|irc|matrix|line|mattermost|teams)\]|autoSelectFamily=|dnsResultOrder=|^[[:space:]]*[│┌┐└┘├┤┬┴┼─═╭╮╰╯]+[[:space:]]*$')"
|
|
121
|
+
|
|
122
|
+
marked="$(extract_last_marked_block "$cleaned")"
|
|
123
|
+
if [ -n "$marked" ]; then
|
|
124
|
+
cleaned="$marked"
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
cleaned="$(printf '%s\n' "$cleaned" | sed -E 's/^🔗[[:space:]]*//')"
|
|
97
128
|
|
|
98
129
|
printf '%s' "$(trim_text "$cleaned")"
|
|
99
130
|
}
|
|
100
131
|
|
|
132
|
+
sentence_case_first() {
|
|
133
|
+
local text="$1"
|
|
134
|
+
printf '%s' "$text" | awk '
|
|
135
|
+
BEGIN { done = 0 }
|
|
136
|
+
{
|
|
137
|
+
if (done) { print; next }
|
|
138
|
+
line = $0
|
|
139
|
+
for (i = 1; i <= length(line); i++) {
|
|
140
|
+
ch = substr(line, i, 1)
|
|
141
|
+
if (ch ~ /[a-z]/) {
|
|
142
|
+
pre = substr(line, 1, i - 1)
|
|
143
|
+
post = substr(line, i + 1)
|
|
144
|
+
line = pre toupper(ch) post
|
|
145
|
+
done = 1
|
|
146
|
+
break
|
|
147
|
+
} else if (ch ~ /[A-Z]/) {
|
|
148
|
+
done = 1
|
|
149
|
+
break
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
print line
|
|
153
|
+
}'
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
apply_reply_style() {
|
|
157
|
+
local text="$1"
|
|
158
|
+
text="$(trim_text "$text")"
|
|
159
|
+
[ -z "$text" ] && { printf '%s' "$text"; return; }
|
|
160
|
+
text="$(sentence_case_first "$text")"
|
|
161
|
+
printf '%s' "$text"
|
|
162
|
+
}
|
|
163
|
+
|
|
101
164
|
run_with_timeout() {
|
|
102
165
|
local mode="$1"
|
|
103
166
|
local prompt="$2"
|
|
@@ -140,10 +203,16 @@ run_with_timeout() {
|
|
|
140
203
|
cd "$WORKSPACE" || exit 1
|
|
141
204
|
FULL_MSG="[${CHANNEL}:${TARGET}] $MSG"
|
|
142
205
|
|
|
206
|
+
if ! acquire_bridge_lock; then
|
|
207
|
+
openclaw message send --channel "$CHANNEL" --target "$TARGET" -m "Bridge is still processing a previous request. Please retry in a moment."
|
|
208
|
+
printf '[%s] /cc lock timeout after %ss\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$LOCK_WAIT_SEC"
|
|
209
|
+
exit 0
|
|
210
|
+
fi
|
|
211
|
+
|
|
143
212
|
run_result="$(run_with_timeout --continue "$FULL_MSG")"
|
|
144
213
|
rc="$(printf '%s' "$run_result" | head -n 1)"
|
|
145
|
-
|
|
146
|
-
output="$(sanitize_output "$
|
|
214
|
+
raw_output="$(printf '%s' "$run_result" | tail -n +2)"
|
|
215
|
+
output="$(sanitize_output "$raw_output")"
|
|
147
216
|
|
|
148
217
|
if [ "$rc" -eq 124 ] || [ "$rc" -eq 137 ]; then
|
|
149
218
|
output="OpenCode timed out after ${RUN_TIMEOUT_SEC}s. Task may still be running. Try waiting a bit or send a follow-up."
|
|
@@ -153,7 +222,13 @@ run_with_timeout() {
|
|
|
153
222
|
output="OpenCode ran, but returned a non-informative echo. Please retry with a more specific prompt."
|
|
154
223
|
fi
|
|
155
224
|
|
|
156
|
-
|
|
225
|
+
output="$(apply_reply_style "$output")"
|
|
226
|
+
|
|
227
|
+
if has_external_delivery_success "$raw_output"; then
|
|
228
|
+
printf '[%s] /cc skipped bridge send (already sent by OpenCode)\n' "$(date '+%Y-%m-%d %H:%M:%S')"
|
|
229
|
+
else
|
|
230
|
+
openclaw message send --channel "$CHANNEL" --target "$TARGET" -m "$output"
|
|
231
|
+
fi
|
|
157
232
|
|
|
158
233
|
ended_at=$(date +%s)
|
|
159
234
|
elapsed=$((ended_at - started_at))
|
|
@@ -39,4 +39,6 @@ The format is: `[CHANNEL:ID] actual message`
|
|
|
39
39
|
- For follow-up status questions such as "have you created it?", do not answer with only yes/no.
|
|
40
40
|
Always include short status details and the run command.
|
|
41
41
|
- Keep tone clear, proactive, and helpful. Prefer concise but complete responses.
|
|
42
|
+
- Use proper sentence case and punctuation. Start the first sentence with an uppercase letter.
|
|
43
|
+
- Avoid slang-only openings like "hey!" or "yep!" without context; provide a complete helpful sentence.
|
|
42
44
|
- Length guidance: trivial questions can be 1-2 lines; implementation results should usually be 4-10 lines.
|