@mono-agent/agent-app 0.6.2 → 0.9.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 (313) hide show
  1. package/README.md +259 -19
  2. package/dist/account-home.d.ts +6 -0
  3. package/dist/account-home.d.ts.map +1 -0
  4. package/dist/account-home.js +9 -0
  5. package/dist/account-home.js.map +1 -0
  6. package/dist/adapter-send-proxy.d.ts +18 -0
  7. package/dist/adapter-send-proxy.d.ts.map +1 -0
  8. package/dist/adapter-send-proxy.js +229 -0
  9. package/dist/adapter-send-proxy.js.map +1 -0
  10. package/dist/adapter-send-tools-main.js +62 -4
  11. package/dist/adapter-send-tools-main.js.map +1 -1
  12. package/dist/adapter-send-tools.d.ts +33 -6
  13. package/dist/adapter-send-tools.d.ts.map +1 -1
  14. package/dist/adapter-send-tools.js +485 -87
  15. package/dist/adapter-send-tools.js.map +1 -1
  16. package/dist/app-config.d.ts +3 -1
  17. package/dist/app-config.d.ts.map +1 -1
  18. package/dist/app-config.js +16 -5
  19. package/dist/app-config.js.map +1 -1
  20. package/dist/app.d.ts +27 -0
  21. package/dist/app.d.ts.map +1 -1
  22. package/dist/app.js +761 -147
  23. package/dist/app.js.map +1 -1
  24. package/dist/background-environment.d.ts +16 -0
  25. package/dist/background-environment.d.ts.map +1 -0
  26. package/dist/background-environment.js +68 -0
  27. package/dist/background-environment.js.map +1 -0
  28. package/dist/background-runtime.d.ts +62 -0
  29. package/dist/background-runtime.d.ts.map +1 -0
  30. package/dist/background-runtime.js +1115 -0
  31. package/dist/background-runtime.js.map +1 -0
  32. package/dist/background-snapshot-key.d.ts +13 -0
  33. package/dist/background-snapshot-key.d.ts.map +1 -0
  34. package/dist/background-snapshot-key.js +194 -0
  35. package/dist/background-snapshot-key.js.map +1 -0
  36. package/dist/background-snapshot.d.ts +96 -0
  37. package/dist/background-snapshot.d.ts.map +1 -0
  38. package/dist/background-snapshot.js +450 -0
  39. package/dist/background-snapshot.js.map +1 -0
  40. package/dist/background-worker-lease.d.ts +39 -0
  41. package/dist/background-worker-lease.d.ts.map +1 -0
  42. package/dist/background-worker-lease.js +356 -0
  43. package/dist/background-worker-lease.js.map +1 -0
  44. package/dist/background.d.ts +74 -2
  45. package/dist/background.d.ts.map +1 -1
  46. package/dist/background.js +815 -73
  47. package/dist/background.js.map +1 -1
  48. package/dist/broadcast-recorder.d.ts.map +1 -1
  49. package/dist/broadcast-recorder.js +24 -2
  50. package/dist/broadcast-recorder.js.map +1 -1
  51. package/dist/channel-plugins.d.ts +2 -0
  52. package/dist/channel-plugins.d.ts.map +1 -1
  53. package/dist/channel-plugins.js +8 -0
  54. package/dist/channel-plugins.js.map +1 -1
  55. package/dist/channels.d.ts +10 -0
  56. package/dist/channels.d.ts.map +1 -1
  57. package/dist/channels.js +87 -9
  58. package/dist/channels.js.map +1 -1
  59. package/dist/cli.d.ts +86 -4
  60. package/dist/cli.d.ts.map +1 -1
  61. package/dist/cli.js +2421 -143
  62. package/dist/cli.js.map +1 -1
  63. package/dist/config-reference.d.ts.map +1 -1
  64. package/dist/config-reference.js +448 -6
  65. package/dist/config-reference.js.map +1 -1
  66. package/dist/configuration-proposal-main.d.ts +3 -0
  67. package/dist/configuration-proposal-main.d.ts.map +1 -0
  68. package/dist/configuration-proposal-main.js +13 -0
  69. package/dist/configuration-proposal-main.js.map +1 -0
  70. package/dist/configuration-proposal-tool.d.ts +33 -0
  71. package/dist/configuration-proposal-tool.d.ts.map +1 -0
  72. package/dist/configuration-proposal-tool.js +188 -0
  73. package/dist/configuration-proposal-tool.js.map +1 -0
  74. package/dist/configured-agent.d.ts +16 -0
  75. package/dist/configured-agent.d.ts.map +1 -1
  76. package/dist/configured-agent.js +165 -18
  77. package/dist/configured-agent.js.map +1 -1
  78. package/dist/consumer-contract.d.ts +3 -0
  79. package/dist/consumer-contract.d.ts.map +1 -1
  80. package/dist/consumer-contract.js +44 -1
  81. package/dist/consumer-contract.js.map +1 -1
  82. package/dist/continuation-command.d.ts +15 -0
  83. package/dist/continuation-command.d.ts.map +1 -0
  84. package/dist/continuation-command.js +170 -0
  85. package/dist/continuation-command.js.map +1 -0
  86. package/dist/continuation-config.d.ts +25 -0
  87. package/dist/continuation-config.d.ts.map +1 -0
  88. package/dist/continuation-config.js +236 -0
  89. package/dist/continuation-config.js.map +1 -0
  90. package/dist/continuation-service.d.ts +99 -0
  91. package/dist/continuation-service.d.ts.map +1 -0
  92. package/dist/continuation-service.js +1313 -0
  93. package/dist/continuation-service.js.map +1 -0
  94. package/dist/continuation-store.d.ts +104 -0
  95. package/dist/continuation-store.d.ts.map +1 -0
  96. package/dist/continuation-store.js +688 -0
  97. package/dist/continuation-store.js.map +1 -0
  98. package/dist/continuations.d.ts +167 -0
  99. package/dist/continuations.d.ts.map +1 -0
  100. package/dist/continuations.js +71 -0
  101. package/dist/continuations.js.map +1 -0
  102. package/dist/doctor.d.ts +29 -5
  103. package/dist/doctor.d.ts.map +1 -1
  104. package/dist/doctor.js +1611 -116
  105. package/dist/doctor.js.map +1 -1
  106. package/dist/first-run-managed-memory.d.ts +39 -0
  107. package/dist/first-run-managed-memory.d.ts.map +1 -0
  108. package/dist/first-run-managed-memory.js +584 -0
  109. package/dist/first-run-managed-memory.js.map +1 -0
  110. package/dist/first-run-readiness.d.ts +111 -0
  111. package/dist/first-run-readiness.d.ts.map +1 -0
  112. package/dist/first-run-readiness.js +728 -0
  113. package/dist/first-run-readiness.js.map +1 -0
  114. package/dist/index.d.ts +17 -3
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js +8 -1
  117. package/dist/index.js.map +1 -1
  118. package/dist/init.d.ts +95 -3
  119. package/dist/init.d.ts.map +1 -1
  120. package/dist/init.js +1218 -24
  121. package/dist/init.js.map +1 -1
  122. package/dist/interaction-bridge.d.ts +25 -1
  123. package/dist/interaction-bridge.d.ts.map +1 -1
  124. package/dist/interaction-bridge.js +281 -19
  125. package/dist/interaction-bridge.js.map +1 -1
  126. package/dist/launchd.d.ts +16 -6
  127. package/dist/launchd.d.ts.map +1 -1
  128. package/dist/launchd.js +30 -15
  129. package/dist/launchd.js.map +1 -1
  130. package/dist/local-configuration.d.ts +99 -0
  131. package/dist/local-configuration.d.ts.map +1 -0
  132. package/dist/local-configuration.js +1299 -0
  133. package/dist/local-configuration.js.map +1 -0
  134. package/dist/managed-runtime-packages.d.ts +9 -0
  135. package/dist/managed-runtime-packages.d.ts.map +1 -0
  136. package/dist/managed-runtime-packages.js +56 -0
  137. package/dist/managed-runtime-packages.js.map +1 -0
  138. package/dist/memory-command.d.ts +4 -0
  139. package/dist/memory-command.d.ts.map +1 -1
  140. package/dist/memory-command.js +751 -27
  141. package/dist/memory-command.js.map +1 -1
  142. package/dist/memory-embedding-service.d.ts +33 -0
  143. package/dist/memory-embedding-service.d.ts.map +1 -0
  144. package/dist/memory-embedding-service.js +207 -0
  145. package/dist/memory-embedding-service.js.map +1 -0
  146. package/dist/memory-recall.d.ts +43 -14
  147. package/dist/memory-recall.d.ts.map +1 -1
  148. package/dist/memory-recall.js +103 -33
  149. package/dist/memory-recall.js.map +1 -1
  150. package/dist/memory-retrieval.d.ts +66 -0
  151. package/dist/memory-retrieval.d.ts.map +1 -0
  152. package/dist/memory-retrieval.js +332 -0
  153. package/dist/memory-retrieval.js.map +1 -0
  154. package/dist/modules/base.d.ts +6 -5
  155. package/dist/modules/base.d.ts.map +1 -1
  156. package/dist/modules/base.js +11 -7
  157. package/dist/modules/base.js.map +1 -1
  158. package/dist/modules/catalog.d.ts.map +1 -1
  159. package/dist/modules/catalog.js +141 -25
  160. package/dist/modules/catalog.js.map +1 -1
  161. package/dist/modules/index.d.ts +2 -2
  162. package/dist/modules/index.d.ts.map +1 -1
  163. package/dist/modules/index.js +1 -1
  164. package/dist/modules/index.js.map +1 -1
  165. package/dist/modules/known-tools.d.ts +3 -0
  166. package/dist/modules/known-tools.d.ts.map +1 -1
  167. package/dist/modules/known-tools.js +11 -1
  168. package/dist/modules/known-tools.js.map +1 -1
  169. package/dist/modules/types.d.ts +20 -6
  170. package/dist/modules/types.d.ts.map +1 -1
  171. package/dist/modules/types.js.map +1 -1
  172. package/dist/notify-runtime.d.ts +26 -0
  173. package/dist/notify-runtime.d.ts.map +1 -0
  174. package/dist/notify-runtime.js +27 -0
  175. package/dist/notify-runtime.js.map +1 -0
  176. package/dist/notify-tool.d.ts +51 -0
  177. package/dist/notify-tool.d.ts.map +1 -0
  178. package/dist/notify-tool.js +182 -0
  179. package/dist/notify-tool.js.map +1 -0
  180. package/dist/package-version.d.ts +3 -0
  181. package/dist/package-version.d.ts.map +1 -0
  182. package/dist/package-version.js +14 -0
  183. package/dist/package-version.js.map +1 -0
  184. package/dist/pi-auth-store-inspection.d.ts +21 -0
  185. package/dist/pi-auth-store-inspection.d.ts.map +1 -0
  186. package/dist/pi-auth-store-inspection.js +120 -0
  187. package/dist/pi-auth-store-inspection.js.map +1 -0
  188. package/dist/pi-oauth-login-main.d.ts +3 -0
  189. package/dist/pi-oauth-login-main.d.ts.map +1 -0
  190. package/dist/pi-oauth-login-main.js +14 -0
  191. package/dist/pi-oauth-login-main.js.map +1 -0
  192. package/dist/pi-oauth-login.d.ts +22 -0
  193. package/dist/pi-oauth-login.d.ts.map +1 -0
  194. package/dist/pi-oauth-login.js +79 -0
  195. package/dist/pi-oauth-login.js.map +1 -0
  196. package/dist/proactive-notify.d.ts +2 -0
  197. package/dist/proactive-notify.d.ts.map +1 -1
  198. package/dist/proactive-notify.js +1 -0
  199. package/dist/proactive-notify.js.map +1 -1
  200. package/dist/process-incarnation.d.ts +23 -0
  201. package/dist/process-incarnation.d.ts.map +1 -0
  202. package/dist/process-incarnation.js +208 -0
  203. package/dist/process-incarnation.js.map +1 -0
  204. package/dist/project-skills.d.ts +40 -0
  205. package/dist/project-skills.d.ts.map +1 -0
  206. package/dist/project-skills.js +573 -0
  207. package/dist/project-skills.js.map +1 -0
  208. package/dist/provider-setup.d.ts +117 -2
  209. package/dist/provider-setup.d.ts.map +1 -1
  210. package/dist/provider-setup.js +1505 -49
  211. package/dist/provider-setup.js.map +1 -1
  212. package/dist/readiness-probe-worker.d.ts +12 -0
  213. package/dist/readiness-probe-worker.d.ts.map +1 -0
  214. package/dist/readiness-probe-worker.js +276 -0
  215. package/dist/readiness-probe-worker.js.map +1 -0
  216. package/dist/readiness-probe.d.ts +100 -0
  217. package/dist/readiness-probe.d.ts.map +1 -0
  218. package/dist/readiness-probe.js +780 -0
  219. package/dist/readiness-probe.js.map +1 -0
  220. package/dist/recipes/base.d.ts +15 -0
  221. package/dist/recipes/base.d.ts.map +1 -0
  222. package/dist/recipes/base.js +51 -0
  223. package/dist/recipes/base.js.map +1 -0
  224. package/dist/recipes/catalog.d.ts +4 -0
  225. package/dist/recipes/catalog.d.ts.map +1 -0
  226. package/dist/recipes/catalog.js +525 -0
  227. package/dist/recipes/catalog.js.map +1 -0
  228. package/dist/recipes/index.d.ts +11 -0
  229. package/dist/recipes/index.d.ts.map +1 -0
  230. package/dist/recipes/index.js +14 -0
  231. package/dist/recipes/index.js.map +1 -0
  232. package/dist/recipes/types.d.ts +70 -0
  233. package/dist/recipes/types.d.ts.map +1 -0
  234. package/dist/recipes/types.js +15 -0
  235. package/dist/recipes/types.js.map +1 -0
  236. package/dist/request-model-override.d.ts +43 -1
  237. package/dist/request-model-override.d.ts.map +1 -1
  238. package/dist/request-model-override.js +178 -19
  239. package/dist/request-model-override.js.map +1 -1
  240. package/dist/run-history.d.ts +32 -0
  241. package/dist/run-history.d.ts.map +1 -0
  242. package/dist/run-history.js +859 -0
  243. package/dist/run-history.js.map +1 -0
  244. package/dist/runs-health.d.ts.map +1 -1
  245. package/dist/runs-health.js +12 -4
  246. package/dist/runs-health.js.map +1 -1
  247. package/dist/runtime-option-extensions.d.ts +14 -0
  248. package/dist/runtime-option-extensions.d.ts.map +1 -0
  249. package/dist/runtime-option-extensions.js +98 -0
  250. package/dist/runtime-option-extensions.js.map +1 -0
  251. package/dist/runtime-routes.d.ts +9 -0
  252. package/dist/runtime-routes.d.ts.map +1 -0
  253. package/dist/runtime-routes.js +13 -0
  254. package/dist/runtime-routes.js.map +1 -0
  255. package/dist/sandbox-manager.d.ts +86 -0
  256. package/dist/sandbox-manager.d.ts.map +1 -0
  257. package/dist/sandbox-manager.js +1402 -0
  258. package/dist/sandbox-manager.js.map +1 -0
  259. package/dist/setup.d.ts +29 -0
  260. package/dist/setup.d.ts.map +1 -0
  261. package/dist/setup.js +97 -0
  262. package/dist/setup.js.map +1 -0
  263. package/dist/supermemory-plugin.d.ts +56 -0
  264. package/dist/supermemory-plugin.d.ts.map +1 -0
  265. package/dist/supermemory-plugin.js +142 -0
  266. package/dist/supermemory-plugin.js.map +1 -0
  267. package/dist/tui-command.d.ts +56 -0
  268. package/dist/tui-command.d.ts.map +1 -1
  269. package/dist/tui-command.js +305 -31
  270. package/dist/tui-command.js.map +1 -1
  271. package/dist/web-command.d.ts +8 -0
  272. package/dist/web-command.d.ts.map +1 -1
  273. package/dist/web-command.js +174 -17
  274. package/dist/web-command.js.map +1 -1
  275. package/dist/wizard/answers.d.ts +31 -4
  276. package/dist/wizard/answers.d.ts.map +1 -1
  277. package/dist/wizard/answers.js +141 -29
  278. package/dist/wizard/answers.js.map +1 -1
  279. package/dist/wizard/from-flags.d.ts +7 -0
  280. package/dist/wizard/from-flags.d.ts.map +1 -1
  281. package/dist/wizard/from-flags.js +36 -2
  282. package/dist/wizard/from-flags.js.map +1 -1
  283. package/dist/wizard/index.d.ts +4 -4
  284. package/dist/wizard/index.d.ts.map +1 -1
  285. package/dist/wizard/index.js +2 -2
  286. package/dist/wizard/index.js.map +1 -1
  287. package/dist/wizard/model-discovery.d.ts +33 -2
  288. package/dist/wizard/model-discovery.d.ts.map +1 -1
  289. package/dist/wizard/model-discovery.js +826 -108
  290. package/dist/wizard/model-discovery.js.map +1 -1
  291. package/dist/wizard/presets.d.ts +1 -1
  292. package/dist/wizard/presets.d.ts.map +1 -1
  293. package/dist/wizard/presets.js +7 -12
  294. package/dist/wizard/presets.js.map +1 -1
  295. package/dist/wizard/prompts.d.ts +56 -9
  296. package/dist/wizard/prompts.d.ts.map +1 -1
  297. package/dist/wizard/prompts.js +172 -20
  298. package/dist/wizard/prompts.js.map +1 -1
  299. package/dist/wizard/run.d.ts +59 -3
  300. package/dist/wizard/run.d.ts.map +1 -1
  301. package/dist/wizard/run.js +1290 -191
  302. package/dist/wizard/run.js.map +1 -1
  303. package/package.json +21 -16
  304. package/resources/srt/package-lock.json +66 -0
  305. package/resources/srt/package.json +9 -0
  306. package/schema/mono-agent.config.schema.json +587 -20
  307. package/skills/mono-agent-composer/SKILL.md +6 -6
  308. package/skills/mono-agent-composer/references/config-blueprint.md +11 -10
  309. package/skills/mono-agent-composer/references/discovery-questions.md +33 -18
  310. package/skills/mono-agent-composer/references/feature-coverage.md +14 -12
  311. package/skills/mono-agent-composer/references/package-map.md +2 -2
  312. package/skills/mono-agent-composer/references/playbooks.md +8 -7
  313. package/skills/mono-agent-composer/references/validation.md +3 -3
