agentix-cli 0.137.2 → 0.138.0

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 (148) hide show
  1. package/dist/{App-TOAWET76.js → App-F42CYCKX.js} +2 -2
  2. package/dist/{ChatApp-4DRCRKFS.js → ChatApp-RPMQBKHV.js} +2 -2
  3. package/dist/{absorb-eval-OXNL5QGQ.js → absorb-eval-HRPEHJSO.js} +2 -2
  4. package/dist/{agent-GALMGMNJ.js → agent-L5CJF3GH.js} +2 -2
  5. package/dist/{board-dashboard-2A6VSQ7V.js → board-dashboard-33NGOGWC.js} +440 -285
  6. package/dist/board-dashboard-33NGOGWC.js.map +1 -0
  7. package/dist/{chunk-XZIKAHFU.js → chunk-375MXG3H.js} +2 -2
  8. package/dist/{chunk-5ADXRVYT.js → chunk-4HHHVWDB.js} +5 -5
  9. package/dist/{chunk-Q72TK3DO.js → chunk-5HLD66CW.js} +2 -2
  10. package/dist/{chunk-5RHCM3L7.js → chunk-6AUWEL6V.js} +2 -2
  11. package/dist/{chunk-635B6SXI.js → chunk-6VP2KMUM.js} +2 -2
  12. package/dist/{chunk-WCXXXAHV.js → chunk-7DYVNET6.js} +1 -1
  13. package/dist/chunk-7DYVNET6.js.map +1 -0
  14. package/dist/{chunk-3K3LRLZX.js → chunk-7V73QTQ7.js} +2 -2
  15. package/dist/{chunk-PNITKKDR.js → chunk-7YZL5MUL.js} +9 -9
  16. package/dist/{chunk-PNITKKDR.js.map → chunk-7YZL5MUL.js.map} +1 -1
  17. package/dist/chunk-A5GYG56I.js +2 -0
  18. package/dist/chunk-A5GYG56I.js.map +1 -0
  19. package/dist/{chunk-GIQKQD2B.js → chunk-AGQYUOZY.js} +2 -2
  20. package/dist/{chunk-2JKKGS77.js → chunk-AP4DADXG.js} +2 -2
  21. package/dist/{chunk-DIE6XXJF.js → chunk-CZZJEFUM.js} +2 -2
  22. package/dist/{chunk-23LWLYOK.js → chunk-DBJUGKX2.js} +2 -2
  23. package/dist/{chunk-B6PMIUVV.js → chunk-EGPCEQJN.js} +2 -2
  24. package/dist/{chunk-ZYUVKFX2.js → chunk-GAIXI26T.js} +2 -2
  25. package/dist/{chunk-KHYF6KTY.js → chunk-HJCFLGVT.js} +13 -13
  26. package/dist/chunk-HJCFLGVT.js.map +1 -0
  27. package/dist/{chunk-VDG6Y5L3.js → chunk-HQH44RGL.js} +2 -2
  28. package/dist/chunk-IS2IWRP7.js +4 -0
  29. package/dist/chunk-IS2IWRP7.js.map +1 -0
  30. package/dist/{chunk-BXXP6DTB.js → chunk-JIJDBCV7.js} +2 -2
  31. package/dist/{chunk-Z2QOQBUS.js → chunk-LA6P3TUK.js} +2 -2
  32. package/dist/{chunk-SQ37I2MD.js → chunk-MTDVAO5C.js} +2 -2
  33. package/dist/{chunk-7JUISIE7.js → chunk-QGSUENRK.js} +2 -2
  34. package/dist/{chunk-PNYBZPPB.js → chunk-SK47VJMQ.js} +3 -3
  35. package/dist/{chunk-RWMDDMYX.js → chunk-TFH6S7IT.js} +2 -2
  36. package/dist/{chunk-QY5YUHGW.js → chunk-TVW5ZKJY.js} +2 -2
  37. package/dist/{chunk-RTKSSFX2.js → chunk-UPNKRCFX.js} +7 -7
  38. package/dist/{chunk-IIFHX625.js → chunk-UPQTTOVQ.js} +2 -2
  39. package/dist/{chunk-E3AEOQMK.js → chunk-VVX4RXMV.js} +2 -2
  40. package/dist/{chunk-PLPDG6GE.js → chunk-XBARUCG5.js} +2 -2
  41. package/dist/{chunk-MXDWLBIA.js → chunk-XVYIPVSC.js} +2 -2
  42. package/dist/{chunk-JC5KLH2K.js → chunk-Y7IHOQC7.js} +2 -2
  43. package/dist/cli.js +1 -1
  44. package/dist/cli.js.map +1 -1
  45. package/dist/{client-PWE4BJH4.js → client-EB55Y6EJ.js} +2 -2
  46. package/dist/{config-E53FBZ47.js → config-7DRUA5R3.js} +2 -2
  47. package/dist/{config-mutate-ZEHN6JMZ.js → config-mutate-GGA7VXXH.js} +2 -2
  48. package/dist/config-mutator-POFVILXH.js +2 -0
  49. package/dist/{contributions-CLLCLS3O.js → contributions-TZ26MTML.js} +2 -2
  50. package/dist/{doctor-XKT5FWPO.js → doctor-GTRZ7GWF.js} +2 -2
  51. package/dist/{follow-up-tool-ZFRZUZLI.js → follow-up-tool-PNB7KMCY.js} +2 -2
  52. package/dist/{hub-N5ADP3LO.js → hub-QWJR4E6V.js} +2 -2
  53. package/dist/index.js +1 -1
  54. package/dist/net-family-X2P3OVDP.js +2 -0
  55. package/dist/ntfy-Q4YHFKWW.js +2 -0
  56. package/dist/{program-AMQ7JGHO.js → program-KMUCHLDU.js} +23 -23
  57. package/dist/{program-AMQ7JGHO.js.map → program-KMUCHLDU.js.map} +1 -1
  58. package/dist/{promote-M4UBD2R6.js → promote-HAPXWGYH.js} +2 -2
  59. package/dist/push-PRFZMCIK.js +2 -0
  60. package/dist/push-bridge-276ZLSUT.js +2 -0
  61. package/dist/{query-KMQHF5HW.js → query-ICLOVLZ3.js} +2 -2
  62. package/dist/{query-settings-PENAE4UG.js → query-settings-7AXUOHDL.js} +2 -2
  63. package/dist/{registry-GYKSYSDD.js → registry-IUNSHCOL.js} +2 -2
  64. package/dist/{request-planner-GBX6DHRQ.js → request-planner-TDCLF2CH.js} +2 -2
  65. package/dist/{review-candidates-SYMRJGI2.js → review-candidates-QCBXLWG6.js} +2 -2
  66. package/dist/{routing-S3L44JLL.js → routing-YUP3HHL5.js} +2 -2
  67. package/dist/schedule-tool-3C22NBMN.js +2 -0
  68. package/dist/{scheduler-AW4F5ZKS.js → scheduler-7NK2FH5V.js} +2 -2
  69. package/dist/{seat-QBBNCOFO.js → seat-PTPPQOTP.js} +2 -2
  70. package/dist/{select-ZCFIMYWS.js → select-2XSTWMBR.js} +2 -2
  71. package/dist/{set-enabled-4F27A3U2.js → set-enabled-SS5Q3OX7.js} +2 -2
  72. package/dist/{tool-M462KSMF.js → tool-QCMSXEDB.js} +2 -2
  73. package/dist/{tool-G6XTO24J.js → tool-RK4LDFFH.js} +2 -2
  74. package/dist/{wiki-JXVHIEZI.js → wiki-Q2E44YAE.js} +2 -2
  75. package/dist/wiki-enrich-6ULCDOTX.js +2 -0
  76. package/package.json +1 -1
  77. package/dist/board-dashboard-2A6VSQ7V.js.map +0 -1
  78. package/dist/chunk-GFKLKPPY.js +0 -4
  79. package/dist/chunk-GFKLKPPY.js.map +0 -1
  80. package/dist/chunk-KHYF6KTY.js.map +0 -1
  81. package/dist/chunk-PBP3D2BM.js +0 -2
  82. package/dist/chunk-PBP3D2BM.js.map +0 -1
  83. package/dist/chunk-WCXXXAHV.js.map +0 -1
  84. package/dist/config-mutator-AK775RTM.js +0 -2
  85. package/dist/net-family-OFHIZDHS.js +0 -2
  86. package/dist/ntfy-W56TUC5C.js +0 -2
  87. package/dist/push-B2GNI3VQ.js +0 -2
  88. package/dist/push-bridge-F4PCXWJF.js +0 -2
  89. package/dist/schedule-tool-FXUFRZHR.js +0 -2
  90. package/dist/wiki-enrich-6776OMUB.js +0 -2
  91. /package/dist/{App-TOAWET76.js.map → App-F42CYCKX.js.map} +0 -0
  92. /package/dist/{ChatApp-4DRCRKFS.js.map → ChatApp-RPMQBKHV.js.map} +0 -0
  93. /package/dist/{absorb-eval-OXNL5QGQ.js.map → absorb-eval-HRPEHJSO.js.map} +0 -0
  94. /package/dist/{agent-GALMGMNJ.js.map → agent-L5CJF3GH.js.map} +0 -0
  95. /package/dist/{chunk-XZIKAHFU.js.map → chunk-375MXG3H.js.map} +0 -0
  96. /package/dist/{chunk-5ADXRVYT.js.map → chunk-4HHHVWDB.js.map} +0 -0
  97. /package/dist/{chunk-Q72TK3DO.js.map → chunk-5HLD66CW.js.map} +0 -0
  98. /package/dist/{chunk-5RHCM3L7.js.map → chunk-6AUWEL6V.js.map} +0 -0
  99. /package/dist/{chunk-635B6SXI.js.map → chunk-6VP2KMUM.js.map} +0 -0
  100. /package/dist/{chunk-3K3LRLZX.js.map → chunk-7V73QTQ7.js.map} +0 -0
  101. /package/dist/{chunk-GIQKQD2B.js.map → chunk-AGQYUOZY.js.map} +0 -0
  102. /package/dist/{chunk-2JKKGS77.js.map → chunk-AP4DADXG.js.map} +0 -0
  103. /package/dist/{chunk-DIE6XXJF.js.map → chunk-CZZJEFUM.js.map} +0 -0
  104. /package/dist/{chunk-23LWLYOK.js.map → chunk-DBJUGKX2.js.map} +0 -0
  105. /package/dist/{chunk-B6PMIUVV.js.map → chunk-EGPCEQJN.js.map} +0 -0
  106. /package/dist/{chunk-ZYUVKFX2.js.map → chunk-GAIXI26T.js.map} +0 -0
  107. /package/dist/{chunk-VDG6Y5L3.js.map → chunk-HQH44RGL.js.map} +0 -0
  108. /package/dist/{chunk-BXXP6DTB.js.map → chunk-JIJDBCV7.js.map} +0 -0
  109. /package/dist/{chunk-Z2QOQBUS.js.map → chunk-LA6P3TUK.js.map} +0 -0
  110. /package/dist/{chunk-SQ37I2MD.js.map → chunk-MTDVAO5C.js.map} +0 -0
  111. /package/dist/{chunk-7JUISIE7.js.map → chunk-QGSUENRK.js.map} +0 -0
  112. /package/dist/{chunk-PNYBZPPB.js.map → chunk-SK47VJMQ.js.map} +0 -0
  113. /package/dist/{chunk-RWMDDMYX.js.map → chunk-TFH6S7IT.js.map} +0 -0
  114. /package/dist/{chunk-QY5YUHGW.js.map → chunk-TVW5ZKJY.js.map} +0 -0
  115. /package/dist/{chunk-RTKSSFX2.js.map → chunk-UPNKRCFX.js.map} +0 -0
  116. /package/dist/{chunk-IIFHX625.js.map → chunk-UPQTTOVQ.js.map} +0 -0
  117. /package/dist/{chunk-E3AEOQMK.js.map → chunk-VVX4RXMV.js.map} +0 -0
  118. /package/dist/{chunk-PLPDG6GE.js.map → chunk-XBARUCG5.js.map} +0 -0
  119. /package/dist/{chunk-MXDWLBIA.js.map → chunk-XVYIPVSC.js.map} +0 -0
  120. /package/dist/{chunk-JC5KLH2K.js.map → chunk-Y7IHOQC7.js.map} +0 -0
  121. /package/dist/{client-PWE4BJH4.js.map → client-EB55Y6EJ.js.map} +0 -0
  122. /package/dist/{config-E53FBZ47.js.map → config-7DRUA5R3.js.map} +0 -0
  123. /package/dist/{config-mutate-ZEHN6JMZ.js.map → config-mutate-GGA7VXXH.js.map} +0 -0
  124. /package/dist/{config-mutator-AK775RTM.js.map → config-mutator-POFVILXH.js.map} +0 -0
  125. /package/dist/{contributions-CLLCLS3O.js.map → contributions-TZ26MTML.js.map} +0 -0
  126. /package/dist/{doctor-XKT5FWPO.js.map → doctor-GTRZ7GWF.js.map} +0 -0
  127. /package/dist/{follow-up-tool-ZFRZUZLI.js.map → follow-up-tool-PNB7KMCY.js.map} +0 -0
  128. /package/dist/{hub-N5ADP3LO.js.map → hub-QWJR4E6V.js.map} +0 -0
  129. /package/dist/{net-family-OFHIZDHS.js.map → net-family-X2P3OVDP.js.map} +0 -0
  130. /package/dist/{ntfy-W56TUC5C.js.map → ntfy-Q4YHFKWW.js.map} +0 -0
  131. /package/dist/{promote-M4UBD2R6.js.map → promote-HAPXWGYH.js.map} +0 -0
  132. /package/dist/{push-B2GNI3VQ.js.map → push-PRFZMCIK.js.map} +0 -0
  133. /package/dist/{push-bridge-F4PCXWJF.js.map → push-bridge-276ZLSUT.js.map} +0 -0
  134. /package/dist/{query-KMQHF5HW.js.map → query-ICLOVLZ3.js.map} +0 -0
  135. /package/dist/{query-settings-PENAE4UG.js.map → query-settings-7AXUOHDL.js.map} +0 -0
  136. /package/dist/{registry-GYKSYSDD.js.map → registry-IUNSHCOL.js.map} +0 -0
  137. /package/dist/{request-planner-GBX6DHRQ.js.map → request-planner-TDCLF2CH.js.map} +0 -0
  138. /package/dist/{review-candidates-SYMRJGI2.js.map → review-candidates-QCBXLWG6.js.map} +0 -0
  139. /package/dist/{routing-S3L44JLL.js.map → routing-YUP3HHL5.js.map} +0 -0
  140. /package/dist/{schedule-tool-FXUFRZHR.js.map → schedule-tool-3C22NBMN.js.map} +0 -0
  141. /package/dist/{scheduler-AW4F5ZKS.js.map → scheduler-7NK2FH5V.js.map} +0 -0
  142. /package/dist/{seat-QBBNCOFO.js.map → seat-PTPPQOTP.js.map} +0 -0
  143. /package/dist/{select-ZCFIMYWS.js.map → select-2XSTWMBR.js.map} +0 -0
  144. /package/dist/{set-enabled-4F27A3U2.js.map → set-enabled-SS5Q3OX7.js.map} +0 -0
  145. /package/dist/{tool-M462KSMF.js.map → tool-QCMSXEDB.js.map} +0 -0
  146. /package/dist/{tool-G6XTO24J.js.map → tool-RK4LDFFH.js.map} +0 -0
  147. /package/dist/{wiki-JXVHIEZI.js.map → wiki-Q2E44YAE.js.map} +0 -0
  148. /package/dist/{wiki-enrich-6776OMUB.js.map → wiki-enrich-6ULCDOTX.js.map} +0 -0
