@rubytech/create-realagent 1.0.615 → 1.0.616
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/package.json +1 -1
- package/payload/platform/config/brand.json +4 -0
- package/payload/platform/lib/mcp-stderr-tee/dist/index.d.ts +23 -13
- package/payload/platform/lib/mcp-stderr-tee/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/mcp-stderr-tee/dist/index.js +86 -89
- package/payload/platform/lib/mcp-stderr-tee/dist/index.js.map +1 -1
- package/payload/platform/lib/mcp-stderr-tee/src/index.ts +86 -101
- package/payload/platform/plugins/admin/mcp/dist/index.js +33 -2
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/skills/stream-log-review/SKILL.md +22 -8
- package/payload/platform/plugins/cloudflare/PLUGIN.md +5 -4
- package/payload/platform/plugins/cloudflare/mcp/__tests__/auth-binding.test.ts +196 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/brand-load.test.ts +81 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/manifest-scope.test.ts +65 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/verify-scenario-0.test.ts +70 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/verify-scenario-B.test.ts +124 -0
- package/payload/platform/plugins/cloudflare/mcp/dist/index.js +221 -200
- package/payload/platform/plugins/cloudflare/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.d.ts +174 -39
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.d.ts.map +1 -1
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.js +891 -194
- package/payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.js.map +1 -1
- package/payload/platform/plugins/cloudflare/mcp/package.json +5 -2
- package/payload/platform/plugins/cloudflare/mcp/vitest.config.ts +10 -0
- package/payload/platform/plugins/cloudflare/references/setup-guide.md +31 -32
- package/payload/platform/plugins/cloudflare/skills/setup-tunnel/SKILL.md +25 -3
- package/payload/platform/plugins/docs/PLUGIN.md +2 -0
- package/payload/platform/plugins/docs/references/cloudflare.md +68 -0
- package/payload/platform/plugins/docs/references/plugins-guide.md +8 -6
- package/payload/platform/scripts/logs-read.sh +114 -54
- package/payload/platform/templates/specialists/agents/personal-assistant.md +12 -8
- package/payload/server/server.js +387 -71
|
@@ -1,19 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# logs-read.sh — Shell counterpart to the logs-read MCP tool.
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
4
|
+
# Task 532: stream logs are per-conversation, not per-day. The primary mode
|
|
5
|
+
# now reads a single {prefix}-{conversationId}.log file — the reader gets a
|
|
6
|
+
# continuous, conversation-scoped timeline from first [spawn] to final
|
|
7
|
+
# [process-exit] without needing to filter.
|
|
7
8
|
#
|
|
8
|
-
#
|
|
9
|
-
# logs-read.sh <
|
|
10
|
-
# logs-read.sh --tail [type] [lines]
|
|
9
|
+
# Modes:
|
|
10
|
+
# logs-read.sh <conversationId> [type] Read {prefix}-{convId}.log
|
|
11
|
+
# logs-read.sh --tail [type] [lines] Tail most recent file of type
|
|
12
|
+
# logs-read.sh --grep <sessionKey> [type] Legacy grep across log files
|
|
11
13
|
#
|
|
12
|
-
# Types: system, session, error, heartbeat, public, server
|
|
14
|
+
# Types: system, session, error, heartbeat, public, server, mcp, vnc, review
|
|
15
|
+
# For per-conversation types (system/session/error/public): conversationId is
|
|
16
|
+
# required in the first mode. For platform-scoped types (server/vnc/review/
|
|
17
|
+
# heartbeat): conversationId is ignored.
|
|
18
|
+
#
|
|
19
|
+
# Every invocation writes a one-line trailer describing files searched,
|
|
20
|
+
# matches returned, and files rejected — empty output never leaves a reader
|
|
21
|
+
# guessing why.
|
|
13
22
|
#
|
|
14
23
|
# Exit codes:
|
|
15
24
|
# 0 Success (output produced)
|
|
16
|
-
# 1 No matches found (clean, not an error)
|
|
25
|
+
# 1 No matches / file not found (clean, not an error)
|
|
17
26
|
# 2 Usage error or missing directory
|
|
18
27
|
set -euo pipefail
|
|
19
28
|
|
|
@@ -50,7 +59,6 @@ if [[ ${#ACCOUNT_DIRS[@]} -eq 0 ]]; then
|
|
|
50
59
|
fi
|
|
51
60
|
|
|
52
61
|
# Build array of account log directories that actually exist.
|
|
53
|
-
# Multi-account devices (e.g. Maxy Pi) may have >1 account dir.
|
|
54
62
|
ACCOUNT_LOG_DIRS=()
|
|
55
63
|
for _adir in "${ACCOUNT_DIRS[@]}"; do
|
|
56
64
|
[[ -d "${_adir}logs" ]] && ACCOUNT_LOG_DIRS+=("${_adir}logs")
|
|
@@ -62,20 +70,15 @@ fi
|
|
|
62
70
|
MULTI_ACCOUNT=$(( ${#ACCOUNT_LOG_DIRS[@]} > 1 ? 1 : 0 ))
|
|
63
71
|
|
|
64
72
|
# Account ID suffix for headers — only shown when multiple accounts exist.
|
|
65
|
-
# Accepts a log directory path (e.g. /path/accounts/<id>/logs) and extracts
|
|
66
|
-
# the account ID from the parent directory name.
|
|
67
73
|
account_suffix() {
|
|
68
74
|
if [[ $MULTI_ACCOUNT -eq 1 ]]; then
|
|
69
75
|
local path="$1"
|
|
70
|
-
# Normalize: strip trailing slash, ensure we're looking at the logs dir
|
|
71
76
|
path="${path%/}"
|
|
72
|
-
# If path ends with /logs, extract account ID from parent
|
|
73
77
|
if [[ "$path" == */logs ]]; then
|
|
74
78
|
local acct_id
|
|
75
79
|
acct_id=$(basename "$(dirname "$path")")
|
|
76
80
|
echo " [${acct_id:0:8}]"
|
|
77
81
|
else
|
|
78
|
-
# Path is a file inside logs/ — go up two levels
|
|
79
82
|
local acct_id
|
|
80
83
|
acct_id=$(basename "$(dirname "$(dirname "$path")")")
|
|
81
84
|
echo " [${acct_id:0:8}]"
|
|
@@ -84,7 +87,7 @@ account_suffix() {
|
|
|
84
87
|
}
|
|
85
88
|
|
|
86
89
|
# --- Prefix map (mirrors MCP tool exactly) ---
|
|
87
|
-
#
|
|
90
|
+
# Per-conversation types: stream log + its siblings (stderr, sse, public).
|
|
88
91
|
prefix_for_type() {
|
|
89
92
|
case "$1" in
|
|
90
93
|
system) echo "claude-agent-stream-" ;;
|
|
@@ -96,24 +99,34 @@ prefix_for_type() {
|
|
|
96
99
|
esac
|
|
97
100
|
}
|
|
98
101
|
|
|
99
|
-
#
|
|
102
|
+
# Which types are per-conversation (the first mode's convId argument applies)
|
|
103
|
+
is_per_conversation_type() {
|
|
104
|
+
case "$1" in
|
|
105
|
+
system|error|session|public) return 0 ;;
|
|
106
|
+
*) return 1 ;;
|
|
107
|
+
esac
|
|
108
|
+
}
|
|
109
|
+
|
|
100
110
|
SEARCH_TYPES="system error session public server mcp vnc review"
|
|
101
111
|
VALID_TYPES="system, session, error, heartbeat, public, server, mcp, vnc, review"
|
|
102
112
|
|
|
103
|
-
# --- Usage ---
|
|
104
113
|
usage() {
|
|
105
114
|
cat >&2 <<EOF
|
|
106
115
|
Usage:
|
|
107
|
-
logs-read.sh <
|
|
108
|
-
logs-read.sh --tail [type] [lines]
|
|
116
|
+
logs-read.sh <conversationId> [type] Read {prefix}-{convId}.log
|
|
117
|
+
logs-read.sh --tail [type] [lines] Tail most recent log of type
|
|
118
|
+
logs-read.sh --grep <sessionKey> [type] Legacy grep across log files
|
|
109
119
|
|
|
110
120
|
Types: $VALID_TYPES
|
|
111
121
|
Default type: system | Default lines: 50
|
|
122
|
+
|
|
123
|
+
Per-conversation types (system, session, error, public) require conversationId
|
|
124
|
+
in the first mode — the log file is named {prefix}-{conversationId}.log.
|
|
125
|
+
Platform-scoped types (server, vnc, review, heartbeat) ignore conversationId.
|
|
112
126
|
EOF
|
|
113
127
|
exit 2
|
|
114
128
|
}
|
|
115
129
|
|
|
116
|
-
# --- Validate type ---
|
|
117
130
|
validate_type() {
|
|
118
131
|
local t="$1"
|
|
119
132
|
case "$t" in
|
|
@@ -122,12 +135,65 @@ validate_type() {
|
|
|
122
135
|
esac
|
|
123
136
|
}
|
|
124
137
|
|
|
125
|
-
# ---
|
|
126
|
-
|
|
138
|
+
# --- Per-conversation mode: read {prefix}-{convId}.log ---
|
|
139
|
+
per_conversation_mode() {
|
|
140
|
+
local conv_id="$1"
|
|
141
|
+
local filter_type="${2:-system}"
|
|
142
|
+
|
|
143
|
+
if [[ -z "$conv_id" ]]; then
|
|
144
|
+
echo "Error: conversationId cannot be empty" >&2
|
|
145
|
+
exit 2
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
validate_type "$filter_type"
|
|
149
|
+
|
|
150
|
+
# Platform-scoped types shortcut to their fixed files regardless of convId.
|
|
151
|
+
case "$filter_type" in
|
|
152
|
+
server|vnc|review|heartbeat|mcp)
|
|
153
|
+
echo "# note: type=$filter_type is platform-scoped; conversationId ignored — showing fixed file" >&2
|
|
154
|
+
tail_mode "$filter_type" "50"
|
|
155
|
+
return
|
|
156
|
+
;;
|
|
157
|
+
esac
|
|
158
|
+
|
|
159
|
+
local prefix
|
|
160
|
+
prefix=$(prefix_for_type "$filter_type")
|
|
161
|
+
if [[ -z "$prefix" ]]; then
|
|
162
|
+
echo "Error: no prefix mapping for type '$filter_type'" >&2
|
|
163
|
+
exit 2
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
local found=0
|
|
167
|
+
local searched=0
|
|
168
|
+
local rejected=0
|
|
169
|
+
for log_dir in "${ACCOUNT_LOG_DIRS[@]}"; do
|
|
170
|
+
local filepath="$log_dir/${prefix}${conv_id}.log"
|
|
171
|
+
searched=$((searched + 1))
|
|
172
|
+
if [[ ! -f "$filepath" ]]; then
|
|
173
|
+
rejected=$((rejected + 1))
|
|
174
|
+
continue
|
|
175
|
+
fi
|
|
176
|
+
[[ $found -gt 0 ]] && echo ""
|
|
177
|
+
echo "## $(basename "$filepath") ($filter_type)$(account_suffix "$log_dir")"
|
|
178
|
+
cat "$filepath"
|
|
179
|
+
found=$((found + 1))
|
|
180
|
+
done
|
|
181
|
+
|
|
182
|
+
# Trailer: empty output never leaves the reader guessing why.
|
|
183
|
+
if [[ $found -eq 0 ]]; then
|
|
184
|
+
echo "-- trailer: conversationId=$conv_id type=$filter_type searched=$searched found=0 rejected=$rejected reason=file-not-found" >&2
|
|
185
|
+
exit 1
|
|
186
|
+
fi
|
|
187
|
+
echo "" >&2
|
|
188
|
+
echo "-- trailer: conversationId=$conv_id type=$filter_type searched=$searched matched=$found rejected=$rejected" >&2
|
|
189
|
+
exit 0
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
# --- Legacy grep mode (backward compatibility with sessionKey-tagged lines) ---
|
|
193
|
+
grep_mode() {
|
|
127
194
|
local session_key="$1"
|
|
128
195
|
local filter_type="${2:-}"
|
|
129
196
|
|
|
130
|
-
# Guard against empty session key (grep -F "" matches everything)
|
|
131
197
|
if [[ -z "$session_key" ]]; then
|
|
132
198
|
echo "Error: session key cannot be empty" >&2
|
|
133
199
|
exit 2
|
|
@@ -137,7 +203,6 @@ session_key_mode() {
|
|
|
137
203
|
validate_type "$filter_type"
|
|
138
204
|
fi
|
|
139
205
|
|
|
140
|
-
# Determine which types to search
|
|
141
206
|
local types_to_search
|
|
142
207
|
if [[ -n "$filter_type" && "$filter_type" != "heartbeat" ]]; then
|
|
143
208
|
types_to_search="$filter_type"
|
|
@@ -146,11 +211,13 @@ session_key_mode() {
|
|
|
146
211
|
fi
|
|
147
212
|
|
|
148
213
|
local found=0
|
|
214
|
+
local files_searched=0
|
|
215
|
+
local files_rejected=0
|
|
149
216
|
|
|
150
217
|
for log_type in $types_to_search; do
|
|
151
|
-
# server: single file in configDir (platform-scoped, not account-scoped)
|
|
152
218
|
if [[ "$log_type" == "server" ]]; then
|
|
153
219
|
if [[ -f "$SERVER_LOG" ]]; then
|
|
220
|
+
files_searched=$((files_searched + 1))
|
|
154
221
|
local result
|
|
155
222
|
if result=$(grep -F "$session_key" "$SERVER_LOG" 2>/dev/null); then
|
|
156
223
|
if [[ -n "$result" ]]; then
|
|
@@ -160,14 +227,15 @@ session_key_mode() {
|
|
|
160
227
|
found=$((found + 1))
|
|
161
228
|
fi
|
|
162
229
|
fi
|
|
230
|
+
else
|
|
231
|
+
files_rejected=$((files_rejected + 1))
|
|
163
232
|
fi
|
|
164
233
|
continue
|
|
165
234
|
fi
|
|
166
235
|
|
|
167
|
-
# vnc: single platform-scoped file covering the VNC browser viewer
|
|
168
|
-
# lifecycle (boot events from vnc.sh + runtime events from vnc-logger.ts)
|
|
169
236
|
if [[ "$log_type" == "vnc" ]]; then
|
|
170
237
|
if [[ -f "$VNC_LOG" ]]; then
|
|
238
|
+
files_searched=$((files_searched + 1))
|
|
171
239
|
local result
|
|
172
240
|
if result=$(grep -F "$session_key" "$VNC_LOG" 2>/dev/null); then
|
|
173
241
|
if [[ -n "$result" ]]; then
|
|
@@ -177,16 +245,15 @@ session_key_mode() {
|
|
|
177
245
|
found=$((found + 1))
|
|
178
246
|
fi
|
|
179
247
|
fi
|
|
248
|
+
else
|
|
249
|
+
files_rejected=$((files_rejected + 1))
|
|
180
250
|
fi
|
|
181
251
|
continue
|
|
182
252
|
fi
|
|
183
253
|
|
|
184
|
-
# review: single platform-scoped file containing every decision made
|
|
185
|
-
# by the in-process review detector — scan cycles, matches, suppressions,
|
|
186
|
-
# rate-limit decisions, rule mutations, and admin tool audit trail.
|
|
187
|
-
# Task 385 — the one log that proves observability-plus-review is working.
|
|
188
254
|
if [[ "$log_type" == "review" ]]; then
|
|
189
255
|
if [[ -f "$REVIEW_LOG" ]]; then
|
|
256
|
+
files_searched=$((files_searched + 1))
|
|
190
257
|
local result
|
|
191
258
|
if result=$(grep -F "$session_key" "$REVIEW_LOG" 2>/dev/null); then
|
|
192
259
|
if [[ -n "$result" ]]; then
|
|
@@ -196,6 +263,8 @@ session_key_mode() {
|
|
|
196
263
|
found=$((found + 1))
|
|
197
264
|
fi
|
|
198
265
|
fi
|
|
266
|
+
else
|
|
267
|
+
files_rejected=$((files_rejected + 1))
|
|
199
268
|
fi
|
|
200
269
|
continue
|
|
201
270
|
fi
|
|
@@ -204,20 +273,17 @@ session_key_mode() {
|
|
|
204
273
|
prefix=$(prefix_for_type "$log_type")
|
|
205
274
|
[[ -z "$prefix" ]] && continue
|
|
206
275
|
|
|
207
|
-
# Search all account log directories for matching files
|
|
208
276
|
for log_dir in "${ACCOUNT_LOG_DIRS[@]}"; do
|
|
209
277
|
shopt -s nullglob
|
|
210
278
|
local files=("$log_dir"/${prefix}*.log)
|
|
211
279
|
shopt -u nullglob
|
|
212
|
-
|
|
213
|
-
# Sort by filename (date suffix ensures chronological order)
|
|
214
280
|
IFS=$'\n' files=($(printf '%s\n' "${files[@]}" | sort)); unset IFS
|
|
215
281
|
|
|
216
282
|
for filepath in "${files[@]}"; do
|
|
283
|
+
files_searched=$((files_searched + 1))
|
|
217
284
|
local file
|
|
218
285
|
file=$(basename "$filepath")
|
|
219
286
|
|
|
220
|
-
# grep -F: fixed string match. Exit 1 = no match (expected).
|
|
221
287
|
local result
|
|
222
288
|
if result=$(grep -F "$session_key" "$filepath" 2>/dev/null); then
|
|
223
289
|
if [[ -n "$result" ]]; then
|
|
@@ -232,27 +298,26 @@ session_key_mode() {
|
|
|
232
298
|
done
|
|
233
299
|
|
|
234
300
|
if [[ $found -eq 0 ]]; then
|
|
235
|
-
echo "No log lines found for session key \"$session_key\"."
|
|
301
|
+
echo "No log lines found for session key \"$session_key\"." >&2
|
|
302
|
+
echo "-- trailer: sessionKey=$session_key files_searched=$files_searched files_rejected=$files_rejected matches=0" >&2
|
|
236
303
|
exit 1
|
|
237
304
|
fi
|
|
238
|
-
|
|
305
|
+
echo "" >&2
|
|
306
|
+
echo "-- trailer: sessionKey=$session_key files_searched=$files_searched files_rejected=$files_rejected matches=$found" >&2
|
|
239
307
|
exit 0
|
|
240
308
|
}
|
|
241
309
|
|
|
242
|
-
# --- Tail mode ---
|
|
243
310
|
tail_mode() {
|
|
244
311
|
local log_type="${1:-system}"
|
|
245
312
|
local lines="${2:-50}"
|
|
246
313
|
|
|
247
314
|
validate_type "$log_type"
|
|
248
315
|
|
|
249
|
-
# Validate lines is numeric
|
|
250
316
|
if ! [[ "$lines" =~ ^[0-9]+$ ]]; then
|
|
251
317
|
echo "Error: lines must be a number, got '$lines'" >&2
|
|
252
318
|
exit 2
|
|
253
319
|
fi
|
|
254
320
|
|
|
255
|
-
# Heartbeat: single fixed file (account-scoped) — search all accounts, use most recent
|
|
256
321
|
if [[ "$log_type" == "heartbeat" ]]; then
|
|
257
322
|
local hb_file=""
|
|
258
323
|
for log_dir in "${ACCOUNT_LOG_DIRS[@]}"; do
|
|
@@ -273,7 +338,6 @@ tail_mode() {
|
|
|
273
338
|
exit 0
|
|
274
339
|
fi
|
|
275
340
|
|
|
276
|
-
# Server: single fixed file (platform-scoped, in configDir)
|
|
277
341
|
if [[ "$log_type" == "server" ]]; then
|
|
278
342
|
if [[ ! -f "$SERVER_LOG" ]]; then
|
|
279
343
|
echo "No server log found at $SERVER_LOG"
|
|
@@ -285,11 +349,6 @@ tail_mode() {
|
|
|
285
349
|
exit 0
|
|
286
350
|
fi
|
|
287
351
|
|
|
288
|
-
# VNC: single platform-scoped file covering the entire VNC browser
|
|
289
|
-
# viewer lifecycle (Xtigervnc boot, websockify, Chromium CDP, HTTP
|
|
290
|
-
# viewer fetches, WebSocket upgrades, proxy pipe events, MCP browser
|
|
291
|
-
# tool calls, client disconnect reasons, ensureVnc/ensureCdp recovery).
|
|
292
|
-
# Single retrieval must diagnose any browser-viewer failure mode.
|
|
293
352
|
if [[ "$log_type" == "vnc" ]]; then
|
|
294
353
|
if [[ ! -f "$VNC_LOG" ]]; then
|
|
295
354
|
echo "No vnc-boot log found at $VNC_LOG"
|
|
@@ -301,10 +360,6 @@ tail_mode() {
|
|
|
301
360
|
exit 0
|
|
302
361
|
fi
|
|
303
362
|
|
|
304
|
-
# Review: single platform-scoped file written by the review detector
|
|
305
|
-
# (Task 385). Every scan cycle, rule match, suppression decision, rate
|
|
306
|
-
# limit hold-back, and admin-tool rule mutation is logged here. This is
|
|
307
|
-
# the canonical log to audit "did the detector see this?" questions.
|
|
308
363
|
if [[ "$log_type" == "review" ]]; then
|
|
309
364
|
if [[ ! -f "$REVIEW_LOG" ]]; then
|
|
310
365
|
echo "No review log found at $REVIEW_LOG (detector may not have started yet)"
|
|
@@ -316,7 +371,6 @@ tail_mode() {
|
|
|
316
371
|
exit 0
|
|
317
372
|
fi
|
|
318
373
|
|
|
319
|
-
# Find most recent file by mtime across all account log directories
|
|
320
374
|
local prefix
|
|
321
375
|
prefix=$(prefix_for_type "$log_type")
|
|
322
376
|
|
|
@@ -333,7 +387,9 @@ tail_mode() {
|
|
|
333
387
|
exit 1
|
|
334
388
|
fi
|
|
335
389
|
|
|
336
|
-
# Sort by mtime descending — most recent first
|
|
390
|
+
# Sort by mtime descending — most recent first. Per-conversation filenames
|
|
391
|
+
# no longer sort chronologically by name (UUID suffix), so mtime is the
|
|
392
|
+
# only reliable "most recently active" ordering.
|
|
337
393
|
local match
|
|
338
394
|
match=$(ls -t "${all_files[@]}" | head -1)
|
|
339
395
|
local match_name
|
|
@@ -345,7 +401,6 @@ tail_mode() {
|
|
|
345
401
|
exit 0
|
|
346
402
|
}
|
|
347
403
|
|
|
348
|
-
# --- Main ---
|
|
349
404
|
if [[ $# -eq 0 ]]; then
|
|
350
405
|
usage
|
|
351
406
|
fi
|
|
@@ -355,6 +410,11 @@ case "$1" in
|
|
|
355
410
|
shift
|
|
356
411
|
tail_mode "${1:-system}" "${2:-50}"
|
|
357
412
|
;;
|
|
413
|
+
--grep)
|
|
414
|
+
shift
|
|
415
|
+
[[ $# -eq 0 ]] && usage
|
|
416
|
+
grep_mode "$1" "${2:-}"
|
|
417
|
+
;;
|
|
358
418
|
--help|-h)
|
|
359
419
|
usage
|
|
360
420
|
;;
|
|
@@ -363,6 +423,6 @@ case "$1" in
|
|
|
363
423
|
usage
|
|
364
424
|
;;
|
|
365
425
|
*)
|
|
366
|
-
|
|
426
|
+
per_conversation_mode "$1" "${2:-}"
|
|
367
427
|
;;
|
|
368
428
|
esac
|
|
@@ -3,7 +3,7 @@ name: personal-assistant
|
|
|
3
3
|
description: "Your personal assistant — scheduling, platform administration, messaging channels, system health, and browser automation. Delegate when a task involves managing your calendar, configuring the platform, operating messaging channels, or completing interactive browser tasks."
|
|
4
4
|
summary: "Handles the operational tasks you'd give a personal assistant — scheduling meetings, managing your platform settings, connecting messaging channels, and completing browser-based tasks on your behalf. For example, when you want to schedule a weekly check-in, set up Telegram, or fill out an online form."
|
|
5
5
|
model: claude-sonnet-4-6
|
|
6
|
-
tools: mcp__admin__system-status, mcp__admin__brand-settings, mcp__admin__account-manage, mcp__admin__account-update, mcp__admin__logs-read, mcp__admin__plugin-read, mcp__admin__api-key-store, mcp__admin__api-key-verify, mcp__admin__render-component, mcp__admin__file-attach, mcp__admin__wifi, mcp__contacts__contact-create, mcp__contacts__contact-lookup, mcp__contacts__contact-update, mcp__contacts__contact-delete, mcp__contacts__contact-list, mcp__contacts__contact-export, mcp__contacts__contact-erase, mcp__contacts__group-create, mcp__contacts__group-manage, mcp__cloudflare__cf-
|
|
6
|
+
tools: mcp__admin__system-status, mcp__admin__brand-settings, mcp__admin__account-manage, mcp__admin__account-update, mcp__admin__logs-read, mcp__admin__plugin-read, mcp__admin__api-key-store, mcp__admin__api-key-verify, mcp__admin__render-component, mcp__admin__file-attach, mcp__admin__wifi, mcp__contacts__contact-create, mcp__contacts__contact-lookup, mcp__contacts__contact-update, mcp__contacts__contact-delete, mcp__contacts__contact-list, mcp__contacts__contact-export, mcp__contacts__contact-erase, mcp__contacts__group-create, mcp__contacts__group-manage, mcp__cloudflare__cf-add-zone, mcp__cloudflare__cf-zone-status, mcp__cloudflare__cf-verify, mcp__cloudflare__cf-rebuild, mcp__cloudflare__tunnel-status, mcp__cloudflare__tunnel-install, mcp__cloudflare__tunnel-login, mcp__cloudflare__tunnel-enable, mcp__cloudflare__tunnel-disable, mcp__cloudflare__tunnel-add-hostname, mcp__cloudflare__dns-lookup, mcp__telegram__message, mcp__telegram__message-history, mcp__telegram__telegram-webhook-register, mcp__whatsapp__whatsapp-login-start, mcp__whatsapp__whatsapp-login-wait, mcp__whatsapp__whatsapp-status, mcp__whatsapp__whatsapp-disconnect, mcp__whatsapp__whatsapp-send, mcp__whatsapp__whatsapp-send-document, mcp__whatsapp__whatsapp-config, mcp__whatsapp__whatsapp-activity, mcp__whatsapp__whatsapp-conversations, mcp__whatsapp__whatsapp-messages, mcp__whatsapp__whatsapp-group-info, mcp__email__email-setup, mcp__email__email-read, mcp__email__email-send, mcp__email__email-reply, mcp__email__email-search, mcp__email__email-graph-query, mcp__email__email-otp-extract, mcp__email__email-status, mcp__email__email-auto-respond-config, mcp__scheduling__schedule-event, mcp__scheduling__schedule-list, mcp__scheduling__schedule-get, mcp__scheduling__schedule-update, mcp__scheduling__schedule-cancel, mcp__scheduling__schedule-export-ics, mcp__scheduling__schedule-import-ics, mcp__scheduling__time-resolve, mcp__memory__memory-search, mcp__memory__profile-update, mcp__plugin_playwright_playwright__browser_navigate, mcp__plugin_playwright_playwright__browser_navigate_back, mcp__plugin_playwright_playwright__browser_snapshot, mcp__plugin_playwright_playwright__browser_click, mcp__plugin_playwright_playwright__browser_fill, mcp__plugin_playwright_playwright__browser_fill_form, mcp__plugin_playwright_playwright__browser_type, mcp__plugin_playwright_playwright__browser_press_key, mcp__plugin_playwright_playwright__browser_hover, mcp__plugin_playwright_playwright__browser_select_option, mcp__plugin_playwright_playwright__browser_wait_for, mcp__plugin_playwright_playwright__browser_handle_dialog, mcp__plugin_playwright_playwright__browser_evaluate, mcp__plugin_playwright_playwright__browser_console_messages, mcp__plugin_playwright_playwright__browser_resize, mcp__plugin_playwright_playwright__browser_tabs, mcp__plugin_playwright_playwright__browser_close
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Personal Assistant
|
|
@@ -41,19 +41,23 @@ Manages events, appointments, and recurring triggers in the graph.
|
|
|
41
41
|
|
|
42
42
|
## Cloudflare Tunnel
|
|
43
43
|
|
|
44
|
-
Guides setting up a Cloudflare Tunnel so the platform is reachable via a custom domain.
|
|
44
|
+
Guides setting up a Cloudflare Tunnel so the platform is reachable via a custom domain. The brand declares its Cloudflare zones at build time in `brand.json` (`cloudflare.zones`); every tool refuses operations against hostnames whose registrable parent is not in that list. Authentication is OAuth-only via `tunnel-login`; on first success the device records an account binding (`account-binding.json`) and refuses subsequent operations if the cert is later rotated under a different Cloudflare account.
|
|
45
45
|
|
|
46
|
-
**Auth
|
|
46
|
+
**Auth path:** `tunnel-login` (one-click OAuth in VNC browser). Pass `force=true` to clear cert + binding when switching Cloudflare accounts. There is no API-token auth path — the plugin recognises only the cert-bound account identity.
|
|
47
47
|
|
|
48
|
-
**Setup flow:**
|
|
48
|
+
**Setup flow:** `cloudflare-setup` is the single orchestrator — it discovers state, prompts for tunnel/zone selection and labels via UI components, then creates the tunnel and routes DNS for the declared zones.
|
|
49
49
|
|
|
50
|
-
**
|
|
50
|
+
**Diagnostic flow:** `cf-verify` audits every relevant Cloudflare artefact and tags each as IN-SCOPE / OUT-OF-SCOPE / MISSING against the brand manifest and account binding. Non-mutating; safe to run at any time, including before login.
|
|
51
51
|
|
|
52
|
-
**
|
|
52
|
+
**Recovery flow:** `cf-rebuild` discards out-of-scope artefacts and reconstructs the declared state. Idempotent. Refuses to delete cert.pem when bound to the wrong account; halts with an actionable instruction to run `tunnel-login force=true`. Pass `dryRun=true` to preview.
|
|
53
53
|
|
|
54
|
-
**
|
|
54
|
+
**DNS lookups:** `dns-lookup` for hostname resolution. Nameserver-not-yet-propagated is the most common operator issue; `cf-zone-status` reports activation status.
|
|
55
55
|
|
|
56
|
-
**
|
|
56
|
+
**Alias domains:** `tunnel-add-hostname` registers an additional declared zone as an alias on an existing tunnel. The hostname must still be in scope per `brand.cloudflare.zones`.
|
|
57
|
+
|
|
58
|
+
**User-facing language:** Say "connection" not "certificate", "domain" not "zone", "address" not "hostname". No Cloudflare internal terminology.
|
|
59
|
+
|
|
60
|
+
**Verification:** Always verify URLs work by navigating to them in the browser. Never claim a URL works without browser verification.
|
|
57
61
|
|
|
58
62
|
## Telegram
|
|
59
63
|
|