@@ -0,0 +1,51 @@
1
+ import type { MonoAgentAppLogger } from "./channels.js";
2
+ import type { NotifyDeliveryResult } from "./proactive-notify.js";
3
+ /**
4
+ * In-process MCP server that exposes the proactive-notification tools to the agent.
5
+ *
6
+ * Unlike `memory_recall`/the adapter send tools (stdio children that re-derive
7
+ * everything from config/disk), notification delivery has to run a real turn on a
8
+ * destination channel's LIVE session, so the handler must reach the app's running
9
+ * channel registry — which only exists in this process. We therefore host the
10
+ * tools over loopback HTTP (the one MCP transport the runtime's client supports
11
+ * for an in-process server) and close over app-supplied delivery/discovery hooks.
12
+ *
13
+ * Two tools, both intended for proactive cron/webhook turns (the runtime extension
14
+ * only injects this server for those):
15
+ * - `list_notify_destinations` — discover the conversations the agent may notify
16
+ * (answers "how do I get a conversationId?" when there is no triggering payload).
17
+ * - `notify_conversation` — deliver a message as a real turn into one of them.
18
+ */
19
+ export declare const NOTIFY_TOOLS_MCP_SERVER_NAME = "mono-agent-notify";
20
+ /** A conversation the agent may proactively notify, surfaced to the model for discovery. */
21
+ export interface NotifyToolDestination {
22
+ /** Destination conversationId to pass to `notify_conversation`, e.g. `telegram:42`. */
23
+ readonly conversationId: string;
24
+ /** Owning channel id (telegram/slack). */
25
+ readonly channelId: string;
26
+ /** ISO timestamp of the most recent turn on this conversation, if known. */
27
+ readonly lastSeen?: string;
28
+ /** True when this is an allowlisted destination the agent has not yet conversed with. */
29
+ readonly fromAllowlist?: boolean;
30
+ }
31
+ export interface NotifyToolsDeps {
32
+ /** Deliver `text` as a real turn into `conversationId` (allowlist-enforced by the owning channel). */
33
+ readonly deliver: (conversationId: string, text: string) => Promise<NotifyDeliveryResult>;
34
+ /** The conversations the agent may notify right now (seen + single-allowlist destinations). */
35
+ readonly listDestinations: () => Promise<readonly NotifyToolDestination[]>;
36
+ readonly logger?: MonoAgentAppLogger | undefined;
37
+ }
38
+ export interface NotifyToolsServer {
39
+ /** Loopback URL the runtime's MCP client connects to (`http://127.0.0.1:<port>/mcp`). */
40
+ readonly url: string;
41
+ /** Bearer token required on every request. */
42
+ readonly token: string;
43
+ close(): Promise<void>;
44
+ }
45
+ /**
46
+ * Start the in-process notify MCP server on an ephemeral loopback port. Stateless:
47
+ * each request gets a fresh `McpServer`+transport (the tools are pure request/response),
48
+ * which sidesteps session bookkeeping and concurrent-trigger races.
49
+ */
50
+ export declare function startNotifyToolsServer(deps: NotifyToolsDeps): Promise<NotifyToolsServer>;
51
+ //# sourceMappingURL=notify-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify-tool.d.ts","sourceRoot":"","sources":["../src/notify-tool.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAElE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,4BAA4B,sBAAsB,CAAC;AAEhE,4FAA4F;AAC5F,MAAM,WAAW,qBAAqB;IACpC,uFAAuF;IACvF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,yFAAyF;IACzF,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,sGAAsG;IACtG,QAAQ,CAAC,OAAO,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAC1F,+FAA+F;IAC/F,QAAQ,CAAC,gBAAgB,EAAE,MAAM,OAAO,CAAC,SAAS,qBAAqB,EAAE,CAAC,CAAC;IAC3E,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;CAClD;AAED,MAAM,WAAW,iBAAiB;IAChC,yFAAyF;IACzF,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAID;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgC9F"}
@@ -0,0 +1,182 @@
1
+ import { createServer } from "node:http";
2
+ import { randomBytes, timingSafeEqual } from "node:crypto";
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
5
+ import * as z from "zod/v4";
6
+ /**
7
+ * In-process MCP server that exposes the proactive-notification tools to the agent.
8
+ *
9
+ * Unlike `memory_recall`/the adapter send tools (stdio children that re-derive
10
+ * everything from config/disk), notification delivery has to run a real turn on a
11
+ * destination channel's LIVE session, so the handler must reach the app's running
12
+ * channel registry — which only exists in this process. We therefore host the
13
+ * tools over loopback HTTP (the one MCP transport the runtime's client supports
14
+ * for an in-process server) and close over app-supplied delivery/discovery hooks.
15
+ *
16
+ * Two tools, both intended for proactive cron/webhook turns (the runtime extension
17
+ * only injects this server for those):
18
+ * - `list_notify_destinations` — discover the conversations the agent may notify
19
+ * (answers "how do I get a conversationId?" when there is no triggering payload).
20
+ * - `notify_conversation` — deliver a message as a real turn into one of them.
21
+ */
22
+ export const NOTIFY_TOOLS_MCP_SERVER_NAME = "mono-agent-notify";
23
+ const MCP_PATH = "/mcp";
24
+ /**
25
+ * Start the in-process notify MCP server on an ephemeral loopback port. Stateless:
26
+ * each request gets a fresh `McpServer`+transport (the tools are pure request/response),
27
+ * which sidesteps session bookkeeping and concurrent-trigger races.
28
+ */
29
+ export async function startNotifyToolsServer(deps) {
30
+ const token = randomBytes(24).toString("hex");
31
+ const expectedAuth = `Bearer ${token}`;
32
+ const httpServer = createServer((req, res) => {
33
+ void handleHttpRequest(req, res, expectedAuth, deps);
34
+ });
35
+ await new Promise((resolve, reject) => {
36
+ const onError = (error) => reject(error);
37
+ httpServer.once("error", onError);
38
+ httpServer.listen(0, "127.0.0.1", () => {
39
+ httpServer.removeListener("error", onError);
40
+ resolve();
41
+ });
42
+ });
43
+ const address = httpServer.address();
44
+ if (address === null || typeof address === "string") {
45
+ httpServer.close();
46
+ throw new Error("notify tools server: failed to bind a loopback port.");
47
+ }
48
+ const url = `http://127.0.0.1:${address.port}${MCP_PATH}`;
49
+ return {
50
+ url,
51
+ token,
52
+ close: () => new Promise((resolve) => {
53
+ httpServer.close(() => resolve());
54
+ }),
55
+ };
56
+ }
57
+ async function handleHttpRequest(req, res, expectedAuth, deps) {
58
+ if (!isAuthorized(req, expectedAuth)) {
59
+ res.writeHead(401, { "content-type": "application/json" });
60
+ res.end(JSON.stringify({ error: "unauthorized" }));
61
+ return;
62
+ }
63
+ if (req.url?.split("?", 1)[0] !== MCP_PATH) {
64
+ res.writeHead(404, { "content-type": "application/json" });
65
+ res.end(JSON.stringify({ error: "not found" }));
66
+ return;
67
+ }
68
+ // Stateless: only POST carries JSON-RPC. The single tool round-trips are
69
+ // request/response, so reject the optional GET/DELETE session streams.
70
+ if (req.method !== "POST") {
71
+ res.writeHead(405, { "content-type": "application/json", allow: "POST" });
72
+ res.end(JSON.stringify({ error: "method not allowed" }));
73
+ return;
74
+ }
75
+ const server = buildMcpServer(deps);
76
+ // Stateless: omitting sessionIdGenerator runs the transport without session
77
+ // tracking, so a fresh server+transport per request is the correct pattern and
78
+ // concurrent triggers never share state.
79
+ const transport = new StreamableHTTPServerTransport({});
80
+ // Idempotent: with HTTP keep-alive the response can `finish` without firing
81
+ // `close`, so bind both and guard against a double-close leaking nothing.
82
+ let cleaned = false;
83
+ const cleanup = () => {
84
+ if (cleaned)
85
+ return;
86
+ cleaned = true;
87
+ void transport.close();
88
+ void server.close();
89
+ };
90
+ res.on("close", cleanup);
91
+ res.on("finish", cleanup);
92
+ try {
93
+ // The transport implements the SDK Transport interface at runtime; the cast
94
+ // bridges an exactOptionalPropertyTypes mismatch in the SDK's own typings.
95
+ await server.connect(transport);
96
+ await transport.handleRequest(req, res);
97
+ }
98
+ catch (error) {
99
+ deps.logger?.error?.("notify tools server: request failed.", { reason: reasonOf(error) });
100
+ if (!res.headersSent) {
101
+ res.writeHead(500, { "content-type": "application/json" });
102
+ res.end(JSON.stringify({ error: "internal error" }));
103
+ }
104
+ }
105
+ }
106
+ function isAuthorized(req, expectedAuth) {
107
+ const header = req.headers.authorization;
108
+ if (typeof header !== "string") {
109
+ return false;
110
+ }
111
+ const a = Buffer.from(header);
112
+ const b = Buffer.from(expectedAuth);
113
+ return a.length === b.length && timingSafeEqual(a, b);
114
+ }
115
+ function buildMcpServer(deps) {
116
+ const server = new McpServer({ name: "agent-notify-tools", version: "0.1.0" });
117
+ server.registerTool("list_notify_destinations", {
118
+ title: "List notification destinations",
119
+ description: "List the conversations you can proactively deliver a message to with notify_conversation. " +
120
+ "Use this when you have no triggering conversationId in hand (e.g. a scheduled/cron run) to " +
121
+ "discover where to reach the user. Each entry's `conversationId` is what notify_conversation " +
122
+ "expects — read its description for how delivery works (the destination turn's reply is what is sent).",
123
+ inputSchema: {},
124
+ }, async () => {
125
+ const destinations = await deps.listDestinations();
126
+ const lines = destinations.length === 0
127
+ ? ["(no known destinations yet — the agent has not handled any push-channel conversation and no single allowlisted destination is configured)"]
128
+ : destinations.map((d) => `- ${d.conversationId}${d.lastSeen === undefined ? "" : ` (last active ${d.lastSeen})`}${d.fromAllowlist === true ? " (allowlisted, not yet used)" : ""}`);
129
+ return {
130
+ content: [{ type: "text", text: ["Conversations you can notify:", ...lines].join("\n") }],
131
+ structuredContent: { destinations },
132
+ };
133
+ });
134
+ server.registerTool("notify_conversation", {
135
+ title: "Notify a conversation",
136
+ description: "Proactively deliver a message into a conversation you are not currently handling. The message " +
137
+ "runs as a real turn on that conversation's own session and THAT TURN'S REPLY is what the user " +
138
+ "receives (so the user sees it natively and the conversation remembers it). Use this to follow up " +
139
+ "from a cron job or an inbound webhook callback.\n\n" +
140
+ "How `text` is delivered (read carefully — this is the #1 mistake):\n" +
141
+ "- `text` is the stimulus the destination conversation acts on; it is NOT posted verbatim. The " +
142
+ "destination agent reads `text` and composes the user-facing reply with its own context, and that " +
143
+ "reply is delivered automatically.\n" +
144
+ "- To deliver pre-composed or exact content (e.g. a digest), phrase `text` as an explicit reply " +
145
+ "instruction, e.g.: \"Reply with the text below exactly as written, adding nothing, and do not call " +
146
+ "any tools — your reply is delivered automatically:\\n\\n<your content>\".\n" +
147
+ "- The destination must NOT call its own send tools (e.g. slack_send_message) — its reply is already " +
148
+ "delivered, so sending again posts the message twice.\n\n" +
149
+ "How to choose `conversationId`:\n" +
150
+ "- Webhook/async callback: pass the `conversationId` carried in the triggering request payload.\n" +
151
+ "- Otherwise (e.g. a scheduled run): call list_notify_destinations first and pick from it.\n\n" +
152
+ "Delivery is bounded by the channel allowlist and may return delivered:false (e.g. unknown/disallowed " +
153
+ "id, channel offline). The call blocks until the destination turn replies, so keep that turn to a single " +
154
+ "reply — a turn that re-scans, recalls, or hunts for a send tool is slow and can hit the request timeout. " +
155
+ "If you receive delivered:false, do not assume it was also delivered some other way.",
156
+ inputSchema: {
157
+ conversationId: z
158
+ .string()
159
+ .min(1)
160
+ .describe("Destination conversationId, e.g. telegram:42 or slack:C123 (or slack:C123:1718.99 for a thread)."),
161
+ text: z
162
+ .string()
163
+ .min(1)
164
+ .describe("What to deliver. The destination conversation runs this as a turn and its reply is delivered; " +
165
+ "to deliver exact content, phrase this as a reply-verbatim, no-tools instruction (see the tool description)."),
166
+ },
167
+ }, async (args) => {
168
+ const result = await deps.deliver(args.conversationId, args.text);
169
+ const summary = result.delivered
170
+ ? `Delivered to ${args.conversationId}.`
171
+ : `Not delivered to ${args.conversationId}${result.reason === undefined ? "" : `: ${result.reason}`}.`;
172
+ return {
173
+ content: [{ type: "text", text: summary }],
174
+ structuredContent: { delivered: result.delivered, ...(result.reason === undefined ? {} : { reason: result.reason }) },
175
+ };
176
+ });
177
+ return server;
178
+ }
179
+ function reasonOf(error) {
180
+ return error instanceof Error ? error.message : String(error);
181
+ }
182
+ //# sourceMappingURL=notify-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify-tool.js","sourceRoot":"","sources":["../src/notify-tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** The installed agent-app version, used for exact lockstep plugin guidance. */
2
+ export declare function agentAppPackageVersion(): string | undefined;
3
+ //# sourceMappingURL=package-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-version.d.ts","sourceRoot":"","sources":["../src/package-version.ts"],"names":[],"mappings":"AAEA,gFAAgF;AAChF,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,SAAS,CAS3D"}
@@ -0,0 +1,14 @@
1
+ import { createRequire } from "node:module";
2
+ /** The installed agent-app version, used for exact lockstep plugin guidance. */
3
+ export function agentAppPackageVersion() {
4
+ try {
5
+ const pkg = createRequire(import.meta.url)("../package.json");
6
+ return typeof pkg.version === "string" && pkg.version.trim().length > 0
7
+ ? pkg.version.trim()
8
+ : undefined;
9
+ }
10
+ catch {
11
+ return undefined;
12
+ }
13
+ }
14
+ //# sourceMappingURL=package-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-version.js","sourceRoot":"","sources":["../src/package-version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,gFAAgF;AAChF,MAAM,UAAU,sBAAsB;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAmC,CAAC;QAChG,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YACrE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE;YACpB,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,21 @@
1
+ export declare const MAX_PI_AUTH_STORE_BYTES = 1048576;
2
+ export type PiAuthStoreUnsafeReason = "owner-check-unavailable" | "symbolic-link" | "not-regular-file" | "multiple-hard-links" | "oversized" | "foreign-owner" | "not-owner-only" | "changed-during-read" | "malformed-json" | "unreadable";
3
+ export type PiAuthStoreInspection = {
4
+ readonly status: "ok";
5
+ readonly auth: Readonly<Record<string, unknown>>;
6
+ } | {
7
+ readonly status: "missing";
8
+ } | {
9
+ readonly status: "unsafe";
10
+ readonly reason: PiAuthStoreUnsafeReason;
11
+ };
12
+ /**
13
+ * Inspect an existing Pi credential store without following aliases or reading
14
+ * unbounded input. Credential discovery is deliberately stricter than the
15
+ * explicit, locked repair flow: discovery accepts only a current-user,
16
+ * owner-only, single-link regular file. The repair flow may read a
17
+ * current-user, non-writable 0644 file under its exclusive lock solely so it
18
+ * can atomically replace that file with a hardened 0600 store.
19
+ */
20
+ export declare function inspectPiAuthStore(path: string): Promise<PiAuthStoreInspection>;
21
+ //# sourceMappingURL=pi-auth-store-inspection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-auth-store-inspection.d.ts","sourceRoot":"","sources":["../src/pi-auth-store-inspection.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,uBAAuB,UAAY,CAAC;AAEjD,MAAM,MAAM,uBAAuB,GAC/B,yBAAyB,GACzB,eAAe,GACf,kBAAkB,GAClB,qBAAqB,GACrB,WAAW,GACX,eAAe,GACf,gBAAgB,GAChB,qBAAqB,GACrB,gBAAgB,GAChB,YAAY,CAAC;AAEjB,MAAM,MAAM,qBAAqB,GAC7B;IAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,GAC3E;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAA;CAAE,CAAC;AAE5E;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA6DrF"}
@@ -0,0 +1,120 @@
1
+ import { constants as fsConstants } from "node:fs";
2
+ import { lstat, open } from "node:fs/promises";
3
+ export const MAX_PI_AUTH_STORE_BYTES = 1_048_576;
4
+ /**
5
+ * Inspect an existing Pi credential store without following aliases or reading
6
+ * unbounded input. Credential discovery is deliberately stricter than the
7
+ * explicit, locked repair flow: discovery accepts only a current-user,
8
+ * owner-only, single-link regular file. The repair flow may read a
9
+ * current-user, non-writable 0644 file under its exclusive lock solely so it
10
+ * can atomically replace that file with a hardened 0600 store.
11
+ */
12
+ export async function inspectPiAuthStore(path) {
13
+ if (typeof process.getuid !== "function") {
14
+ return { status: "unsafe", reason: "owner-check-unavailable" };
15
+ }
16
+ let handle;
17
+ try {
18
+ try {
19
+ handle = await open(path, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW | fsConstants.O_NONBLOCK);
20
+ }
21
+ catch (error) {
22
+ if (hasErrorCode(error, "ENOENT"))
23
+ return { status: "missing" };
24
+ if (hasErrorCode(error, "ELOOP") || hasErrorCode(error, "EMLINK")) {
25
+ return { status: "unsafe", reason: "symbolic-link" };
26
+ }
27
+ return { status: "unsafe", reason: "unreadable" };
28
+ }
29
+ const before = await handle.stat();
30
+ const unsafeBefore = unsafeStatReason(before, process.getuid());
31
+ if (unsafeBefore !== undefined)
32
+ return { status: "unsafe", reason: unsafeBefore };
33
+ const contents = await readBounded(handle, MAX_PI_AUTH_STORE_BYTES);
34
+ if (contents === undefined)
35
+ return { status: "unsafe", reason: "oversized" };
36
+ const after = await handle.stat();
37
+ const unsafeAfter = unsafeStatReason(after, process.getuid());
38
+ if (unsafeAfter !== undefined)
39
+ return { status: "unsafe", reason: unsafeAfter };
40
+ if (!sameOpenedFileSnapshot(before, after) || contents.byteLength !== after.size) {
41
+ return { status: "unsafe", reason: "changed-during-read" };
42
+ }
43
+ let pathStat;
44
+ try {
45
+ pathStat = await lstat(path);
46
+ }
47
+ catch {
48
+ return { status: "unsafe", reason: "changed-during-read" };
49
+ }
50
+ const unsafePath = unsafeStatReason(pathStat, process.getuid());
51
+ if (unsafePath !== undefined)
52
+ return { status: "unsafe", reason: unsafePath };
53
+ if (pathStat.dev !== after.dev || pathStat.ino !== after.ino) {
54
+ return { status: "unsafe", reason: "changed-during-read" };
55
+ }
56
+ let parsed;
57
+ try {
58
+ parsed = JSON.parse(contents.toString("utf8"));
59
+ }
60
+ catch {
61
+ return { status: "unsafe", reason: "malformed-json" };
62
+ }
63
+ if (!isRecord(parsed))
64
+ return { status: "unsafe", reason: "malformed-json" };
65
+ return { status: "ok", auth: parsed };
66
+ }
67
+ catch {
68
+ return { status: "unsafe", reason: "unreadable" };
69
+ }
70
+ finally {
71
+ try {
72
+ await handle?.close();
73
+ }
74
+ catch {
75
+ // Inspection is read-only and already fails closed; a close failure must
76
+ // not turn an unsafe credential store into an uncaught validation error.
77
+ }
78
+ }
79
+ }
80
+ function unsafeStatReason(value, ownerUid) {
81
+ if (!value.isFile())
82
+ return "not-regular-file";
83
+ if (value.nlink !== 1)
84
+ return "multiple-hard-links";
85
+ if (value.size > MAX_PI_AUTH_STORE_BYTES)
86
+ return "oversized";
87
+ if (value.uid !== ownerUid)
88
+ return "foreign-owner";
89
+ if ((value.mode & 0o077) !== 0)
90
+ return "not-owner-only";
91
+ return undefined;
92
+ }
93
+ async function readBounded(handle, maxBytes) {
94
+ const output = Buffer.allocUnsafe(maxBytes + 1);
95
+ let offset = 0;
96
+ while (offset < output.byteLength) {
97
+ const { bytesRead } = await handle.read(output, offset, output.byteLength - offset, null);
98
+ if (bytesRead === 0)
99
+ return output.subarray(0, offset);
100
+ offset += bytesRead;
101
+ }
102
+ return undefined;
103
+ }
104
+ function sameOpenedFileSnapshot(left, right) {
105
+ return left.dev === right.dev
106
+ && left.ino === right.ino
107
+ && left.uid === right.uid
108
+ && left.nlink === right.nlink
109
+ && left.mode === right.mode
110
+ && left.size === right.size
111
+ && left.mtimeMs === right.mtimeMs
112
+ && left.ctimeMs === right.ctimeMs;
113
+ }
114
+ function hasErrorCode(error, code) {
115
+ return typeof error === "object" && error !== null && "code" in error && error.code === code;
116
+ }
117
+ function isRecord(value) {
118
+ return typeof value === "object" && value !== null && !Array.isArray(value);
119
+ }
120
+ //# sourceMappingURL=pi-auth-store-inspection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-auth-store-inspection.js","sourceRoot":"","sources":["../src/pi-auth-store-inspection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=pi-oauth-login-main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-oauth-login-main.d.ts","sourceRoot":"","sources":["../src/pi-oauth-login-main.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import { runPiOAuthLogin } from "./pi-oauth-login.js";
3
+ const [provider, ...extra] = process.argv.slice(2);
4
+ if (provider === undefined || extra.length > 0) {
5
+ process.stderr.write("Usage: mono-agent-pi-oauth-login <provider>\n");
6
+ process.exitCode = 2;
7
+ }
8
+ else {
9
+ runPiOAuthLogin(provider).catch((error) => {
10
+ process.stderr.write(`Pi OAuth login failed: ${error instanceof Error ? error.message : String(error)}\n`);
11
+ process.exitCode = 1;
12
+ });
13
+ }
14
+ //# sourceMappingURL=pi-oauth-login-main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-oauth-login-main.js","sourceRoot":"","sources":["../src/pi-oauth-login-main.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnD,IAAI,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;IAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACtE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC;KAAM,CAAC;IACN,eAAe,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QACjD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3G,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { type OAuthProviderInterface } from "@earendil-works/pi-ai/oauth";
2
+ export interface PiOAuthLoginIo {
3
+ readonly ask: (question: string) => Promise<string>;
4
+ readonly write: (text: string) => void;
5
+ }
6
+ export interface RunPiOAuthLoginOptions {
7
+ readonly authPath?: string;
8
+ readonly provider?: OAuthProviderInterface;
9
+ readonly io?: PiOAuthLoginIo;
10
+ }
11
+ /**
12
+ * Run Pi's provider-owned OAuth implementation with a complete terminal
13
+ * callback surface. In particular, Anthropic races its localhost callback
14
+ * against `onManualCodeInput`; Pi's generic CLI omits that callback even though
15
+ * it prints instructions saying a final redirect URL can be pasted.
16
+ *
17
+ * The raw line is intentionally handed to the provider unchanged. Anthropic's
18
+ * shipped parser extracts code/state from the full URL and validates state
19
+ * against the PKCE verifier before token exchange.
20
+ */
21
+ export declare function runPiOAuthLogin(providerId: string, options?: RunPiOAuthLoginOptions): Promise<void>;
22
+ //# sourceMappingURL=pi-oauth-login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-oauth-login.d.ts","sourceRoot":"","sources":["../src/pi-oauth-login.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,sBAAsB,EAC5B,MAAM,6BAA6B,CAAC;AAErC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAC3C,QAAQ,CAAC,EAAE,CAAC,EAAE,cAAc,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,IAAI,CAAC,CAoDf"}
@@ -0,0 +1,79 @@
1
+ import { chmod, readFile, writeFile } from "node:fs/promises";
2
+ import { createInterface } from "node:readline";
3
+ import { getOAuthProvider, } from "@earendil-works/pi-ai/oauth";
4
+ /**
5
+ * Run Pi's provider-owned OAuth implementation with a complete terminal
6
+ * callback surface. In particular, Anthropic races its localhost callback
7
+ * against `onManualCodeInput`; Pi's generic CLI omits that callback even though
8
+ * it prints instructions saying a final redirect URL can be pasted.
9
+ *
10
+ * The raw line is intentionally handed to the provider unchanged. Anthropic's
11
+ * shipped parser extracts code/state from the full URL and validates state
12
+ * against the PKCE verifier before token exchange.
13
+ */
14
+ export async function runPiOAuthLogin(providerId, options = {}) {
15
+ const provider = options.provider ?? getOAuthProvider(providerId);
16
+ if (provider === undefined || provider.id !== providerId) {
17
+ throw new Error(`Unknown bundled Pi OAuth provider: ${providerId}`);
18
+ }
19
+ const readline = options.io === undefined
20
+ ? createInterface({ input: process.stdin, output: process.stdout })
21
+ : undefined;
22
+ const io = options.io ?? {
23
+ ask: async (question) => await new Promise((resolve) => readline.question(question, resolve)),
24
+ write: (text) => process.stdout.write(text),
25
+ };
26
+ try {
27
+ const callbacks = {
28
+ onAuth: (info) => {
29
+ io.write(`\nOpen this URL in your browser:\n${info.url}\n`);
30
+ if (info.instructions !== undefined)
31
+ io.write(`${info.instructions}\n`);
32
+ io.write("\n");
33
+ },
34
+ onDeviceCode: (info) => {
35
+ io.write(`\nOpen this URL in your browser:\n${info.verificationUri}\n`);
36
+ io.write(`Enter code: ${info.userCode}\n\n`);
37
+ },
38
+ onPrompt: async (prompt) => await io.ask(`${prompt.message}${prompt.placeholder === undefined ? "" : ` (${prompt.placeholder})`}: `),
39
+ onManualCodeInput: async () => await io.ask("Paste the final redirect URL or authorization code " +
40
+ "(its OAuth state will be validated), or wait for the localhost callback:\n> "),
41
+ onSelect: async (prompt) => {
42
+ io.write(`\n${prompt.message}\n`);
43
+ prompt.options.forEach((option, index) => io.write(` ${index + 1}. ${option.label}\n`));
44
+ const answer = await io.ask(`Enter number (1-${prompt.options.length}): `);
45
+ return prompt.options[Number.parseInt(answer, 10) - 1]?.id;
46
+ },
47
+ onProgress: (message) => io.write(`${message}\n`),
48
+ };
49
+ const credentials = await provider.login(callbacks);
50
+ const authPath = options.authPath ?? "auth.json";
51
+ const auth = await readAuth(authPath);
52
+ await writeFile(authPath, `${JSON.stringify({
53
+ ...auth,
54
+ [providerId]: { type: "oauth", ...credentials },
55
+ }, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
56
+ await chmod(authPath, 0o600);
57
+ io.write(`\nCredentials saved to ${authPath}\n`);
58
+ }
59
+ finally {
60
+ readline?.close();
61
+ }
62
+ }
63
+ async function readAuth(path) {
64
+ let contents;
65
+ try {
66
+ contents = await readFile(path, "utf8");
67
+ }
68
+ catch (error) {
69
+ if (error.code === "ENOENT")
70
+ return {};
71
+ throw error;
72
+ }
73
+ const parsed = JSON.parse(contents);
74
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
75
+ throw new Error(`${path} must contain a JSON object.`);
76
+ }
77
+ return parsed;
78
+ }
79
+ //# sourceMappingURL=pi-oauth-login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-oauth-login.js","sourceRoot":"","sources":["../src/pi-oauth-login.ts"],"names":[],"mappings":"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"}
@@ -15,6 +15,8 @@ export interface ProactiveNotifyInput {
15
15
  * destination's harness (e.g. a Slack interactive trigger).
16
16
  */
17
17
  readonly verbatim?: boolean;
18
+ /** Stable host delivery identity for adapters with duplicate suppression. */
19
+ readonly deliveryKey?: string;
18
20
  /** Currently running channels, keyed by id (the app's live registry). */
19
21
  readonly running: ReadonlyMap<ChannelId, Pick<RunningChannel, "notify">>;
20
22
  readonly logger?: MonoAgentAppLogger;
@@ -1 +1 @@
1
- {"version":3,"file":"proactive-notify.d.ts","sourceRoot":"","sources":["../src/proactive-notify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAInF,YAAY,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAcxE,mHAAmH;AACnH,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAMtF;AAED,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,sFAAsF;IACtF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA+B3G"}
1
+ {"version":3,"file":"proactive-notify.d.ts","sourceRoot":"","sources":["../src/proactive-notify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE,OAAO,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAInF,YAAY,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAcxE,mHAAmH;AACnH,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAMtF;AAED,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,sFAAsF;IACtF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,6EAA6E;IAC7E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAgC3G"}
@@ -44,6 +44,7 @@ export async function routeProactiveNotification(input) {
44
44
  conversationId: input.conversationId,
45
45
  text: input.text,
46
46
  ...(input.verbatim === undefined ? {} : { verbatim: input.verbatim }),
47
+ ...(input.deliveryKey === undefined ? {} : { deliveryKey: input.deliveryKey }),
47
48
  });
48
49
  }
49
50
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"proactive-notify.js","sourceRoot":"","sources":["../src/proactive-notify.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,MAAM,sBAAsB,GAAuC;IACjE,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;CACrB,CAAC;AAEF,mHAAmH;AACnH,MAAM,UAAU,wBAAwB,CAAC,cAAsB;IAC7D,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,sBAAsB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAChE,CAAC;AAmBD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,KAA2B;IAC1E,MAAM,SAAS,GAAG,wBAAwB,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACjE,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,2DAA2D,EAAE;YAChF,cAAc,EAAE,KAAK,CAAC,cAAc;SACrC,CAAC,CAAC;QACH,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,yCAAyC,EAAE,CAAC;IACjF,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC7C,IAAI,OAAO,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;QAClC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAClB,kGAAkG,EAClG,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,SAAS,EAAE,CACpD,CAAC;QACF,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,gEAAgE,EAAE,CAAC;IACpH,CAAC;IACD,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,MAAM,CAAC;YAC1B,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;SACtE,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/B,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,kEAAkE,EAAE;YACvF,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,SAAS;YACT,MAAM;SACP,CAAC,CAAC;QACH,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACtC,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC"}
1
+ {"version":3,"file":"proactive-notify.js","sourceRoot":"","sources":["../src/proactive-notify.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,MAAM,sBAAsB,GAAuC;IACjE,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;CACrB,CAAC;AAEF,mHAAmH;AACnH,MAAM,UAAU,wBAAwB,CAAC,cAAsB;IAC7D,MAAM,KAAK,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,sBAAsB,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAChE,CAAC;AAqBD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,KAA2B;IAC1E,MAAM,SAAS,GAAG,wBAAwB,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACjE,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,2DAA2D,EAAE;YAChF,cAAc,EAAE,KAAK,CAAC,cAAc;SACrC,CAAC,CAAC;QACH,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,yCAAyC,EAAE,CAAC;IACjF,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC7C,IAAI,OAAO,EAAE,MAAM,KAAK,SAAS,EAAE,CAAC;QAClC,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAClB,kGAAkG,EAClG,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,SAAS,EAAE,CACpD,CAAC;QACF,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,gEAAgE,EAAE,CAAC;IACpH,CAAC;IACD,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,MAAM,CAAC;YAC1B,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;YACrE,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;SAC/E,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/B,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,kEAAkE,EAAE;YACvF,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,SAAS;YACT,MAAM;SACP,CAAC,CAAC;QACH,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACtC,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC"}