instar 1.3.33 → 1.3.35
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/dist/messaging/AgentTelegramComms.d.ts +77 -0
- package/dist/messaging/AgentTelegramComms.d.ts.map +1 -1
- package/dist/messaging/AgentTelegramComms.js +108 -0
- package/dist/messaging/AgentTelegramComms.js.map +1 -1
- package/dist/messaging/TelegramAdapter.d.ts +12 -1
- package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
- package/dist/messaging/TelegramAdapter.js +28 -7
- package/dist/messaging/TelegramAdapter.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/1.3.34.md +37 -0
- package/upgrades/1.3.35.md +44 -0
- package/upgrades/side-effects/agent-telegram-comms-send.md +71 -0
- package/upgrades/side-effects/telegram-adapter-multi-instance.md +61 -0
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-05-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-05-27T23:05:08.677Z",
|
|
5
|
+
"instarVersion": "1.3.35",
|
|
6
6
|
"entryCount": 192,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Instar Upgrade Guide — NEXT
|
|
2
|
+
|
|
3
|
+
<!-- bump: patch -->
|
|
4
|
+
|
|
5
|
+
## What Changed
|
|
6
|
+
|
|
7
|
+
**TelegramAdapter can now run a second bot cleanly (groundwork for agent-to-agent Telegram
|
|
8
|
+
comms).** Two internal additions, both shipping dark (nothing uses them yet): (1) a
|
|
9
|
+
non-primary Telegram adapter can namespace its own state files under a sub-directory, so two
|
|
10
|
+
bots in one process never clobber each other's poll-offset / registry / message-log /
|
|
11
|
+
attention files; and (2) inbound Telegram messages now expose whether the sender is a bot
|
|
12
|
+
(`is_bot`) and any `sender_chat` — the structural input a later update uses to tell an
|
|
13
|
+
agent-sent message from a human typing the same text. The primary bot's behavior and state
|
|
14
|
+
paths are byte-for-byte unchanged.
|
|
15
|
+
|
|
16
|
+
## What to Tell Your User
|
|
17
|
+
|
|
18
|
+
- Nothing changes in how your agent behaves today — this is plumbing for a later feature
|
|
19
|
+
(agents messaging each other over Telegram). Your agent's own Telegram keeps working
|
|
20
|
+
exactly as before.
|
|
21
|
+
|
|
22
|
+
## Summary of New Capabilities
|
|
23
|
+
|
|
24
|
+
| Capability | How to Use |
|
|
25
|
+
|-----------|-----------|
|
|
26
|
+
| Multi-instance `TelegramAdapter` | Internal — `new TelegramAdapter(cfg, stateDir, { subDir, suppressLifelineAutoCreate })`; primary (no opts) unchanged |
|
|
27
|
+
| Sender-identity on inbound messages | Internal — `message.from.is_bot` + `message.sender_chat` exposed on the update type |
|
|
28
|
+
|
|
29
|
+
## Evidence
|
|
30
|
+
|
|
31
|
+
**Net-new groundwork, not a bug fix.** Proven by a dedicated test asserting the load-bearing
|
|
32
|
+
safety property — a PRIMARY adapter's four state-file paths are byte-for-byte the historical
|
|
33
|
+
`{stateDir}/...` values (this code runs the agent's own Telegram, so an unchanged primary is
|
|
34
|
+
the non-negotiable invariant) — plus that a `subDir` adapter namespaces all four files and
|
|
35
|
+
shares no path with the primary. The existing Telegram suites (71 tests across 5 files) pass
|
|
36
|
+
unchanged as the regression guard. `tsc --noEmit` clean. The wiring that consumes these
|
|
37
|
+
(the agent-message recipient handler + `sendAgentMessage`) lands in the follow-up PR.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Instar Upgrade Guide — NEXT
|
|
2
|
+
|
|
3
|
+
<!-- bump: patch -->
|
|
4
|
+
|
|
5
|
+
## What Changed
|
|
6
|
+
|
|
7
|
+
**Agent-to-agent Telegram comms primitive — send side now wired in.** Builds on the
|
|
8
|
+
TelegramAdapter groundwork that landed in v1.3.34 (where the adapter learned to run a
|
|
9
|
+
second bot cleanly + expose `is_bot`/`sender_chat` on inbound messages). This release adds
|
|
10
|
+
the actual send function plus its safety machinery, still **dark** (no caller uses it
|
|
11
|
+
yet — the mentor wires it in the follow-up):
|
|
12
|
+
|
|
13
|
+
- **`sendAgentMessage`** — formats the visible `[a2a:from=… to=… role=… id=… corr=… ts=… v=1]`
|
|
14
|
+
marker, sends via an injected adapter, and writes one audit row for every outcome
|
|
15
|
+
(`ok` / `failed` / `role-refused`) — never silent.
|
|
16
|
+
- **Runtime anti-loop guard** — refuses to send any role the caller wasn't constructed with
|
|
17
|
+
permission for. No marker formed, no send attempted, audit row written. This makes the
|
|
18
|
+
import-surface lint a backup rather than the only defense; the runtime guard always
|
|
19
|
+
applies. A role-handler that *consumes* role X structurally cannot *send* role X.
|
|
20
|
+
- **Bot-token scrubbing on every error/audit surface** — Telegram 401 response bodies
|
|
21
|
+
sometimes echo the token; redaction makes leaks structurally impossible from this module.
|
|
22
|
+
|
|
23
|
+
## What to Tell Your User
|
|
24
|
+
|
|
25
|
+
- Nothing changes in how your agent behaves today — still plumbing. Your agent's own
|
|
26
|
+
Telegram keeps working exactly as before. A follow-up update wires this into the mentor
|
|
27
|
+
feature.
|
|
28
|
+
|
|
29
|
+
## Summary of New Capabilities
|
|
30
|
+
|
|
31
|
+
| Capability | How to Use |
|
|
32
|
+
|-----------|-----------|
|
|
33
|
+
| `sendAgentMessage` + audit ledger | Internal — see `src/messaging/AgentTelegramComms.ts`; formats the marker, sends via injected adapter, writes a `SendAuditRow` for every outcome, scrubs the bot token |
|
|
34
|
+
|
|
35
|
+
## Evidence
|
|
36
|
+
|
|
37
|
+
**Net-new groundwork, not a bug fix.** Proven by 5 new unit tests (25 total in the suite,
|
|
38
|
+
all green): happy-path send + audit (marker round-trips through `parseMarker` — sender output
|
|
39
|
+
IS receiver input); correlation threading (explicit `correlationId` lands in the marker's
|
|
40
|
+
`corr=` field for prompt↔reply linkage via Telegram chat history alone); the anti-loop
|
|
41
|
+
role-refusal (a role not in the caller's allowed-set → no send, no marker, `role-refused`
|
|
42
|
+
audit row); adapter failure with the bot token in the error body → token scrubbed from both
|
|
43
|
+
the result reason and the audit row; `scrubToken` unit coverage across full-token,
|
|
44
|
+
secret-portion, no-token-present, and undefined-token cases. `tsc --noEmit` clean.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Side-Effects Review — agent-to-agent Telegram comms: send side + audit (PR 2b)
|
|
2
|
+
|
|
3
|
+
**Spec:** `docs/specs/MENTOR-LIVE-READINESS-SPEC.md` §Fix 2a "Sender side" + anti-loop #1 +
|
|
4
|
+
round-2 adversarial F5 (token-leak scrub). PR 2 of the staged build, part b.
|
|
5
|
+
**Change:** Extend `src/messaging/AgentTelegramComms.ts` with `sendAgentMessage` (the
|
|
6
|
+
adapter-agnostic send function), a `SendAuditRow` schema + appender hook, and `scrubToken`
|
|
7
|
+
(redacts the bot token from any error surface before it leaves the module). I/O still
|
|
8
|
+
**injected** — fully unit-testable; no caller invokes it yet (dark). PR 3 wires it.
|
|
9
|
+
**Files:** `src/messaging/AgentTelegramComms.ts` (additive), `tests/unit/messaging/AgentTelegramComms.test.ts` (+5).
|
|
10
|
+
|
|
11
|
+
## What changed
|
|
12
|
+
|
|
13
|
+
- `sendAgentMessage(input, deps)` — mints/uses `a2aId` (UUID-or-supplied), defaults
|
|
14
|
+
`correlationId` to `id` (prompts self-correlate; replies thread on the prompt's id),
|
|
15
|
+
formats the marker via `formatMarker`, calls the injected `deps.send(topicId, text)`,
|
|
16
|
+
and writes ONE audit row (always — on `ok`, `failed`, or `role-refused`). Returns
|
|
17
|
+
`{ok, a2aId, sentMessageId?, reason?}`.
|
|
18
|
+
- **Runtime anti-loop guard** (spec §Fix 2a anti-loop #1): refuses any `role` not in
|
|
19
|
+
`deps.allowedRoles` — NO send attempted, NO marker formed, audit row with
|
|
20
|
+
`result: 'role-refused'`. This makes the import-surface lint (deferred to PR 3) a
|
|
21
|
+
backup rather than the only defense; the runtime guard always applies.
|
|
22
|
+
- `scrubToken(s, token)` — redacts the bot token (full + secret-portion) from any
|
|
23
|
+
string before it leaves the module. Wired into every error/audit path in
|
|
24
|
+
`sendAgentMessage` (round-2 adversarial F5: Telegram 401 response bodies sometimes
|
|
25
|
+
echo the token).
|
|
26
|
+
|
|
27
|
+
## The seven questions
|
|
28
|
+
|
|
29
|
+
1. **Over-block.** The runtime role-refusal is exact — a caller that legitimately needs
|
|
30
|
+
role X passes it in `allowedRoles`. No false-positive refusal.
|
|
31
|
+
2. **Under-block.** Every send path writes an audit row (ok / failed / role-refused) — no
|
|
32
|
+
silent drop. Token scrub runs on every reason-string surface (format errors, send
|
|
33
|
+
errors). The audit row schema explicitly forbids secrets (verified in the artifact).
|
|
34
|
+
3. **Level-of-abstraction fit.** I/O injected (`send`, `appendAudit`, `now`, `mintId`,
|
|
35
|
+
`botToken`, `fromBotId`, `toBotId`). The function is the wire-level send/marker/audit
|
|
36
|
+
logic; storage choice (JSONL vs SQLite) is the caller's (PR 3 picks).
|
|
37
|
+
4. **Signal vs authority.** Send is the authority on "did the message leave my process";
|
|
38
|
+
the result is exact (`ok` only when the adapter returns a messageId). Audit row is the
|
|
39
|
+
signal trail. No silent best-effort.
|
|
40
|
+
5. **Interactions — dark, but the module surface is shared with PR 1 + the existing
|
|
41
|
+
`decideRoute`.** The send side adds NEW exports (sendAgentMessage, scrubToken,
|
|
42
|
+
SendAuditRow, etc.) — existing imports unaffected. Dark today.
|
|
43
|
+
6. **External surfaces.** None new in this PR. The audit row schema is the wire format
|
|
44
|
+
for future log readers (Stage-B forensics will read it in PR 3).
|
|
45
|
+
7. **Rollback cost.** Trivial — revert removes additive exports + tests. No data, no
|
|
46
|
+
migration. PR 1 / PR 2a are not touched.
|
|
47
|
+
|
|
48
|
+
## Testing
|
|
49
|
+
|
|
50
|
+
- 5 new unit tests (25 total in the file, all green):
|
|
51
|
+
- **send + audit happy path**: marker round-trips through `parseMarker` (the sender's
|
|
52
|
+
output is the receiver's input — closes the wire-format integration informally);
|
|
53
|
+
`result: 'ok'` audit row with `sentMessageId` + correct fields.
|
|
54
|
+
- **correlation threading**: explicit `correlationId` lands in the marker's `corr=`
|
|
55
|
+
and in the audit row (prompt↔reply linkage via Telegram chat history alone, per
|
|
56
|
+
Codey's round-2 design point).
|
|
57
|
+
- **ANTI-LOOP runtime refusal**: a role not in `allowedRoles` → no send, role-refused
|
|
58
|
+
audit row with explanatory reason. Proves the import-lint isn't the only defense.
|
|
59
|
+
- **send-error with token in body**: adapter throws an error containing the bot token
|
|
60
|
+
→ result + audit reason both scrubbed (no token leak through any surface).
|
|
61
|
+
- **scrubToken unit**: full-token + secret-portion + no-token-present + undefined-token
|
|
62
|
+
coverage.
|
|
63
|
+
- `tsc --noEmit` clean.
|
|
64
|
+
|
|
65
|
+
## Migration parity
|
|
66
|
+
|
|
67
|
+
None — additive exports to a dark module. No config, no routes, no agent-installed file
|
|
68
|
+
changes. PR 3 wires the receiver-handler at `server.ts`, the role handlers, the audit
|
|
69
|
+
ledger persistence (JSONL append via SafeFsExecutor), and the processed-id store (SQLite
|
|
70
|
+
per the convention note flagged in PR 1's artifact); migration (file-outbox retirement,
|
|
71
|
+
dead-config removal) lands there per the spec's §Migration parity.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Side-Effects Review — TelegramAdapter multi-instance isolation + Message-type extension (PR 2a)
|
|
2
|
+
|
|
3
|
+
**Spec:** `docs/specs/MENTOR-LIVE-READINESS-SPEC.md` §Fix 2b "Implementation surface" items
|
|
4
|
+
1-2 + round-2 integration F1 (converged, approved). PR 2 of the staged build, part a.
|
|
5
|
+
**Change:** Make `TelegramAdapter` safe to run as a second (non-primary) instance in one
|
|
6
|
+
process, and expose the Telegram fields the a2a spoof-defense needs. **Ships dark** — no
|
|
7
|
+
caller passes the new options yet; the new Message fields are additive-optional.
|
|
8
|
+
**Files:** `src/messaging/TelegramAdapter.ts`, `tests/unit/telegram-adapter-multi-instance.test.ts` (new).
|
|
9
|
+
|
|
10
|
+
## What changed
|
|
11
|
+
|
|
12
|
+
1. **Constructor opts `{ subDir?, suppressLifelineAutoCreate? }`** (3rd param, optional). When
|
|
13
|
+
`subDir` is set, the four per-bot state files (registry / message-log / poll-offset /
|
|
14
|
+
attention) live under `{stateDir}/{subDir}/` via a new `botStateDir`. The PRIMARY bot
|
|
15
|
+
(no `subDir`) gets `botStateDir === stateDir` → **paths are byte-for-byte unchanged**.
|
|
16
|
+
2. **`suppressLifelineAutoCreate`** — `start()` skips `ensureLifelineTopic()` when true, so a
|
|
17
|
+
non-primary bot can't create a second Lifeline topic in the chat.
|
|
18
|
+
3. **Message-type extension** — `message.from.is_bot?: boolean` + `message.sender_chat?` added
|
|
19
|
+
to `TelegramUpdate`. These are the structural inputs to the a2a user-spoof defense (a
|
|
20
|
+
human typing an `[a2a:…]` marker has `is_bot:false` and no `sender_chat`).
|
|
21
|
+
|
|
22
|
+
## The seven questions
|
|
23
|
+
|
|
24
|
+
1. **Over-block.** N/A — no gate. The only behavior gate is `suppressLifelineAutoCreate`,
|
|
25
|
+
default false (primary unaffected).
|
|
26
|
+
2. **Under-block.** The reviewer-flagged collision (two adapters sharing
|
|
27
|
+
`telegram-poll-offset.json` → `poll()`'s cross-token detection fires continuously) is
|
|
28
|
+
eliminated: non-primary state is namespaced. Test asserts the two adapters share NO
|
|
29
|
+
state-file path.
|
|
30
|
+
3. **Level-of-abstraction fit.** The isolation is at construction (one place), not scattered
|
|
31
|
+
per-callsite. `botStateDir` is the single source for per-bot paths.
|
|
32
|
+
4. **Signal vs authority.** N/A.
|
|
33
|
+
5. **Interactions — THE risk, and how it's bounded.** This file runs Echo's own (primary)
|
|
34
|
+
Telegram — the channel to the user. The change is built so the primary path is
|
|
35
|
+
**identical** (when `subDir` is undefined, `botStateDir === stateDir`). A dedicated test
|
|
36
|
+
asserts the four primary paths are byte-for-byte the historical `{stateDir}/...` values,
|
|
37
|
+
and the existing TelegramAdapter suites (71 tests across 5 files) pass unchanged — the
|
|
38
|
+
regression guard for "did I break my own comms." The new code only branches when `subDir`
|
|
39
|
+
is set, and nothing sets it yet (dark). Media/dashboard dirs still resolve off `stateDir`
|
|
40
|
+
inline — NOT isolated — which is fine: the reviewer flagged only the four constructor
|
|
41
|
+
state files, and the mentor bot (the only future `subDir` user) does no media/dashboard.
|
|
42
|
+
6. **External surfaces.** None. No routes, no config consumed yet. The Message-type fields
|
|
43
|
+
are additive-optional (every existing reader ignores them).
|
|
44
|
+
7. **Rollback cost.** Trivial — revert restores the 2-param constructor; no data, no migration
|
|
45
|
+
(the primary never wrote to a subDir).
|
|
46
|
+
|
|
47
|
+
## Testing
|
|
48
|
+
|
|
49
|
+
- `tests/unit/telegram-adapter-multi-instance.test.ts` (3 tests): **primary paths byte-for-byte
|
|
50
|
+
unchanged** (the load-bearing safety assertion); subDir namespaces all four state files +
|
|
51
|
+
shares no path with primary + creates the sub-dir; `suppressLifelineAutoCreate` recorded
|
|
52
|
+
(false default for primary).
|
|
53
|
+
- Regression: existing Telegram suites (`TelegramAdapter`, `telegram-format-wireup`,
|
|
54
|
+
`telegram-adapter`) + the PR-1 `AgentTelegramComms` suite — 71 tests, all green.
|
|
55
|
+
- `tsc --noEmit` clean.
|
|
56
|
+
|
|
57
|
+
## Migration parity
|
|
58
|
+
|
|
59
|
+
None — additive constructor option + additive optional Message fields. No agent-installed
|
|
60
|
+
file change, no config consumed yet. PR 2b wires `sendAgentMessage` + the recipient handler;
|
|
61
|
+
PR 3's config/migration is per the spec's §Migration parity.
|