instar 1.3.165 → 1.3.167
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 +39 -4
- package/dist/commands/server.js.map +1 -1
- package/dist/core/ForwardedTopicContext.d.ts +29 -0
- package/dist/core/ForwardedTopicContext.d.ts.map +1 -0
- package/dist/core/ForwardedTopicContext.js +46 -0
- package/dist/core/ForwardedTopicContext.js.map +1 -0
- 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.166.md +24 -0
- package/upgrades/1.3.167.md +50 -0
- package/upgrades/side-effects/a2a-inbox-accept-boundary.md +40 -0
- package/upgrades/side-effects/moved-session-context-relay.md +94 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ForwardedTopicContext — build the prior-conversation context block for a session
|
|
3
|
+
* that has just been MOVED to this machine by the multi-machine session pool (§L4).
|
|
4
|
+
*
|
|
5
|
+
* Why this exists (bug #2): when a topic is moved to a standby, the standby spawns the
|
|
6
|
+
* session locally but its OWN message ledger for that topic is EMPTY (it never polled
|
|
7
|
+
* the topic) and its TopicMemory has no rows — so `spawnSessionForTopic` builds an
|
|
8
|
+
* empty context and the moved conversation starts with amnesia. The router (which DID
|
|
9
|
+
* hold the conversation) is the source of truth; the receiver fetches the recent
|
|
10
|
+
* history from it and formats it here into the same "Thread History" block the
|
|
11
|
+
* single-machine JSONL path produces, so the moved session continues the conversation
|
|
12
|
+
* instead of starting blank.
|
|
13
|
+
*
|
|
14
|
+
* Pure + caller-agnostic so it is unit-testable without a live two-machine setup.
|
|
15
|
+
*/
|
|
16
|
+
/** One historical message, matching TelegramAdapter.getTopicHistory()'s shape. */
|
|
17
|
+
export interface ForwardedHistoryMessage {
|
|
18
|
+
fromUser: boolean;
|
|
19
|
+
text?: string;
|
|
20
|
+
senderName?: string;
|
|
21
|
+
timestamp?: string | number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Format fetched router-side history into a Thread History context block, or '' when
|
|
25
|
+
* there is nothing to inject. Mirrors the single-machine JSONL formatting in
|
|
26
|
+
* spawnSessionForTopic so a moved session reads identically to a local one.
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatForwardedTopicContext(messages: ForwardedHistoryMessage[] | null | undefined, topicName?: string): string;
|
|
29
|
+
//# sourceMappingURL=ForwardedTopicContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ForwardedTopicContext.d.ts","sourceRoot":"","sources":["../../src/core/ForwardedTopicContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,kFAAkF;AAClF,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,uBAAuB,EAAE,GAAG,IAAI,GAAG,SAAS,EACtD,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAqBR"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ForwardedTopicContext — build the prior-conversation context block for a session
|
|
3
|
+
* that has just been MOVED to this machine by the multi-machine session pool (§L4).
|
|
4
|
+
*
|
|
5
|
+
* Why this exists (bug #2): when a topic is moved to a standby, the standby spawns the
|
|
6
|
+
* session locally but its OWN message ledger for that topic is EMPTY (it never polled
|
|
7
|
+
* the topic) and its TopicMemory has no rows — so `spawnSessionForTopic` builds an
|
|
8
|
+
* empty context and the moved conversation starts with amnesia. The router (which DID
|
|
9
|
+
* hold the conversation) is the source of truth; the receiver fetches the recent
|
|
10
|
+
* history from it and formats it here into the same "Thread History" block the
|
|
11
|
+
* single-machine JSONL path produces, so the moved session continues the conversation
|
|
12
|
+
* instead of starting blank.
|
|
13
|
+
*
|
|
14
|
+
* Pure + caller-agnostic so it is unit-testable without a live two-machine setup.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Format fetched router-side history into a Thread History context block, or '' when
|
|
18
|
+
* there is nothing to inject. Mirrors the single-machine JSONL formatting in
|
|
19
|
+
* spawnSessionForTopic so a moved session reads identically to a local one.
|
|
20
|
+
*/
|
|
21
|
+
export function formatForwardedTopicContext(messages, topicName) {
|
|
22
|
+
if (!Array.isArray(messages) || messages.length === 0)
|
|
23
|
+
return '';
|
|
24
|
+
const lines = [];
|
|
25
|
+
lines.push(`--- Thread History (last ${messages.length} messages, relayed from the previous machine) ---`);
|
|
26
|
+
lines.push(`IMPORTANT: Read this history carefully before taking any action.`);
|
|
27
|
+
lines.push(`Your task is to continue THIS conversation, not start something new.`);
|
|
28
|
+
if (topicName)
|
|
29
|
+
lines.push(`Topic: ${topicName}`);
|
|
30
|
+
lines.push('');
|
|
31
|
+
for (const m of messages) {
|
|
32
|
+
const sender = m.fromUser ? (m.senderName || 'User') : 'Agent';
|
|
33
|
+
let ts = '??:??';
|
|
34
|
+
if (m.timestamp != null) {
|
|
35
|
+
const d = new Date(m.timestamp);
|
|
36
|
+
if (!Number.isNaN(d.getTime()))
|
|
37
|
+
ts = d.toISOString().slice(11, 19);
|
|
38
|
+
}
|
|
39
|
+
const text = (m.text || '').slice(0, 2000);
|
|
40
|
+
lines.push(`[${ts}] ${sender}: ${text}`);
|
|
41
|
+
}
|
|
42
|
+
lines.push('');
|
|
43
|
+
lines.push('--- End Thread History ---');
|
|
44
|
+
return lines.join('\n');
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=ForwardedTopicContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ForwardedTopicContext.js","sourceRoot":"","sources":["../../src/core/ForwardedTopicContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAUH;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CACzC,QAAsD,EACtD,SAAkB;IAElB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACjE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,4BAA4B,QAAQ,CAAC,MAAM,mDAAmD,CAAC,CAAC;IAC3G,KAAK,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;IAC/E,KAAK,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAC;IACnF,IAAI,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,SAAS,EAAE,CAAC,CAAC;IACjD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QAC/D,IAAI,EAAE,GAAG,OAAO,CAAC;QACjB,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAChC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;gBAAE,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;IAC3C,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACzC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -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:16:12.192Z",
|
|
5
|
+
"instarVersion": "1.3.167",
|
|
6
6
|
"entryCount": 193,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -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,50 @@
|
|
|
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, the moved conversation now remembers what you were talking about — the receiving
|
|
10
|
+
machine pulls the recent history from the machine that was serving it. Only relevant
|
|
11
|
+
when the multi-machine session pool is on; single-machine agents are unaffected. Nothing
|
|
12
|
+
to configure.
|
|
13
|
+
|
|
14
|
+
## Summary of New Capabilities
|
|
15
|
+
|
|
16
|
+
- New `formatForwardedTopicContext` helper formats relayed history into the standard
|
|
17
|
+
thread-history block.
|
|
18
|
+
- `spawnSessionForTopic` accepts an optional pre-computed context, used verbatim when
|
|
19
|
+
provided (skipping the empty-on-a-standby local sources); single-machine behavior is
|
|
20
|
+
unchanged when it is absent.
|
|
21
|
+
- The owner-side resume fetches the router's recent topic messages and passes them, so a
|
|
22
|
+
moved session continues the conversation.
|
|
23
|
+
|
|
24
|
+
## Evidence
|
|
25
|
+
|
|
26
|
+
- Confirmed in code: on a standby, a moved session was spawned with no TopicMemory and an
|
|
27
|
+
empty local message history, so it started with no prior conversation context.
|
|
28
|
+
- Unit, `tests/unit/ForwardedTopicContext.test.ts`: the formatter over empty history,
|
|
29
|
+
multi-message threads with attribution, sender/timestamp fallbacks, and the
|
|
30
|
+
per-message length cap.
|
|
31
|
+
- Wiring, `tests/unit/session-pool-activation-wiring.test.ts`: the owner-side bridge
|
|
32
|
+
still spawns and fails safe with the history fetch wrapped around it.
|
|
33
|
+
- 51 session-pool + adapter tests pass; tsc --noEmit clean.
|
|
34
|
+
- Note: unit-verified; the live confirmation that a moved session retains its context
|
|
35
|
+
follows once the second machine's CLI is logged in.
|
|
36
|
+
- Spec, `docs/specs/moved-session-context-relay.md` plus the .eli16.md sibling.
|
|
37
|
+
|
|
38
|
+
## What Changed — a conversation moved to your other machine keeps its memory
|
|
39
|
+
|
|
40
|
+
A quality step for the multi-machine "move this conversation to my other machine"
|
|
41
|
+
feature. When a conversation moved to the backup machine, that machine started the
|
|
42
|
+
session fresh from its own records — which were empty for that conversation (it had
|
|
43
|
+
never been the one talking to you). So the moved conversation effectively forgot
|
|
44
|
+
everything that came before it.
|
|
45
|
+
|
|
46
|
+
This release has the receiving machine fetch the recent history from the machine that
|
|
47
|
+
was serving the conversation, and seed the moved session with it. So the conversation
|
|
48
|
+
picks up where it left off instead of resetting. It's best-effort: if the other machine
|
|
49
|
+
can't be reached, the session still starts (just without the prior history, as before),
|
|
50
|
+
so it never blocks the move.
|
|
@@ -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,94 @@
|
|
|
1
|
+
# Side-Effects Review — moved session inherits prior conversation (bug #2)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `moved-session-context-relay`
|
|
4
|
+
**Date:** `2026-05-31`
|
|
5
|
+
**Author:** `echo`
|
|
6
|
+
**Second-pass reviewer:** `not required`
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
A session moved to a standby now inherits the topic's recent history from the router.
|
|
11
|
+
New pure helper `formatForwardedTopicContext`; `spawnSessionForTopic` gains an optional
|
|
12
|
+
`precomputedContext`; the owner-side resume fetches the router's
|
|
13
|
+
`/telegram/topics/:topicId/messages` and passes it. Best-effort; default-off for
|
|
14
|
+
single-machine. Closes audit #2 (moved session started with no prior context).
|
|
15
|
+
|
|
16
|
+
## Decision-point inventory
|
|
17
|
+
|
|
18
|
+
- **spawnSessionForTopic context source** — `precomputedContext` provided → use it,
|
|
19
|
+
skip the local TopicMemory/JSONL sources; else → unchanged local logic. Both sides
|
|
20
|
+
covered (the helper tests + the single-machine path is untouched when undefined).
|
|
21
|
+
- **owner-side fetch** — router URL resolvable (`_resolveRouterUrl` → lease holder peer
|
|
22
|
+
URL, not self) + GET ok → format + pass; any failure → spawn without it. Best-effort.
|
|
23
|
+
|
|
24
|
+
## 1. Over-block
|
|
25
|
+
|
|
26
|
+
**What legitimate inputs does this reject?** None. The single-machine spawn path is
|
|
27
|
+
byte-identical when `precomputedContext` is undefined (no router). The fetch is purely
|
|
28
|
+
additive context; a failure falls back to today's behavior (spawn without prior
|
|
29
|
+
history). Nothing that worked before is rejected.
|
|
30
|
+
|
|
31
|
+
## 2. Under-block
|
|
32
|
+
|
|
33
|
+
**What does this still miss?** It fetches up to 50 recent messages (not the entire
|
|
34
|
+
history / no summaries) — sufficient for continuity, not a full replica. It is a
|
|
35
|
+
point-in-time fetch, not a shared/replicated ledger (the broader architectural fix
|
|
36
|
+
remains separate). It is NOT yet live-verified (the moved session can't run until the
|
|
37
|
+
mini's Claude is logged in — bug #12, pending the user). It does not sync userProfile
|
|
38
|
+
(a smaller, separate gap).
|
|
39
|
+
|
|
40
|
+
## 3. Level-of-abstraction fit
|
|
41
|
+
|
|
42
|
+
**Right layer?** Yes. The formatter is a pure module (testable, mirrors the existing
|
|
43
|
+
JSONL format). `precomputedContext` slots into `spawnSessionForTopic`'s existing
|
|
44
|
+
context-resolution as the highest-precedence source. The fetch lives in the owner-side
|
|
45
|
+
resume (the one place a moved session is spawned), using the same `_resolveRouterUrl` /
|
|
46
|
+
authToken plumbing as the outbound relay.
|
|
47
|
+
|
|
48
|
+
## 4. Signal vs authority compliance
|
|
49
|
+
|
|
50
|
+
**Required reference:** [docs/signal-vs-authority.md](../../docs/signal-vs-authority.md)
|
|
51
|
+
|
|
52
|
+
No blocking authority. It only ADDS context to a spawned session; it gates nothing and
|
|
53
|
+
blocks nothing. A fetch failure is swallowed (best-effort) and the session proceeds.
|
|
54
|
+
|
|
55
|
+
## 5. Interactions
|
|
56
|
+
|
|
57
|
+
Reuses the read-only `/telegram/topics/:topicId/messages` route (no new endpoint) and
|
|
58
|
+
the lease-holder resolution (`_resolveRouterUrl`) shared with the outbound relay. Pairs
|
|
59
|
+
with the owner-side resume (#9/#11): the same path that spawns + persists + confirms a
|
|
60
|
+
moved session now also seeds its context. Idempotent (a fresh fetch per spawn). No
|
|
61
|
+
interaction with the lease or shared-state guard.
|
|
62
|
+
|
|
63
|
+
## 6. External surfaces
|
|
64
|
+
|
|
65
|
+
One cross-machine GET from the standby to the router's existing messages route
|
|
66
|
+
(Bearer-authed). No new route, config, or notification. The visible effect: a moved
|
|
67
|
+
session continues the conversation instead of resetting.
|
|
68
|
+
|
|
69
|
+
## 7. Rollback cost
|
|
70
|
+
|
|
71
|
+
Low. Remove the `precomputedContext` param + the onAccepted fetch + the helper; a moved
|
|
72
|
+
session reverts to starting context-less (audit #2). No schema, no state, no migration.
|
|
73
|
+
|
|
74
|
+
## Conclusion
|
|
75
|
+
|
|
76
|
+
Targeted, additive, best-effort context relay; the formatter + the precedence both
|
|
77
|
+
unit-tested; the single-machine path untouched; no new authority/surface; cheap revert.
|
|
78
|
+
Makes a moved session continue its conversation. Honestly scoped: unit-verified, live
|
|
79
|
+
confirmation pending the mini's Claude login.
|
|
80
|
+
|
|
81
|
+
## Second-pass review (if required)
|
|
82
|
+
|
|
83
|
+
Not required — additive best-effort context, pure formatter fully tested, single-machine
|
|
84
|
+
path unchanged, reversible, no authority. The live moved-session-retains-context check
|
|
85
|
+
is the Tier-3 gate after the user's mini login.
|
|
86
|
+
|
|
87
|
+
## Evidence pointers
|
|
88
|
+
|
|
89
|
+
- `tests/unit/ForwardedTopicContext.test.ts` — formatter over empty/multi/fallback/cap.
|
|
90
|
+
- `tests/unit/session-pool-activation-wiring.test.ts` — owner-side bridge spawns + fails safe.
|
|
91
|
+
- 51 session-pool + adapter tests green; `tsc --noEmit` clean.
|
|
92
|
+
- Confirmed in code: on a standby, `spawnSessionForTopic` got `topicMemory: undefined`
|
|
93
|
+
and `getTopicHistory` returns `[]` → `contextContent = ''` (no prior history).
|
|
94
|
+
- Spec: `docs/specs/moved-session-context-relay.md` (+ `.eli16.md`).
|