@rubytech/create-sitedesk-code 0.1.606 → 0.1.608

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.
Files changed (68) hide show
  1. package/dist/index.js +40 -1
  2. package/package.json +1 -1
  3. package/payload/platform/lib/admins-write/vitest.config.ts +1 -0
  4. package/payload/platform/lib/agent-dispatch-rule/vitest.config.ts +1 -0
  5. package/payload/platform/lib/brand-templating/vitest.config.ts +1 -0
  6. package/payload/platform/lib/canonical-instant/vitest.config.ts +1 -0
  7. package/payload/platform/lib/dispatch-read/vitest.config.ts +1 -0
  8. package/payload/platform/lib/graph-search/vitest.config.ts +1 -0
  9. package/payload/platform/lib/graph-style/vitest.config.ts +1 -0
  10. package/payload/platform/lib/mcp-lifeline/vitest.config.ts +1 -0
  11. package/payload/platform/lib/routine-templates/vitest.config.ts +1 -0
  12. package/payload/platform/lib/task-secrets/vitest.config.ts +1 -0
  13. package/payload/platform/lib/telegram-button-labels/vitest.config.ts +1 -0
  14. package/payload/platform/lib/telegram-managed-bot/vitest.config.ts +1 -0
  15. package/payload/platform/lib/telegram-media/vitest.config.ts +1 -0
  16. package/payload/platform/lib/telegram-reach/vitest.config.ts +1 -0
  17. package/payload/platform/lib/telegram-store-read/vitest.config.ts +1 -0
  18. package/payload/platform/plugins/admin/mcp/vitest.config.ts +1 -0
  19. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +39 -2
  20. package/payload/platform/plugins/admin/skills/whats-new/SKILL.md +10 -0
  21. package/payload/platform/plugins/aeo/mcp/vitest.config.ts +1 -0
  22. package/payload/platform/plugins/cloudflare/mcp/vitest.config.ts +1 -0
  23. package/payload/platform/plugins/connector/mcp/vitest.config.ts +1 -0
  24. package/payload/platform/plugins/contacts/mcp/vitest.config.ts +1 -0
  25. package/payload/platform/plugins/docs/references/telegram-guide.md +38 -1
  26. package/payload/platform/plugins/email/mcp/vitest.config.ts +1 -0
  27. package/payload/platform/plugins/filesystem/mcp/vitest.config.ts +1 -0
  28. package/payload/platform/plugins/graph-viewer/mcp/vitest.config.ts +1 -0
  29. package/payload/platform/plugins/memory/mcp/vitest.config.ts +1 -0
  30. package/payload/platform/plugins/scheduling/mcp/vitest.config.ts +1 -0
  31. package/payload/platform/plugins/storage-broker/mcp/vitest.config.ts +6 -1
  32. package/payload/platform/plugins/telegram/PLUGIN.md +6 -2
  33. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-tool.test.js +35 -3
  34. package/payload/platform/plugins/telegram/mcp/dist/__tests__/card-tool.test.js.map +1 -1
  35. package/payload/platform/plugins/telegram/mcp/dist/__tests__/instruct-tool.test.d.ts +2 -0
  36. package/payload/platform/plugins/telegram/mcp/dist/__tests__/instruct-tool.test.d.ts.map +1 -0
  37. package/payload/platform/plugins/telegram/mcp/dist/__tests__/instruct-tool.test.js +93 -0
  38. package/payload/platform/plugins/telegram/mcp/dist/__tests__/instruct-tool.test.js.map +1 -0
  39. package/payload/platform/plugins/telegram/mcp/dist/index.js +20 -0
  40. package/payload/platform/plugins/telegram/mcp/dist/index.js.map +1 -1
  41. package/payload/platform/plugins/telegram/mcp/dist/lib/public-pin.d.ts.map +1 -1
  42. package/payload/platform/plugins/telegram/mcp/dist/lib/public-pin.js +7 -0
  43. package/payload/platform/plugins/telegram/mcp/dist/lib/public-pin.js.map +1 -1
  44. package/payload/platform/plugins/telegram/mcp/dist/tools/card.d.ts.map +1 -1
  45. package/payload/platform/plugins/telegram/mcp/dist/tools/card.js +12 -5
  46. package/payload/platform/plugins/telegram/mcp/dist/tools/card.js.map +1 -1
  47. package/payload/platform/plugins/telegram/mcp/dist/tools/instruct.d.ts +56 -0
  48. package/payload/platform/plugins/telegram/mcp/dist/tools/instruct.d.ts.map +1 -0
  49. package/payload/platform/plugins/telegram/mcp/dist/tools/instruct.js +91 -0
  50. package/payload/platform/plugins/telegram/mcp/dist/tools/instruct.js.map +1 -0
  51. package/payload/platform/plugins/telegram/mcp/vitest.config.ts +1 -0
  52. package/payload/platform/plugins/url-get/mcp/vitest.config.ts +1 -0
  53. package/payload/platform/plugins/whatsapp/mcp/vitest.config.ts +1 -0
  54. package/payload/platform/scripts/repair-misfiled-card-rows.sh +276 -0
  55. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  56. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
  57. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  58. package/payload/platform/services/claude-session-manager/vitest.config.ts +1 -1
  59. package/payload/platform/services/telegram-channel/dist/instructions.d.ts +1 -0
  60. package/payload/platform/services/telegram-channel/dist/instructions.d.ts.map +1 -1
  61. package/payload/platform/services/telegram-channel/dist/instructions.js +23 -0
  62. package/payload/platform/services/telegram-channel/dist/instructions.js.map +1 -1
  63. package/payload/platform/services/telegram-channel/dist/notification.d.ts +22 -7
  64. package/payload/platform/services/telegram-channel/dist/notification.d.ts.map +1 -1
  65. package/payload/platform/services/telegram-channel/dist/notification.js +17 -1
  66. package/payload/platform/services/telegram-channel/dist/notification.js.map +1 -1
  67. package/payload/platform/test/tmpdir-setup.ts +54 -0
  68. package/payload/server/server.js +1488 -1091
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Task 2724 — tell one of this account's PUBLIC Telegram agents what to say to a
3
+ * visitor it is already talking to.
4
+ *
5
+ * WHY IT EXISTS. An operator who corrects a visitor directly is speaking from
6
+ * their OWN session, and a card sent from one session never enters another
7
+ * session's context: nothing seeds a session from the message store. On
8
+ * 2026-08-15 the admin door corrected a visitor and the public agent quoted the
9
+ * wrong price again 97 seconds later, because the correction never reached the
10
+ * agent that was talking to them.
11
+ *
12
+ * WHY IT IS A THIN CLIENT. Every decision belongs to the platform, not here. The
13
+ * bot registry, whether the agent is active, whether the chat is a business
14
+ * chat, whether a broadcast chat is allowlisted, and which session the chat
15
+ * resolves to are all facts the UI process holds; a second copy of any of them
16
+ * in this plugin would be a second authority that could disagree. This posts
17
+ * three fields and relays the verdict.
18
+ *
19
+ * ADMIN DOOR ONLY. The name is in `OFFERED_TOOLS` and in neither
20
+ * `PUBLIC_VISIBLE_TOOLS` nor `PINNED_TOOLS`, so a public spawn never sees it. It
21
+ * is deliberately NOT pinned: `runPinned` substitutes the spawn's own bot and
22
+ * chat, which for this tool would turn every instruction into the agent
23
+ * instructing itself.
24
+ */
25
+ const TAG = "[telegram-instruct]";
26
+ const TOOL = "telegram-instruct";
27
+ export async function telegramInstruct(p, deps) {
28
+ // Refused here rather than at the route, because a blank instruction would
29
+ // otherwise spend a round trip to be told what this call already knows.
30
+ if (p.instruction.trim().length === 0) {
31
+ deps.log(`${TAG} op=call tool=${TOOL} accepted=no reason=blank-instruction`);
32
+ return {
33
+ isError: true,
34
+ text: "An instruction cannot be blank. Say what the agent should do or tell the visitor.",
35
+ };
36
+ }
37
+ if (!deps.port) {
38
+ deps.log(`${TAG} op=call tool=${TOOL} accepted=no reason=no-platform-port`);
39
+ return {
40
+ isError: true,
41
+ text: "telegram-instruct cannot reach this install's own server: no platform port is set for " +
42
+ "this session. Instructing a public agent needs the running server, so nothing was sent.",
43
+ };
44
+ }
45
+ let res;
46
+ try {
47
+ res = await deps.fetchImpl(`http://127.0.0.1:${deps.port}/api/channel/operator-inject`, {
48
+ method: "POST",
49
+ headers: { "content-type": "application/json" },
50
+ body: JSON.stringify({ botId: p.botId, chatId: p.chatId, instruction: p.instruction }),
51
+ });
52
+ }
53
+ catch (err) {
54
+ const reason = err instanceof Error ? err.message : String(err);
55
+ deps.log(`${TAG} op=call tool=${TOOL} accepted=no reason=unreachable`);
56
+ return {
57
+ isError: true,
58
+ text: `telegram-instruct could not reach this install's own server: ${reason}. Nothing was sent.`,
59
+ };
60
+ }
61
+ let body = {};
62
+ try {
63
+ body = ((await res.json()) ?? {});
64
+ }
65
+ catch {
66
+ // A body that will not parse is not a reason to invent one. The status is
67
+ // what is actually known, so the status is what is reported.
68
+ body = {};
69
+ }
70
+ if (!res.ok || body.ok !== true) {
71
+ // The route's `detail` is written for the operator and says what to do next,
72
+ // so it is relayed as-is. `error` is the fallback because a machine code
73
+ // still names the refusal; the status is the last resort.
74
+ const detail = typeof body.detail === "string" && body.detail.length > 0
75
+ ? body.detail
76
+ : typeof body.error === "string" && body.error.length > 0
77
+ ? `The server refused the instruction: ${body.error}.`
78
+ : `The server refused the instruction (status ${res.status}).`;
79
+ deps.log(`${TAG} op=call tool=${TOOL} accepted=no reason=${typeof body.error === "string" && body.error.length > 0 ? body.error : `status-${res.status}`}`);
80
+ return { isError: true, text: `${detail} Nothing was sent to the visitor.` };
81
+ }
82
+ const sessionId = typeof body.sessionId === "string" ? body.sessionId : "unknown";
83
+ deps.log(`${TAG} op=call tool=${TOOL} accepted=yes sessionId=${sessionId}`);
84
+ return {
85
+ text: `The instruction is running inside that visitor's own conversation with the agent ` +
86
+ `(session ${sessionId}). The agent writes the message to the visitor itself, in its own ` +
87
+ `words, and its context now holds what it said, so it will not contradict this on the ` +
88
+ `next message. Nothing further is needed from you.`,
89
+ };
90
+ }
91
+ //# sourceMappingURL=instruct.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instruct.js","sourceRoot":"","sources":["../../src/tools/instruct.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { defineConfig } from "vitest/config";
2
2
 
