@@ -17,9 +17,13 @@ vi.mock("../agents/pi-embedded.js", () => ({
1717vi . mock ( "../agents/model-catalog.js" , ( ) => ( {
1818 loadModelCatalog : vi . fn ( ) ,
1919} ) ) ;
20+ vi . mock ( "../agents/subagent-announce.js" , ( ) => ( {
21+ runSubagentAnnounceFlow : vi . fn ( ) ,
22+ } ) ) ;
2023
2124import { loadModelCatalog } from "../agents/model-catalog.js" ;
2225import { runEmbeddedPiAgent } from "../agents/pi-embedded.js" ;
26+ import { runSubagentAnnounceFlow } from "../agents/subagent-announce.js" ;
2327import { runCronIsolatedAgentTurn } from "./isolated-agent.js" ;
2428
2529async function withTempHome < T > ( fn : ( home : string ) => Promise < T > ) : Promise < T > {
@@ -86,6 +90,7 @@ describe("runCronIsolatedAgentTurn", () => {
8690 beforeEach ( ( ) => {
8791 vi . mocked ( runEmbeddedPiAgent ) . mockReset ( ) ;
8892 vi . mocked ( loadModelCatalog ) . mockResolvedValue ( [ ] ) ;
93+ vi . mocked ( runSubagentAnnounceFlow ) . mockReset ( ) . mockResolvedValue ( true ) ;
8994 setActivePluginRegistry (
9095 createTestRegistry ( [
9196 {
@@ -97,7 +102,7 @@ describe("runCronIsolatedAgentTurn", () => {
97102 ) ;
98103 } ) ;
99104
100- it ( "announces when delivery is requested" , async ( ) => {
105+ it ( "announces via shared subagent flow when delivery is requested" , async ( ) => {
101106 await withTempHome ( async ( home ) => {
102107 const storePath = await writeSessionStore ( home ) ;
103108 const deps : CliDeps = {
@@ -130,11 +135,16 @@ describe("runCronIsolatedAgentTurn", () => {
130135 } ) ;
131136
132137 expect ( res . status ) . toBe ( "ok" ) ;
133- expect ( deps . sendMessageTelegram ) . toHaveBeenCalled ( ) ;
138+ expect ( runSubagentAnnounceFlow ) . toHaveBeenCalledTimes ( 1 ) ;
139+ const announceArgs = vi . mocked ( runSubagentAnnounceFlow ) . mock . calls [ 0 ] ?. [ 0 ] as
140+ | { announceType ?: string }
141+ | undefined ;
142+ expect ( announceArgs ?. announceType ) . toBe ( "cron job" ) ;
143+ expect ( deps . sendMessageTelegram ) . not . toHaveBeenCalled ( ) ;
134144 } ) ;
135145 } ) ;
136146
137- it ( "announces only the final payload text" , async ( ) => {
147+ it ( "passes final payload text into shared subagent announce flow " , async ( ) => {
138148 await withTempHome ( async ( home ) => {
139149 const storePath = await writeSessionStore ( home ) ;
140150 const deps : CliDeps = {
@@ -167,12 +177,71 @@ describe("runCronIsolatedAgentTurn", () => {
167177 } ) ;
168178
169179 expect ( res . status ) . toBe ( "ok" ) ;
170- expect ( deps . sendMessageTelegram ) . toHaveBeenCalledTimes ( 1 ) ;
171- expect ( deps . sendMessageTelegram ) . toHaveBeenCalledWith (
172- "123" ,
173- "Final weather summary" ,
174- expect . any ( Object ) ,
180+ expect ( runSubagentAnnounceFlow ) . toHaveBeenCalledTimes ( 1 ) ;
181+ const announceArgs = vi . mocked ( runSubagentAnnounceFlow ) . mock . calls [ 0 ] ?. [ 0 ] as
182+ | { roundOneReply ?: string ; requesterOrigin ?: { threadId ?: string | number } }
183+ | undefined ;
184+ expect ( announceArgs ?. roundOneReply ) . toBe ( "Final weather summary" ) ;
185+ expect ( announceArgs ?. requesterOrigin ?. threadId ) . toBeUndefined ( ) ;
186+ } ) ;
187+ } ) ;
188+
189+ it ( "passes resolved threadId into shared subagent announce flow" , async ( ) => {
190+ await withTempHome ( async ( home ) => {
191+ const storePath = await writeSessionStore ( home ) ;
192+ await fs . writeFile (
193+ storePath ,
194+ JSON . stringify (
195+ {
196+ "agent:main:main" : {
197+ sessionId : "main-session" ,
198+ updatedAt : Date . now ( ) ,
199+ lastChannel : "telegram" ,
200+ lastTo : "123" ,
201+ lastThreadId : 42 ,
202+ } ,
203+ } ,
204+ null ,
205+ 2 ,
206+ ) ,
207+ "utf-8" ,
175208 ) ;
209+ const deps : CliDeps = {
210+ sendMessageWhatsApp : vi . fn ( ) ,
211+ sendMessageTelegram : vi . fn ( ) ,
212+ sendMessageDiscord : vi . fn ( ) ,
213+ sendMessageSignal : vi . fn ( ) ,
214+ sendMessageIMessage : vi . fn ( ) ,
215+ } ;
216+ vi . mocked ( runEmbeddedPiAgent ) . mockResolvedValue ( {
217+ payloads : [ { text : "Final weather summary" } ] ,
218+ meta : {
219+ durationMs : 5 ,
220+ agentMeta : { sessionId : "s" , provider : "p" , model : "m" } ,
221+ } ,
222+ } ) ;
223+
224+ const res = await runCronIsolatedAgentTurn ( {
225+ cfg : makeCfg ( home , storePath , {
226+ channels : { telegram : { botToken : "t-1" } } ,
227+ } ) ,
228+ deps,
229+ job : {
230+ ...makeJob ( { kind : "agentTurn" , message : "do it" } ) ,
231+ delivery : { mode : "announce" , channel : "last" } ,
232+ } ,
233+ message : "do it" ,
234+ sessionKey : "cron:job-1" ,
235+ lane : "cron" ,
236+ } ) ;
237+
238+ expect ( res . status ) . toBe ( "ok" ) ;
239+ const announceArgs = vi . mocked ( runSubagentAnnounceFlow ) . mock . calls [ 0 ] ?. [ 0 ] as
240+ | { requesterOrigin ?: { threadId ?: string | number ; channel ?: string ; to ?: string } }
241+ | undefined ;
242+ expect ( announceArgs ?. requesterOrigin ?. channel ) . toBe ( "telegram" ) ;
243+ expect ( announceArgs ?. requesterOrigin ?. to ) . toBe ( "123" ) ;
244+ expect ( announceArgs ?. requesterOrigin ?. threadId ) . toBe ( 42 ) ;
176245 } ) ;
177246 } ) ;
178247
@@ -211,6 +280,7 @@ describe("runCronIsolatedAgentTurn", () => {
211280 } ) ;
212281
213282 expect ( res . status ) . toBe ( "ok" ) ;
283+ expect ( runSubagentAnnounceFlow ) . not . toHaveBeenCalled ( ) ;
214284 expect ( deps . sendMessageTelegram ) . not . toHaveBeenCalled ( ) ;
215285 } ) ;
216286 } ) ;
@@ -248,11 +318,12 @@ describe("runCronIsolatedAgentTurn", () => {
248318 } ) ;
249319
250320 expect ( res . status ) . toBe ( "ok" ) ;
321+ expect ( runSubagentAnnounceFlow ) . not . toHaveBeenCalled ( ) ;
251322 expect ( deps . sendMessageTelegram ) . not . toHaveBeenCalled ( ) ;
252323 } ) ;
253324 } ) ;
254325
255- it ( "fails when announce delivery fails and best-effort is disabled" , async ( ) => {
326+ it ( "fails when shared announce flow fails and best-effort is disabled" , async ( ) => {
256327 await withTempHome ( async ( home ) => {
257328 const storePath = await writeSessionStore ( home ) ;
258329 const deps : CliDeps = {
@@ -269,6 +340,7 @@ describe("runCronIsolatedAgentTurn", () => {
269340 agentMeta : { sessionId : "s" , provider : "p" , model : "m" } ,
270341 } ,
271342 } ) ;
343+ vi . mocked ( runSubagentAnnounceFlow ) . mockResolvedValue ( false ) ;
272344 const res = await runCronIsolatedAgentTurn ( {
273345 cfg : makeCfg ( home , storePath , {
274346 channels : { telegram : { botToken : "t-1" } } ,
@@ -284,11 +356,11 @@ describe("runCronIsolatedAgentTurn", () => {
284356 } ) ;
285357
286358 expect ( res . status ) . toBe ( "error" ) ;
287- expect ( res . error ) . toBe ( "Error: boom " ) ;
359+ expect ( res . error ) . toBe ( "cron announce delivery failed " ) ;
288360 } ) ;
289361 } ) ;
290362
291- it ( "ignores announce delivery failures when best-effort is enabled" , async ( ) => {
363+ it ( "ignores shared announce flow failures when best-effort is enabled" , async ( ) => {
292364 await withTempHome ( async ( home ) => {
293365 const storePath = await writeSessionStore ( home ) ;
294366 const deps : CliDeps = {
@@ -305,6 +377,7 @@ describe("runCronIsolatedAgentTurn", () => {
305377 agentMeta : { sessionId : "s" , provider : "p" , model : "m" } ,
306378 } ,
307379 } ) ;
380+ vi . mocked ( runSubagentAnnounceFlow ) . mockResolvedValue ( false ) ;
308381 const res = await runCronIsolatedAgentTurn ( {
309382 cfg : makeCfg ( home , storePath , {
310383 channels : { telegram : { botToken : "t-1" } } ,
@@ -325,7 +398,8 @@ describe("runCronIsolatedAgentTurn", () => {
325398 } ) ;
326399
327400 expect ( res . status ) . toBe ( "ok" ) ;
328- expect ( deps . sendMessageTelegram ) . toHaveBeenCalled ( ) ;
401+ expect ( runSubagentAnnounceFlow ) . toHaveBeenCalledTimes ( 1 ) ;
402+ expect ( deps . sendMessageTelegram ) . not . toHaveBeenCalled ( ) ;
329403 } ) ;
330404 } ) ;
331405} ) ;
0 commit comments