@@ -1,4 +0,0 @@
1
- var $=[1e3,3e3,8e3],w=2e4;function b(e){let t=e,n=t?.message??String(e),s=t?.cause;return s?.code?`${n} code=${s.code}`:s?.message&&s.message!==n?`${n} (${s.message})`:n}var A=new Set(["ECONNREFUSED","ETIMEDOUT","ENETUNREACH","EHOSTUNREACH","EADDRNOTAVAIL","ENOTFOUND","EAI_AGAIN","UND_ERR_CONNECT_TIMEOUT"]);function M(e){let t=e?.cause?.code;return!!t&&A.has(t)}function N(e){return e===429||e===503}function m(e){return/^[\x20-\x7E]*$/.test(e)?e:`=?UTF-8?B?${Buffer.from(e,"utf8").toString("base64")}?=`}function D(e){let t=e.split(`
2
- `),n=(t[0]??"").trim(),s=t.slice(1).join(`
3
- `).trim();return s?n.length===0||n.length>80?{body:e.trim()}:{title:n,body:s}:{body:e.trim()}}var y=class{name="ntfy";config;log;constructor(t,n=console.error.bind(console,"[ntfy]")){this.config=t,this.log=n}async start(){this.log(`ntfy: ready (${this.serverUrl()}/${this.config.topic})`)}async stop(){}onMessage(t){}serverUrl(){return(this.config.server||"https://ntfy.sh").replace(/\/+$/,"")}async send(t){let n=(t.chatId||"").trim(),s=n&&n!=="default"?n:this.config.topic;if(!s)throw new Error("ntfy: no topic (pass chatId, or set channels.ntfy.topic)");let f=D(t.text||""),p=f.title||this.config.defaultTitle||"AgentX",c={"Content-Type":"text/plain; charset=utf-8",Title:m(p),Priority:String(this.config.defaultPriority??3)};if(this.config.token&&(c.Authorization=`Bearer ${this.config.token}`),t.parseMode==="markdown"&&(c.Markdown="yes"),t.buttons?.length){let i=t.buttons.slice(0,3).map(r=>`view, ${r.label.replace(/[,;]/g," ")}, ${r.url}`).join("; ");c.Actions=m(i)}let E=`${this.serverUrl()}/${encodeURIComponent(s)}`,T=f.body||t.text||"",d=this.config.retryDelaysMs??$,u=d.length+1,h=Date.now()+(this.config.sendTimeoutMs??w);for(let i=1;;i++){let r,a,l=!1;try{let o=AbortSignal.timeout(Math.max(1,h-Date.now()));r=await fetch(E,{method:"POST",headers:c,body:T,signal:o})}catch(o){a=new Error(`ntfy: ${b(o)}`,{cause:o}),l=M(o)}if(r){if(r.ok)return(await r.json().catch(()=>null))?.id;let o=await r.text().catch(()=>"");a=new Error(`ntfy: ${r.status} ${o.slice(0,200)}`),l=N(r.status)}let g=d[i-1];if(!l||i>=u||Date.now()+g>=h)throw this.log(`ntfy: send failed after ${i} attempt(s): ${a.message}`),a;this.log(`ntfy: attempt ${i}/${u} failed (${a.message}); retrying in ${g} ms`),await new Promise(o=>setTimeout(o,g))}}};export{b as a,D as b,y as c};
4
- //# sourceMappingURL=chunk-GFKLKPPY.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/channels/ntfy.ts"],"sourcesContent":["import type { ChannelAdapter, IncomingMessage, OutgoingMessage } from \"./types\"\n\n// --- ntfy channel — push notifications to the operator's phone ---\n//\n// Outbound only. ntfy has an inbound side (SSE subscribe), but nothing here\n// wants it: a push notification is a one-way tap on the shoulder, and replies\n// come back through the channels that already carry conversation (Telegram,\n// WhatsApp) or through POST /ask when Siri asks a follow-up.\n//\n// Registering it as a ChannelAdapter rather than a bespoke notifier is what\n// makes it free everywhere: notifications.destination, POST /send, cron\n// failure pings, and the agent-facing `channel` action all funnel through\n// router.sendOutbound() and already know how to address a channel + chatId.\n//\n// Addressing: `chatId` is the ntfy topic. The literal `\"default\"` (and an\n// empty string) resolve to the configured topic instead. That indirection\n// exists so agents never have to carry the topic in their prompts — on the\n// public ntfy.sh the topic IS the credential, and every caller that funnels\n// through the router (POST /send, channel.reply) requires a non-empty chatId.\n\nexport interface NtfyConfig {\n /** Base URL of the ntfy server. Default is the public ntfy.sh. */\n server?: string\n /** Default topic when an OutgoingMessage carries no chatId. */\n topic: string\n /** Access token for protected topics (ntfy `Authorization: Bearer`). */\n token?: string\n /** 1 (min) .. 5 (max). ntfy's default is 3. */\n defaultPriority?: number\n /** Notification title. Per-message titles override it. */\n defaultTitle?: string\n /** Test hook, not in the config schema: waits between attempts when a\n * publish is safe to repeat. One attempt more than there are entries. */\n retryDelaysMs?: number[]\n /** Test hook, not in the config schema: time limit for one send, all\n * attempts and waits included. */\n sendTimeoutMs?: number\n}\n\nconst DEFAULT_RETRY_DELAYS_MS = [1000, 3000, 8000]\nconst DEFAULT_SEND_TIMEOUT_MS = 20_000\n\n/** `fetch failed` hides the reason in `cause`; surface its code so a log\n * line says ETIMEDOUT or ECONNREFUSED rather than nothing useful (#930). */\nexport function describeFetchError(e: unknown): string {\n const err = e as { message?: string; cause?: { code?: string; message?: string } }\n const message = err?.message ?? String(e)\n const cause = err?.cause\n if (cause?.code) return `${message} code=${cause.code}`\n if (cause?.message && cause.message !== message) return `${message} (${cause.message})`\n return message\n}\n\n// A publish is retried only when the server cannot have stored it: ntfy has\n// no key to drop a repeat, so re-posting after a 500 or a reset mid-response\n// could put the same notification on the phone twice.\n\n/** The connection never opened, so the request never reached the server. */\nconst CONNECT_FAILURE_CODES = new Set([\n \"ECONNREFUSED\", \"ETIMEDOUT\", \"ENETUNREACH\", \"EHOSTUNREACH\", \"EADDRNOTAVAIL\",\n \"ENOTFOUND\", \"EAI_AGAIN\", \"UND_ERR_CONNECT_TIMEOUT\",\n])\n\nfunction isRetryableFetchError(e: unknown): boolean {\n const code = (e as { cause?: { code?: string } })?.cause?.code\n return !!code && CONNECT_FAILURE_CODES.has(code)\n}\n\n/** 429 and 503 say the server turned the request away without handling it. */\nfunction isRetryableStatus(status: number): boolean {\n return status === 429 || status === 503\n}\n\n/**\n * ntfy requires header values to be ASCII. Titles and tags routinely aren't\n * (French accents, Arabic), so non-ASCII values go out as RFC 2047 encoded\n * words, which ntfy decodes. Pure-ASCII values are passed through untouched\n * so the common case stays readable in logs.\n */\nfunction encodeHeader(value: string): string {\n // eslint-disable-next-line no-control-regex\n if (/^[\\x20-\\x7E]*$/.test(value)) return value\n return `=?UTF-8?B?${Buffer.from(value, \"utf8\").toString(\"base64\")}?=`\n}\n\n/** First line of the body, when it reads like a title (short, no trailing\n * punctuation that implies a sentence continues). Lets an agent write a\n * single blob and still get a well-formed notification. */\nexport function splitTitle(text: string): { title?: string; body: string } {\n const lines = text.split(\"\\n\")\n const first = (lines[0] ?? \"\").trim()\n const rest = lines.slice(1).join(\"\\n\").trim()\n if (!rest) return { body: text.trim() }\n if (first.length === 0 || first.length > 80) return { body: text.trim() }\n return { title: first, body: rest }\n}\n\nexport class NtfyAdapter implements ChannelAdapter {\n readonly name = \"ntfy\"\n private config: NtfyConfig\n private log: (...args: unknown[]) => void\n\n constructor(config: NtfyConfig, log: (...args: unknown[]) => void = console.error.bind(console, \"[ntfy]\")) {\n this.config = config\n this.log = log\n }\n\n async start(): Promise<void> {\n this.log(`ntfy: ready (${this.serverUrl()}/${this.config.topic})`)\n }\n\n async stop(): Promise<void> {}\n\n /** No inbound side — the handler is accepted and never invoked, which\n * satisfies router.addChannel() without pretending to poll. */\n onMessage(_handler: (msg: IncomingMessage) => Promise<void>): void {}\n\n private serverUrl(): string {\n return (this.config.server || \"https://ntfy.sh\").replace(/\\/+$/, \"\")\n }\n\n async send(msg: OutgoingMessage): Promise<string | void> {\n const requested = (msg.chatId || \"\").trim()\n const topic = requested && requested !== \"default\" ? requested : this.config.topic\n if (!topic) throw new Error(\"ntfy: no topic (pass chatId, or set channels.ntfy.topic)\")\n\n const split = splitTitle(msg.text || \"\")\n const title = split.title || this.config.defaultTitle || \"AgentX\"\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"text/plain; charset=utf-8\",\n \"Title\": encodeHeader(title),\n \"Priority\": String(this.config.defaultPriority ?? 3),\n }\n if (this.config.token) headers[\"Authorization\"] = `Bearer ${this.config.token}`\n if (msg.parseMode === \"markdown\") headers[\"Markdown\"] = \"yes\"\n\n // URL buttons map onto ntfy's view actions, so an alert can carry\n // \"open the MR\" without the operator hunting for it.\n if (msg.buttons?.length) {\n const actions = msg.buttons\n .slice(0, 3) // ntfy caps at 3\n .map(b => `view, ${b.label.replace(/[,;]/g, \" \")}, ${b.url}`)\n .join(\"; \")\n headers[\"Actions\"] = encodeHeader(actions)\n }\n\n const url = `${this.serverUrl()}/${encodeURIComponent(topic)}`\n const body = split.body || msg.text || \"\"\n const delays = this.config.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS\n const attempts = delays.length + 1\n // Each try can spend several seconds per address on a dead link, so the\n // whole send gets one time limit and callers never wait much past it.\n const deadline = Date.now() + (this.config.sendTimeoutMs ?? DEFAULT_SEND_TIMEOUT_MS)\n\n // A slow or flapping link loses pushes that a few seconds later would\n // go through. Retry only what cannot have been stored (see above).\n for (let attempt = 1; ; attempt++) {\n let res: Response | undefined\n let failure!: Error\n let retryable = false\n try {\n const signal = AbortSignal.timeout(Math.max(1, deadline - Date.now()))\n res = await fetch(url, { method: \"POST\", headers, body, signal })\n } catch (e) {\n failure = new Error(`ntfy: ${describeFetchError(e)}`, { cause: e })\n retryable = isRetryableFetchError(e)\n }\n if (res) {\n if (res.ok) {\n const json = await res.json().catch(() => null) as { id?: string } | null\n return json?.id\n }\n const detail = await res.text().catch(() => \"\")\n failure = new Error(`ntfy: ${res.status} ${detail.slice(0, 200)}`)\n retryable = isRetryableStatus(res.status)\n }\n const wait = delays[attempt - 1]\n if (!retryable || attempt >= attempts || Date.now() + wait >= deadline) {\n this.log(`ntfy: send failed after ${attempt} attempt(s): ${failure.message}`)\n throw failure\n }\n this.log(`ntfy: attempt ${attempt}/${attempts} failed (${failure.message}); retrying in ${wait} ms`)\n await new Promise(r => setTimeout(r, wait))\n }\n }\n}\n"],"mappings":"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","names":["DEFAULT_RETRY_DELAYS_MS","DEFAULT_SEND_TIMEOUT_MS","describeFetchError","err","message","cause","CONNECT_FAILURE_CODES","isRetryableFetchError","code","isRetryableStatus","status","encodeHeader","value","splitTitle","text","lines","first","rest","NtfyAdapter","config","log","_handler","msg","requested","topic","split","title","headers","actions","b","url","body","delays","attempts","deadline","attempt","res","failure","retryable","signal","e","detail","wait","r"]}