3
3
  export default defineConfig({
4
4
  test: {
5
+ setupFiles: ["../../../test/tmpdir-setup.ts"],
5
6
  environment: "node",
6
7
  // Scoped to src, matching whatsapp/mcp and nine other plugin MCPs. Without
7
8
  // it vitest also collects dist/__tests__/*.test.js, which `tsc -p` emits
@@ -7,6 +7,7 @@ import { defineConfig } from "vitest/config";
7
7
  // and this flag becomes a no-op.
8
8
  export default defineConfig({
9
9
  test: {
10
+ setupFiles: ["../../../test/tmpdir-setup.ts"],
10
11
  environment: "node",
11
12
  include: ["src/**/__tests__/**/*.test.ts"],
12
13
  passWithNoTests: true,
@@ -2,6 +2,7 @@ import { defineConfig } from "vitest/config";
2
2
 
3
3
  export default defineConfig({
4
4
  test: {
5
+ setupFiles: ["../../../test/tmpdir-setup.ts"],
5
6
  environment: "node",
6
7
  include: ["src/**/__tests__/**/*.test.ts"],
7
8
  testTimeout: 10_000,
@@ -0,0 +1,276 @@
1
+ #!/usr/bin/env bash
2
+ # ============================================================
3
+ # repair-misfiled-card-rows.sh
4
+ #
5
+ # Purpose
6
+ # -------
7
+ # Move telegram card rows that were filed in the SENDING conversation into
8
+ # the conversation the card was actually sent to.
9
+ #
10
+ # Until the follower learned to read the card's own destination, it keyed
11
+ # every card store row on the session's own channel key. A card the admin
12
+ # door sent into another chat therefore landed in the admin's own
13
+ # conversation file: the recipient's conversation showed nothing, and the
14
+ # admin's showed a message addressed to somebody else.
15
+ #
16
+ # A misfiled row does not record its true destination, so no rule recovers
17
+ # one. This script is therefore an EXPLICIT MAPPING of the rows whose
18
+ # destination is known from the session transcript, not a migration. Rows
19
+ # outside the mapping are never touched, whatever they look like.
20
+ #
21
+ # What it does (idempotent; re-running after a successful apply is a no-op)
22
+ # detect find each mapped row in the source file
23
+ # move remove it from the source, insert it into the target in
24
+ # dateSent order, rewriting messageId, channelKey, chatId and
25
+ # senderId to the destination and leaving body, buttons,
26
+ # dateSent and sessionId exactly as they were
27
+ # gate re-count both files; a row left behind is a non-zero exit
28
+ #
29
+ # An `update` row (a card edit) moves with its message row, and its
30
+ # targetMessageId is rewritten to the moved row's new messageId — the row
31
+ # id embeds the channel key, so an unrewritten patch would point at an id
32
+ # that no longer exists anywhere.
33
+ #
34
+ # Usage
35
+ # bash repair-misfiled-card-rows.sh # dry-run (default)
36
+ # bash repair-misfiled-card-rows.sh --dry-run
37
+ # bash repair-misfiled-card-rows.sh --apply
38
+ # bash repair-misfiled-card-rows.sh --brand=maxy-code --apply
39
+ # bash repair-misfiled-card-rows.sh --store=/path/to/dir --apply
40
+ #
41
+ # --dry-run Report what would move; mutate nothing (default).
42
+ # --apply Perform the moves, then re-check both files.
43
+ # --brand Brand whose store to repair. Auto-detected when only one
44
+ # ~/.<brand>/data/telegram-messages exists.
45
+ # --store An explicit store directory (the per-account one, holding the
46
+ # .jsonl conversation files). Overrides --brand. For rehearsing
47
+ # against copies before touching the live store.
48
+ # --force Proceed under --apply even though the brand service is running.
49
+ #
50
+ # Removing a line is a whole-file rewrite, and the follower appends to
51
+ # these files, so --apply refuses while the brand service is active. The
52
+ # reader streams byte offsets as SSE resume ids, so a concurrent append
53
+ # during the rewrite would be lost outright.
54
+ # ============================================================
55
+
56
+ set -euo pipefail
57
+
58
+ BRAND=""
59
+ STORE=""
60
+ MODE="dry-run"
61
+ FORCE="no"
62
+
63
+ while [ $# -gt 0 ]; do
64
+ case "$1" in
65
+ --brand=*) BRAND="${1#*=}"; shift ;;
66
+ --brand) BRAND="${2:?--brand requires a value}"; shift 2 ;;
67
+ --store=*) STORE="${1#*=}"; shift ;;
68
+ --store) STORE="${2:?--store requires a value}"; shift 2 ;;
69
+ --dry-run) MODE="dry-run"; shift ;;
70
+ --apply) MODE="apply"; shift ;;
71
+ --force) FORCE="yes"; shift ;;
72
+ -h|--help)
73
+ sed -n '2,/^# =\{20,\}/p' "$0" | sed 's/^# \{0,1\}//'
74
+ exit 0
75
+ ;;
76
+ *) echo "Unknown arg: $1" >&2; exit 2 ;;
77
+ esac
78
+ done
79
+
80
+ log() { echo "[card-repair] $*" >&2; }
81
+
82
+ ACCOUNT="5bc2c0e2-206c-4fee-b274-d87736b4fce1"
83
+ SOURCE_KEY="8711566959:8992591236"
84
+
85
+ # The mapping. One line per row that moves: <card id> <destination channel key>.
86
+ # Both rows carrying `card:96` — the message and its edit — move together,
87
+ # because the mapping is keyed on the card, not on the line.
88
+ MAPPING="163 8850966445:8545731367
89
+ 166 8850966445:8545731367
90
+ 96 8804050655:8711445925"
91
+
92
+ # --- Store resolution ------------------------------------------------
93
+ if [ -z "$STORE" ]; then
94
+ if [ -z "$BRAND" ]; then
95
+ candidates=()
96
+ for d in "$HOME"/.*; do
97
+ [ -d "$d/data/telegram-messages" ] || continue
98
+ candidates+=("$(basename "$d" | sed 's/^\.//')")
99
+ done
100
+ if [ "${#candidates[@]}" -eq 1 ]; then
101
+ BRAND="${candidates[0]}"
102
+ elif [ "${#candidates[@]}" -gt 1 ]; then
103
+ echo "Error: multiple brands with a telegram store (${candidates[*]}); pass --brand=NAME" >&2
104
+ exit 1
105
+ else
106
+ echo "Error: no telegram store under $HOME/.<brand>/data/telegram-messages" >&2
107
+ exit 1
108
+ fi
109
+ fi
110
+ STORE="$HOME/.$BRAND/data/telegram-messages/$ACCOUNT"
111
+ fi
112
+
113
+ if [ ! -d "$STORE" ]; then
114
+ echo "Error: store directory not found: $STORE" >&2
115
+ exit 1
116
+ fi
117
+ log "store=$STORE mode=$MODE"
118
+
119
+ # --- Service gate ----------------------------------------------------
120
+ # Only when repairing a live brand store: a --store run is a rehearsal
121
+ # against copies and has no service to collide with.
122
+ if [ "$MODE" = "apply" ] && [ -n "$BRAND" ] && [ "$FORCE" = "no" ]; then
123
+ if command -v systemctl >/dev/null 2>&1 && systemctl --user is-active --quiet "$BRAND.service"; then
124
+ echo "Error: $BRAND.service is running. Stop it first:" >&2
125
+ echo " systemctl --user stop $BRAND.service" >&2
126
+ echo "The follower appends to these files and removing a row rewrites them." >&2
127
+ exit 1
128
+ fi
129
+ fi
130
+
131
+ stem() { echo "$1" | tr ':' '_'; }
132
+
133
+ SRC_FILE="$STORE/$(stem "$SOURCE_KEY").jsonl"
134
+ if [ ! -f "$SRC_FILE" ]; then
135
+ echo "Error: source conversation file not found: $SRC_FILE" >&2
136
+ exit 1
137
+ fi
138
+
139
+ # --- The move --------------------------------------------------------
140
+ # Python because every step is a JSON rewrite: the row id embeds the channel
141
+ # key, the insert position is by dateSent, and an update row has to follow
142
+ # its message row. Three jq invocations chained through sed would be the
143
+ # same work with no way to keep the two rows consistent.
144
+ export CARD_REPAIR_STORE="$STORE"
145
+ export CARD_REPAIR_ACCOUNT="$ACCOUNT"
146
+ export CARD_REPAIR_SOURCE_KEY="$SOURCE_KEY"
147
+ export CARD_REPAIR_MAPPING="$MAPPING"
148
+ export CARD_REPAIR_MODE="$MODE"
149
+
150
+ python3 - <<'PY'
151
+ import json, os, sys
152
+
153
+ store = os.environ["CARD_REPAIR_STORE"]
154
+ account = os.environ["CARD_REPAIR_ACCOUNT"]
155
+ source_key = os.environ["CARD_REPAIR_SOURCE_KEY"]
156
+ apply_it = os.environ["CARD_REPAIR_MODE"] == "apply"
157
+ mapping = {}
158
+ for line in os.environ["CARD_REPAIR_MAPPING"].strip().splitlines():
159
+ card_id, dest_key = line.split()
160
+ mapping[card_id] = dest_key
161
+
162
+ def path(key):
163
+ return os.path.join(store, key.replace(":", "_") + ".jsonl")
164
+
165
+ def read(p):
166
+ if not os.path.exists(p):
167
+ return []
168
+ rows = []
169
+ with open(p, encoding="utf-8") as fh:
170
+ for line in fh:
171
+ if line.strip():
172
+ rows.append(json.loads(line))
173
+ return rows
174
+
175
+ def row_id(key, card_id):
176
+ return f"telegram:{account}:{key}:card:{card_id}"
177
+
178
+ src_path = path(source_key)
179
+ src_rows = read(src_path)
180
+
181
+ # Group the source's lines: which stay, and which move with which card.
182
+ staying = []
183
+ moving = {card_id: [] for card_id in mapping}
184
+ for row in src_rows:
185
+ matched = None
186
+ for card_id in mapping:
187
+ wanted = row_id(source_key, card_id)
188
+ ident = row.get("targetMessageId") if row.get("kind") == "update" else row.get("messageId")
189
+ if ident == wanted:
190
+ matched = card_id
191
+ break
192
+ if matched is None:
193
+ staying.append(row)
194
+ else:
195
+ moving[matched].append(row)
196
+
197
+ total = sum(len(v) for v in moving.values())
198
+ if total == 0:
199
+ print("[card-repair] nothing to move — the source holds none of the mapped rows", file=sys.stderr)
200
+ sys.exit(0)
201
+
202
+ for card_id, rows in moving.items():
203
+ dest_key = mapping[card_id]
204
+ kinds = ", ".join("update" if r.get("kind") == "update" else "message" for r in rows)
205
+ print(
206
+ f"[card-repair] card:{card_id} {len(rows)} row(s) [{kinds}] {source_key} -> {dest_key}",
207
+ file=sys.stderr,
208
+ )
209
+
210
+ if not apply_it:
211
+ print("[card-repair] dry-run — nothing written. Re-run with --apply.", file=sys.stderr)
212
+ sys.exit(0)
213
+
214
+ # Rewrite each moving row for its new home. dateSent, body, buttons and
215
+ # sessionId are carried across untouched: the row is the same message, filed
216
+ # where it belongs.
217
+ per_dest = {}
218
+ for card_id, rows in moving.items():
219
+ dest_key = mapping[card_id]
220
+ _, chat = dest_key.split(":", 1)
221
+ for row in rows:
222
+ out = dict(row)
223
+ if out.get("kind") == "update":
224
+ out["targetMessageId"] = row_id(dest_key, card_id)
225
+ else:
226
+ out["messageId"] = row_id(dest_key, card_id)
227
+ out["channelKey"] = dest_key
228
+ out["chatId"] = chat
229
+ out["senderId"] = chat
230
+ per_dest.setdefault(dest_key, []).append(out)
231
+
232
+ def sort_key(row):
233
+ # Message rows order by dateSent, which is what the reader sorts on. An
234
+ # update row carries no dateSent and must land after its target, so it
235
+ # borrows the target's stamp and breaks the tie in its own favour.
236
+ if row.get("kind") == "update":
237
+ return (row.get("createdAt", ""), 1)
238
+ return (row.get("dateSent", ""), 0)
239
+
240
+ for dest_key, new_rows in per_dest.items():
241
+ dest_path = path(dest_key)
242
+ existing = read(dest_path)
243
+ have = {r.get("messageId") for r in existing if r.get("kind") != "update"}
244
+ fresh = [r for r in new_rows if r.get("kind") == "update" or r.get("messageId") not in have]
245
+ merged = sorted(existing + fresh, key=sort_key)
246
+ tmp = dest_path + ".repair-tmp"
247
+ with open(tmp, "w", encoding="utf-8") as fh:
248
+ for r in merged:
249
+ fh.write(json.dumps(r, ensure_ascii=False) + "\n")
250
+ os.replace(tmp, dest_path)
251
+ print(f"[card-repair] wrote {len(fresh)} row(s) into {os.path.basename(dest_path)}", file=sys.stderr)
252
+
253
+ tmp = src_path + ".repair-tmp"
254
+ with open(tmp, "w", encoding="utf-8") as fh:
255
+ for r in staying:
256
+ fh.write(json.dumps(r, ensure_ascii=False) + "\n")
257
+ os.replace(tmp, src_path)
258
+ print(f"[card-repair] removed {total} row(s) from {os.path.basename(src_path)}", file=sys.stderr)
259
+ PY
260
+
261
+ # --- Gate ------------------------------------------------------------
262
+ # Only under --apply: a dry-run moved nothing and would fail every check.
263
+ if [ "$MODE" = "apply" ]; then
264
+ fail=0
265
+ while read -r card_id dest_key; do
266
+ [ -n "$card_id" ] || continue
267
+ src_left=$(grep -c ":$SOURCE_KEY:card:$card_id\"" "$SRC_FILE" || true)
268
+ dest_file="$STORE/$(stem "$dest_key").jsonl"
269
+ dest_have=$(grep -c ":$dest_key:card:$card_id\"" "$dest_file" || true)
270
+ log "gate card:$card_id source=$src_left target=$dest_have"
271
+ [ "$src_left" -eq 0 ] || { log "FAIL card:$card_id still in the source"; fail=1; }
272
+ [ "$dest_have" -ge 1 ] || { log "FAIL card:$card_id absent from the target"; fail=1; }
273
+ done <<< "$MAPPING"
274
+ [ "$fail" -eq 0 ] || exit 1
275
+ log "done — every mapped row is in its target conversation"
276
+ fi
@@ -1 +1 @@
1
- {"version":3,"file":"canonical-tool-names.generated.d.ts","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"AAQA,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EA2B7C,CAAA;AAED,gEAAgE;AAChE,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAqXtD,CAAA"}
1
+ {"version":3,"file":"canonical-tool-names.generated.d.ts","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"AAQA,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EA2B7C,CAAA;AAED,gEAAgE;AAChE,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAsXtD,CAAA"}
@@ -359,6 +359,7 @@ export const CANONICAL_MAXY_TOOL_NAMES = [
359
359
  "mcp__plugin_telegram_telegram__telegram-ask",
360
360
  "mcp__plugin_telegram_telegram__telegram-bot-provision",
361
361
  "mcp__plugin_telegram_telegram__telegram-card",
362
+ "mcp__plugin_telegram_telegram__telegram-instruct",
362
363
  "mcp__plugin_telegram_telegram__telegram-live-location",
363
364
  "mcp__plugin_telegram_telegram__telegram-media-fetch",
364
365
  "mcp__plugin_telegram_telegram__telegram-media-send",
@@ -1 +1 @@
1
- {"version":3,"file":"canonical-tool-names.generated.js","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"canonical-tool-names.generated.js","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,6 @@ import { defineConfig } from 'vitest/config'
9
9
 
10
10
  export default defineConfig({
11
11
  test: {
12
- setupFiles: ['./src/__tests__/helpers/env-setup.ts'],
12
+ setupFiles: ['../../test/tmpdir-setup.ts', './src/__tests__/helpers/env-setup.ts'],
13
13
  },
14
14
  })
@@ -14,6 +14,7 @@ export type TelegramChannelRole = 'admin' | 'public';
14
14
  * Both spawn paths stamp the env, so an absent or unrecognised value means the
15
15
  * spawn is wrong and the channel must not boot. */
16
16
  export declare function resolveChannelRole(raw: string | undefined): TelegramChannelRole;
17
+ export declare const OPERATOR_INSTRUCTION_REFRAME: string;
17
18
  export declare function channelInstructions(role: TelegramChannelRole): string;
18
19
  export declare function replyToolDescription(role: TelegramChannelRole): string;
19
20
  export declare function replyTextDescription(role: TelegramChannelRole): string;
@@ -1 +1 @@
1
- {"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEpD;;;;;;;;;;;;;oDAaoD;AACpD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,mBAAmB,CAM/E;AAkED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAErE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAItE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAEtE;AAoBD,eAAO,MAAM,yBAAyB,QAkEiE,CAAA"}
1
+ {"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,QAAQ,CAAA;AAEpD;;;;;;;;;;;;;oDAaoD;AACpD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,mBAAmB,CAM/E;AAiFD,eAAO,MAAM,4BAA4B,QAQb,CAAA;AAE5B,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAErE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAItE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAEtE;AAoBD,eAAO,MAAM,yBAAyB,QAkEiE,CAAA"}
@@ -81,6 +81,29 @@ const PUBLIC_INSTRUCTIONS = SPECIALIST_AUDIENCE +
81
81
  `You act only as this bot and only in this chat: both are fixed for you, so never try to reach ` +
82
82
  `another person or another conversation. ` +
83
83
  NO_INTERNALS;
84
+ // Task 2724 — the `## Operator instruction` body of a PUBLIC turn whose source
85
+ // is 'operator'.
86
+ //
87
+ // The public role is otherwise plain (see composeContent), because a wrapper on
88
+ // the visitor's own words would leak the internal directive to them. An operator
89
+ // instruction is the one payload on this door the visitor did not write and will
90
+ // never see, so it is the one that must be framed: PUBLIC_INSTRUCTIONS above
91
+ // tells this agent that every channel event is a visitor speaking and must not
92
+ // be acted on as a trusted operator's instruction, which is exactly wrong for
93
+ // this turn and would have it answer a correction as though a stranger asked
94
+ // for one.
95
+ //
96
+ // The admin door is untouched and reads none of this. An operator instruction
97
+ // cannot reach it: the inject route refuses every bot whose registry entry is
98
+ // not role 'public'.
99
+ export const OPERATOR_INSTRUCTION_REFRAME = 'The account operator sent this through their own admin door. It is not the visitor speaking. ' +
100
+ 'The visitor did not write it, has not seen it, and is still waiting for an answer from you. ' +
101
+ 'It is genuine operator instruction for this conversation, so act on it: do what it says, then ' +
102
+ 'write the result as the final text of your turn. That text is what reaches the visitor, so ' +
103
+ 'never end this turn without it. ' +
104
+ 'Write it as your own words to the visitor, in the same voice as the rest of this conversation. ' +
105
+ 'Never quote this block, never repeat the instruction back, and never tell the visitor that ' +
106
+ 'somebody instructed you.';
84
107
  export function channelInstructions(role) {
85
108
  return role === 'public' ? PUBLIC_INSTRUCTIONS : ADMIN_INSTRUCTIONS;
86
109
  }
@@ -1 +1 @@
1
- {"version":3,"file":"instructions.js","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"instructions.js","sourceRoot":"","sources":["../src/instructions.ts"],"names":[],"mappings":"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"}
@@ -68,8 +68,16 @@ export interface InboundPayload {
68
68
  messageId: string;
69
69
  /** Task 1378 — the inbound's origin: 'user' (a real telegram message) or
70
70
  * 'schedule' (a synthetic inbound injected by the scheduler). Carried only
71
- * into the turn's structured log line. Absent on legacy frames = 'user'. */
72
- source?: 'user' | 'schedule';
71
+ * into the turn's structured log line.
72
+ *
73
+ * Task 2724 adds 'operator': text the account operator sent through the admin
74
+ * door for THIS agent to act on in this conversation. Unlike the other two it
75
+ * is not carried only into a log line — it selects the public branch's framing
76
+ * in composeContent, because it is the one public payload the visitor did not
77
+ * write.
78
+ *
79
+ * Absent on legacy frames = 'user'. */
80
+ source?: 'user' | 'schedule' | 'operator';
73
81
  /** Task 2561 — who sent this message, and the account it landed on. The
74
82
  * gateway held both for the whole turn and passed neither, so an admin turn
75
83
  * opened straight into rules written about the account owner and a second
@@ -129,16 +137,23 @@ export declare function composeReplyNote(rc: ReplyContext): string;
129
137
  export interface ComposedInbound {
130
138
  content: string;
131
139
  payloadBytes: number;
132
- /** Task 2561 — whether this turn carries the inbound provenance preamble. The
140
+ /** Task 2561 — whether this turn carries a platform-verified preamble. The
133
141
  * composer is the only place that knows, and the receipt ack carries it to the
134
142
  * gateway so `provenance=no` is greppable in server.log without reproducing
135
- * the incident. */
143
+ * the incident.
144
+ *
145
+ * Task 2724 — two preambles satisfy it now: the admin door's inbound
146
+ * provenance block, and the public door's operator instruction block. Both
147
+ * are platform-stamped and neither can be produced by an inbound message,
148
+ * which is the property this flag reports. */
136
149
  provenance: boolean;
137
150
  /** Task 2353 — where this turn's `## Instruction` body came from. 'platform' is
138
- * this service's own constant, which is every admin turn on this door and
151
+ * this service's own admin constant, which is every admin turn on this door and
139
152
  * cannot fail; 'public-plain' is the public role, which carries no instruction
140
- * block at all. There is no 'absent': this door reads no file. */
141
- instructionSource: 'platform' | 'public-plain';
153
+ * block at all. Task 2724 adds 'operator': the public role carrying the
154
+ * operator-instruction constant, the one public turn that IS framed. There is
155
+ * no 'absent': this door reads no file. */
156
+ instructionSource: 'platform' | 'public-plain' | 'operator';
142
157
  }
143
158
  export declare function composeContent(p: InboundPayload, role: TelegramChannelRole): ComposedInbound;
144
159
  /** Defence in depth: this server serves exactly one key. Even though the
@@ -1 +1 @@
1
- {"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../src/notification.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../src/notification.ts"],"names":[],"mappings":"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"}
@@ -21,7 +21,7 @@
21
21
  // Task 2364 — a type-only import from this package's own turn follower, so the
22
22
  // turn-end body and the counts it carries have one definition. Type-only, so it
23
23
  // erases at build and this file still pulls in no runtime dependency.
24
- import { ADMIN_REFRAME_INSTRUCTION } from './instructions.js';
24
+ import { ADMIN_REFRAME_INSTRUCTION, OPERATOR_INSTRUCTION_REFRAME, } from './instructions.js';
25
25
  /**
26
26
  * Task 1516 — render the dispatcher's operator-provenance as a platform-verified
27
27
  * preamble. Every value is dispatcher-stamped (an inbound message cannot produce
@@ -132,6 +132,22 @@ export function composeContent(p, role) {
132
132
  const payload = composePayload(p);
133
133
  const payloadBytes = Buffer.byteLength(payload, 'utf8');
134
134
  if (role !== 'admin') {
135
+ // Task 2724 — an operator instruction is the one public payload the visitor
136
+ // did not write, so it is the one that gets framed. Everything else on this
137
+ // branch stays plain, for the reason this function's header gives.
138
+ //
139
+ // `payloadBytes` stays the INNER length on this branch too, matching the
140
+ // admin branch and every pre-2724 public turn: the `[reframe]` line measures
141
+ // what the person sent, never what the platform wrapped around it.
142
+ if (p.source === 'operator') {
143
+ return {
144
+ content: `## Operator instruction (platform-verified)\n${OPERATOR_INSTRUCTION_REFRAME}\n\n` +
145
+ `## What the operator asked for\n${payload}`,
146
+ payloadBytes,
147
+ provenance: true,
148
+ instructionSource: 'operator',
149
+ };
150
+ }
135
151
  return { content: payload, payloadBytes, provenance: false, instructionSource: 'public-plain' };
136
152
  }
137
153
  // Task 1516 — a scheduled turn opens with the platform-verified provenance