instar 1.3.164 → 1.3.166
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/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +30 -0
- package/dist/commands/server.js.map +1 -1
- package/dist/messaging/TelegramAdapter.d.ts +13 -0
- package/dist/messaging/TelegramAdapter.d.ts.map +1 -1
- package/dist/messaging/TelegramAdapter.js +27 -4
- package/dist/messaging/TelegramAdapter.js.map +1 -1
- package/dist/messaging/installAgentMessageHook.d.ts.map +1 -1
- package/dist/messaging/installAgentMessageHook.js +18 -8
- package/dist/messaging/installAgentMessageHook.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/1.3.165.md +47 -0
- package/upgrades/1.3.166.md +24 -0
- package/upgrades/side-effects/a2a-inbox-accept-boundary.md +40 -0
- package/upgrades/side-effects/standby-telegram-outbound-relay.md +100 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installAgentMessageHook.d.ts","sourceRoot":"","sources":["../../src/messaging/installAgentMessageHook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAEL,KAAK,eAAe,EAEpB,KAAK,UAAU,EAChB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,mBAAmB,EAAmB,MAAM,0BAA0B,CAAC;AACrF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;oFACoF;AACpF,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE7G,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,YAAY,EAAE,gBAAgB,CAAC;IAC/B;;sDAEkD;IAClD,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACxC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,2BAA2B,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"installAgentMessageHook.d.ts","sourceRoot":"","sources":["../../src/messaging/installAgentMessageHook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAEL,KAAK,eAAe,EAEpB,KAAK,UAAU,EAChB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,mBAAmB,EAAmB,MAAM,0BAA0B,CAAC;AACrF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;oFACoF;AACpF,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAE7G,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,YAAY,EAAE,gBAAgB,CAAC;IAC/B;;sDAEkD;IAClD,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACxC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,2BAA2B,GAAG,gBAAgB,CAkGzF"}
|
|
@@ -83,16 +83,26 @@ export function buildAgentMessageHook(deps) {
|
|
|
83
83
|
telegramSenderChatId: input.senderChatId,
|
|
84
84
|
topicId: input.topicId,
|
|
85
85
|
});
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
86
|
+
// Accept-boundary (the #581 / #3 class — this is the THIRD a2a path): a role
|
|
87
|
+
// handler (e.g. the mentee mentor-message handler) SPAWNS a session and
|
|
88
|
+
// bounded-waits for the reply — that can take MINUTES — and delivers its
|
|
89
|
+
// reply OUT via a separate a2a message, not this HTTP response. AWAITING it
|
|
90
|
+
// here meant the caller's /a2a/inbox POST waited the full handler, so the
|
|
91
|
+
// sender's ~10s `AbortSignal.timeout` fired and logged a FALSE "local-inbox
|
|
92
|
+
// delivery attempt failed" (the message was in fact accepted — its id is
|
|
93
|
+
// marked processed above — and the reply will arrive on its own channel).
|
|
94
|
+
// Respond ACCEPTED immediately and run the handler in the background. The
|
|
95
|
+
// idempotency mark above still dedups any retry; a handler failure is caught
|
|
96
|
+
// + logged async (it can't reject a response that already returned).
|
|
97
|
+
void Promise.resolve()
|
|
98
|
+
.then(() => handler(msg, { topicId: input.topicId, senderBotId: input.senderBotId }))
|
|
99
|
+
.catch((err) => {
|
|
100
|
+
// A role-handler failure is recorded but doesn't un-mark the id (we still
|
|
101
|
+
// treat the message as processed; retrying would just re-fail). Stage-B
|
|
102
|
+
// forensics can see the routed row + the absence of a downstream effect.
|
|
93
103
|
// eslint-disable-next-line no-console
|
|
94
104
|
console.error(`[a2a] role-handler "${msg.role}" failed:`, err instanceof Error ? err.message : String(err));
|
|
95
|
-
}
|
|
105
|
+
});
|
|
96
106
|
return { handled: true };
|
|
97
107
|
};
|
|
98
108
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installAgentMessageHook.js","sourceRoot":"","sources":["../../src/messaging/installAgentMessageHook.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"installAgentMessageHook.js","sourceRoot":"","sources":["../../src/messaging/installAgentMessageHook.ts"],"names":[],"mappings":"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"}
|
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-31T12:02:03.497Z",
|
|
5
|
+
"instarVersion": "1.3.166",
|
|
6
6
|
"entryCount": 193,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What to Tell Your User
|
|
7
|
+
|
|
8
|
+
If you run your agent across more than one machine and move a conversation to another
|
|
9
|
+
one, that conversation can now reply to you — its replies are relayed through the
|
|
10
|
+
machine that owns your messaging bot, so you hear back without any risk of the two
|
|
11
|
+
machines clashing over the bot. Only relevant when the multi-machine session pool is
|
|
12
|
+
on; single-machine agents are unaffected. Nothing to configure.
|
|
13
|
+
|
|
14
|
+
## Summary of New Capabilities
|
|
15
|
+
|
|
16
|
+
- `TelegramAdapter` gains an `outboundRelay` hook. When the adapter has no bot token,
|
|
17
|
+
`sendToTopic` routes the send through it (the server wires it to POST the
|
|
18
|
+
Telegram-owning lease holder's `/telegram/reply`), instead of failing silently. A
|
|
19
|
+
token-holding adapter sends directly as before; a relay that can't deliver throws
|
|
20
|
+
rather than dropping the message.
|
|
21
|
+
|
|
22
|
+
## Evidence
|
|
23
|
+
|
|
24
|
+
- Found live: the backup machine's Telegram adapter had no bot token, so a moved
|
|
25
|
+
session's reply was sent with no token and silently vanished.
|
|
26
|
+
- Unit, `tests/unit/TelegramAdapter.test.ts`: a tokenless adapter routes the send
|
|
27
|
+
through the relay (the Telegram API is not hit, the relayed id is returned); a
|
|
28
|
+
token-holding adapter sends directly and never consults the relay; a relay that
|
|
29
|
+
returns nothing throws instead of silently dropping the reply.
|
|
30
|
+
- 19 TelegramAdapter tests pass; tsc --noEmit clean.
|
|
31
|
+
- Spec, `docs/specs/standby-telegram-outbound-relay.md` plus the .eli16.md sibling.
|
|
32
|
+
- Side-effects, `upgrades/side-effects/standby-telegram-outbound-relay.md`.
|
|
33
|
+
|
|
34
|
+
## What Changed — a conversation moved to your other machine can now reply to you
|
|
35
|
+
|
|
36
|
+
The final piece of the multi-machine "move this conversation to my other machine"
|
|
37
|
+
feature. Telegram only allows one program to use a given bot at a time, so in a
|
|
38
|
+
two-machine setup only the main machine holds the bot, and the backup deliberately
|
|
39
|
+
holds none (to avoid two programs fighting over the same bot — a real failure we fixed
|
|
40
|
+
earlier). That meant a conversation moved to the backup machine could run there but
|
|
41
|
+
couldn't actually send a reply — it came out silent.
|
|
42
|
+
|
|
43
|
+
This release adds a relay: when the backup machine wants to reply but has no bot, it
|
|
44
|
+
hands the message to the machine that does hold the bot, which sends it normally. So
|
|
45
|
+
your reply comes through, and there's still only ever one program using the bot — no
|
|
46
|
+
fighting, no duplicate messages. A machine that holds its own bot is completely
|
|
47
|
+
unaffected.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What to Tell Your User
|
|
7
|
+
|
|
8
|
+
If you run multiple agents that talk to each other, you'll stop seeing spurious "delivery failed" timeouts in the logs for messages that actually went through fine. The receiving agent now confirms it got the message right away and does the work in the background, and the reply still comes back as normal.
|
|
9
|
+
|
|
10
|
+
## Summary of New Capabilities
|
|
11
|
+
|
|
12
|
+
- The agent-to-agent inbox hook (the third and last of the agent-to-agent transports) now responds at the accept boundary: it acknowledges immediately after validating the message and runs the (potentially minutes-long) handler in the background, instead of making the sender wait through it. Completes the same fix already shipped for the co-located relay and the cross-machine threadline paths.
|
|
13
|
+
|
|
14
|
+
## Evidence
|
|
15
|
+
|
|
16
|
+
- Found in the agent's own server log: recurring "[a2a] local-inbox delivery attempt failed (to=instar-codey): aborted due to timeout".
|
|
17
|
+
- Root traced through the call chain: the /a2a/inbox response awaited the role handler, which spawns a session and waits minutes; the sender's ~10s timeout fired first. The reply flows back on a separate channel, so awaiting was unnecessary.
|
|
18
|
+
- Unit tests: a held (slow) handler no longer blocks the response (it would have hung if still awaited); a background handler error still yields a clean acknowledgement. Idempotency, validation, and spoof-defense cases unchanged. Independent adversarial review.
|
|
19
|
+
|
|
20
|
+
## What Changed — Agent-to-agent task delivery no longer logs false "delivery failed" timeouts
|
|
21
|
+
|
|
22
|
+
When one of your agents hands a task to another agent on the same machine (for example a mentor agent assigning work to a mentee), the receiver was only acknowledging the message AFTER it had finished the whole task — which means spinning up a work session and waiting minutes for it to think and reply. But the sender only waits about 10 seconds for an acknowledgement, so it gave up and logged a "delivery failed" every time — even though the message was actually received fine and the reply was on its way back on a separate channel.
|
|
23
|
+
|
|
24
|
+
Now the receiver acknowledges the moment it accepts the message and does the work in the background. The sender gets its acknowledgement right away, stops logging false failures, and stops holding a connection open for ten seconds each time. The actual reply still comes back exactly as before.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Side-effects — /a2a/inbox accept-boundary
|
|
2
|
+
|
|
3
|
+
## 1. What files/state does this touch at runtime?
|
|
4
|
+
`installAgentMessageHook.ts` — the role-handler invocation in the agent-message hook. No new files,
|
|
5
|
+
config, schema, or state. The role handler still runs (now in the background); the idempotency mark
|
|
6
|
+
and ledger row are unchanged.
|
|
7
|
+
|
|
8
|
+
## 2. Does it change any functional behavior?
|
|
9
|
+
The `/a2a/inbox` HTTP response now returns `{handled:true}` immediately after the message is validated
|
|
10
|
+
+ marked processed, instead of after the (minutes-long) role handler completes. The handler runs in
|
|
11
|
+
the background and delivers its reply on its own a2a channel exactly as before. Net: the sender no
|
|
12
|
+
longer times out (its ~10s `AbortSignal.timeout`) and no longer logs a false "delivery failed".
|
|
13
|
+
|
|
14
|
+
## 3. What happens on failure / weird config?
|
|
15
|
+
A background handler rejection is caught and logged (`console.error`), exactly as the old `try/catch`
|
|
16
|
+
did — just on a later microtask. The id stays marked processed (unchanged). Validation failures
|
|
17
|
+
(unknown role, spoof, already-processed) still short-circuit BEFORE the handler, unchanged.
|
|
18
|
+
|
|
19
|
+
## 4. Migration parity — do existing agents get it?
|
|
20
|
+
Yes, via the normal release — code-only, compiled into `dist`. No agent-installed file / config /
|
|
21
|
+
template change → no `PostUpdateMigrator` pass.
|
|
22
|
+
|
|
23
|
+
## 5. Could it spam / flood / burn resources?
|
|
24
|
+
No — it REDUCES resource use (no 10s held connection per mentor a2a message). Same single handler
|
|
25
|
+
run, no new timers/IO/network. The idempotency mark still bounds duplicate processing.
|
|
26
|
+
|
|
27
|
+
## 6. Rollback / off-switch?
|
|
28
|
+
Revert the one block (re-`await` the handler). No data, no migration, no flag. Mirrors #581/#3
|
|
29
|
+
rollback.
|
|
30
|
+
|
|
31
|
+
## 7. Concurrency / ordering?
|
|
32
|
+
The handler now runs after the response returns instead of before. The idempotency `markProcessed`
|
|
33
|
+
still happens BEFORE the response (so retries dedup). The reply-out is unchanged (a separate a2a
|
|
34
|
+
send). A background handler error cannot affect the already-sent response.
|
|
35
|
+
|
|
36
|
+
## Blast radius
|
|
37
|
+
Small + additive: one block in `installAgentMessageHook.ts` swapped from await-then-respond to
|
|
38
|
+
respond-then-background. Exactly mirrors the proven #581 (`/messages/relay-agent`) and #3
|
|
39
|
+
(`/threadline/messages/receive`) accept-boundaries. Only the a2a role-handler dispatch timing
|
|
40
|
+
changes; validation, idempotency, ledger, and the reply path are untouched.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Side-Effects Review — Tokenless standby Telegram outbound relay (bug #7)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `standby-telegram-outbound-relay`
|
|
4
|
+
**Date:** `2026-05-31`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
`TelegramAdapter` gains a settable `outboundRelay` callback. In `sendToTopic`, when
|
|
11
|
+
the adapter has NO bot token AND a relay is wired, the send routes through the relay
|
|
12
|
+
instead of the Telegram API (the relayed id feeds the same log/stall/promise
|
|
13
|
+
bookkeeping); a relay returning null throws. `server.ts` wires the relay to POST the
|
|
14
|
+
lease holder's `/telegram/reply/:topicId` (Bearer authToken + the holder's peer URL),
|
|
15
|
+
refusing to relay to self/unknown. Closes bug #7 (a session moved to a tokenless
|
|
16
|
+
standby was mute).
|
|
17
|
+
|
|
18
|
+
## Decision-point inventory
|
|
19
|
+
|
|
20
|
+
- **sendToTopic branch** — `!this.config.token && this.outboundRelay` → relay; else →
|
|
21
|
+
the unchanged API path. Both covered by tests.
|
|
22
|
+
- **relay closure** — `holder` is self or unknown, or no URL → return null (no
|
|
23
|
+
relay); else POST and return the id (or null on non-ok / throw). Self-relay guard
|
|
24
|
+
+ null-on-failure tested via the adapter-level null case.
|
|
25
|
+
|
|
26
|
+
## 1. Over-block
|
|
27
|
+
|
|
28
|
+
**What legitimate inputs does this reject?** Nothing for a token-holding machine — its
|
|
29
|
+
send path is byte-identical (the relay branch is skipped). For a tokenless standby, a
|
|
30
|
+
send that previously failed silently (no token) now either relays successfully or
|
|
31
|
+
throws a clear error (better than the silent mute). No legitimate send is dropped.
|
|
32
|
+
|
|
33
|
+
## 2. Under-block
|
|
34
|
+
|
|
35
|
+
**What does this still miss?** It does not sync conversation CONTEXT to the moved
|
|
36
|
+
session (audit #2 — the reply may lack prior history). It relays to the current lease
|
|
37
|
+
holder only (correct for the single-Telegram-owner model); if the holder is
|
|
38
|
+
unreachable it returns null → `sendToTopic` throws (surfaced, not silent). It does not
|
|
39
|
+
retry/queue a failed relay (the caller/session sees the throw); a durable relay queue
|
|
40
|
+
is possible later but out of scope.
|
|
41
|
+
|
|
42
|
+
## 3. Level-of-abstraction fit
|
|
43
|
+
|
|
44
|
+
**Right layer?** Yes. The send decision lives in `TelegramAdapter.sendToTopic` (the
|
|
45
|
+
one outbound chokepoint), expressed as an injected callback (same pattern as the
|
|
46
|
+
adapter's other `on*` hooks). The cross-machine resolution (holder → URL → POST) lives
|
|
47
|
+
in `server.ts` where the mesh/coordinator/authToken are already in scope. The relay
|
|
48
|
+
reuses the existing `/telegram/reply` route rather than a new mesh command.
|
|
49
|
+
|
|
50
|
+
## 4. Signal vs authority compliance
|
|
51
|
+
|
|
52
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
53
|
+
|
|
54
|
+
No new blocking authority. It changes HOW a tokenless adapter sends (relay vs direct),
|
|
55
|
+
not WHETHER. It preserves the single-Telegram-owner safety invariant (the standby
|
|
56
|
+
never sends on the bot directly), which is the 409-conflict guard — strengthening, not
|
|
57
|
+
weakening, a safety property.
|
|
58
|
+
|
|
59
|
+
## 5. Interactions
|
|
60
|
+
|
|
61
|
+
The relay POSTs the holder's `/telegram/reply` — the same route used for normal
|
|
62
|
+
replies — so the message goes out the one bot the holder owns; no second poller/sender
|
|
63
|
+
(no 409). Pairs with the lease coordinator (`getSyncStatus().leaseHolder` picks the
|
|
64
|
+
target) and peer presence (`peerUrl`). On a token-holding router the callback is wired
|
|
65
|
+
but never invoked. Idempotent per call; a failed relay throws (the session's reply
|
|
66
|
+
attempt errors rather than silently vanishing).
|
|
67
|
+
|
|
68
|
+
## 6. External surfaces
|
|
69
|
+
|
|
70
|
+
One cross-machine HTTP POST from a tokenless standby to the holder's existing
|
|
71
|
+
`/telegram/reply` (Bearer-authed). No new route, config, or notification. The visible
|
|
72
|
+
effect: a moved session's replies reach the user (via the holder's bot).
|
|
73
|
+
|
|
74
|
+
## 7. Rollback cost
|
|
75
|
+
|
|
76
|
+
Low. Remove the `outboundRelay` callback + the `sendToTopic` branch + the wiring; a
|
|
77
|
+
tokenless standby's sends revert to silent failure (bug #7). No schema, no state, no
|
|
78
|
+
migration (the callback is in-memory, default null).
|
|
79
|
+
|
|
80
|
+
## Conclusion
|
|
81
|
+
|
|
82
|
+
Minimal, injected-callback change scoped to the tokenless-send path, reusing the
|
|
83
|
+
existing reply route, preserving the single-owner 409-guard, both branches + the
|
|
84
|
+
null-failure case unit-tested, no change for token-holding machines, cheap revert.
|
|
85
|
+
The completion gate for the live transfer — a moved session can now reply.
|
|
86
|
+
|
|
87
|
+
## Second-pass review (if required)
|
|
88
|
+
|
|
89
|
+
Not required — scoped to the no-token send path, reuses a battle-tested route,
|
|
90
|
+
strengthens (not weakens) the single-owner invariant, both branches + failure tested,
|
|
91
|
+
reversible. The live two-machine re-test (a reply landing) is the Tier-3 gate.
|
|
92
|
+
|
|
93
|
+
## Evidence pointers
|
|
94
|
+
|
|
95
|
+
- `tests/unit/TelegramAdapter.test.ts` — tokenless adapter relays (API not hit, relayed
|
|
96
|
+
id returned); token-holding adapter sends directly (relay not consulted); relay→null
|
|
97
|
+
throws (no silent mute).
|
|
98
|
+
- 19 TelegramAdapter tests green; `tsc --noEmit` clean.
|
|
99
|
+
- Found live: mini telegram adapter `botToken=MISSING` → a moved session's reply muted.
|
|
100
|
+
- Spec: `docs/specs/standby-telegram-outbound-relay.md` (+ `.eli16.md`).
|