@murphai/murph 0.1.1

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 (301) hide show
  1. package/CHANGELOG.md +2009 -0
  2. package/LICENSE +674 -0
  3. package/README.md +97 -0
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/assistant/automation/run-loop.d.ts +21 -0
  6. package/dist/assistant/automation/run-loop.d.ts.map +1 -0
  7. package/dist/assistant/automation/run-loop.js +31 -0
  8. package/dist/assistant/automation/run-loop.js.map +1 -0
  9. package/dist/assistant/automation.d.ts +10 -0
  10. package/dist/assistant/automation.d.ts.map +1 -0
  11. package/dist/assistant/automation.js +5 -0
  12. package/dist/assistant/automation.js.map +1 -0
  13. package/dist/assistant/cron.d.ts +19 -0
  14. package/dist/assistant/cron.d.ts.map +1 -0
  15. package/dist/assistant/cron.js +59 -0
  16. package/dist/assistant/cron.js.map +1 -0
  17. package/dist/assistant/doctor-security.d.ts +15 -0
  18. package/dist/assistant/doctor-security.d.ts.map +1 -0
  19. package/dist/assistant/doctor-security.js +172 -0
  20. package/dist/assistant/doctor-security.js.map +1 -0
  21. package/dist/assistant/doctor.d.ts +5 -0
  22. package/dist/assistant/doctor.d.ts.map +1 -0
  23. package/dist/assistant/doctor.js +527 -0
  24. package/dist/assistant/doctor.js.map +1 -0
  25. package/dist/assistant/outbox.d.ts +19 -0
  26. package/dist/assistant/outbox.d.ts.map +1 -0
  27. package/dist/assistant/outbox.js +28 -0
  28. package/dist/assistant/outbox.js.map +1 -0
  29. package/dist/assistant/provider-catalog.d.ts +61 -0
  30. package/dist/assistant/provider-catalog.d.ts.map +1 -0
  31. package/dist/assistant/provider-catalog.js +205 -0
  32. package/dist/assistant/provider-catalog.js.map +1 -0
  33. package/dist/assistant/service.d.ts +85 -0
  34. package/dist/assistant/service.d.ts.map +1 -0
  35. package/dist/assistant/service.js +26 -0
  36. package/dist/assistant/service.js.map +1 -0
  37. package/dist/assistant/status.d.ts +9 -0
  38. package/dist/assistant/status.d.ts.map +1 -0
  39. package/dist/assistant/status.js +16 -0
  40. package/dist/assistant/status.js.map +1 -0
  41. package/dist/assistant/stop.d.ts +20 -0
  42. package/dist/assistant/stop.d.ts.map +1 -0
  43. package/dist/assistant/stop.js +142 -0
  44. package/dist/assistant/stop.js.map +1 -0
  45. package/dist/assistant/store.d.ts +6 -0
  46. package/dist/assistant/store.d.ts.map +1 -0
  47. package/dist/assistant/store.js +21 -0
  48. package/dist/assistant/store.js.map +1 -0
  49. package/dist/assistant/ui/ink.d.ts +247 -0
  50. package/dist/assistant/ui/ink.d.ts.map +1 -0
  51. package/dist/assistant/ui/ink.js +2417 -0
  52. package/dist/assistant/ui/ink.js.map +1 -0
  53. package/dist/assistant/ui/theme.d.ts +64 -0
  54. package/dist/assistant/ui/theme.d.ts.map +1 -0
  55. package/dist/assistant/ui/theme.js +180 -0
  56. package/dist/assistant/ui/theme.js.map +1 -0
  57. package/dist/assistant/ui/view-model.d.ts +89 -0
  58. package/dist/assistant/ui/view-model.d.ts.map +1 -0
  59. package/dist/assistant/ui/view-model.js +298 -0
  60. package/dist/assistant/ui/view-model.js.map +1 -0
  61. package/dist/assistant-chat-ink.d.ts +2 -0
  62. package/dist/assistant-chat-ink.d.ts.map +1 -0
  63. package/dist/assistant-chat-ink.js +2 -0
  64. package/dist/assistant-chat-ink.js.map +1 -0
  65. package/dist/assistant-daemon-client.d.ts +81 -0
  66. package/dist/assistant-daemon-client.d.ts.map +1 -0
  67. package/dist/assistant-daemon-client.js +473 -0
  68. package/dist/assistant-daemon-client.js.map +1 -0
  69. package/dist/assistant-runtime.d.ts +25 -0
  70. package/dist/assistant-runtime.d.ts.map +1 -0
  71. package/dist/assistant-runtime.js +17 -0
  72. package/dist/assistant-runtime.js.map +1 -0
  73. package/dist/bin.d.ts +3 -0
  74. package/dist/bin.d.ts.map +1 -0
  75. package/dist/bin.js +7 -0
  76. package/dist/bin.js.map +1 -0
  77. package/dist/cli-entry.d.ts +10 -0
  78. package/dist/cli-entry.d.ts.map +1 -0
  79. package/dist/cli-entry.js +127 -0
  80. package/dist/cli-entry.js.map +1 -0
  81. package/dist/commands/assistant.d.ts +5 -0
  82. package/dist/commands/assistant.d.ts.map +1 -0
  83. package/dist/commands/assistant.js +1663 -0
  84. package/dist/commands/assistant.js.map +1 -0
  85. package/dist/commands/audit-command-helpers.d.ts +15 -0
  86. package/dist/commands/audit-command-helpers.d.ts.map +1 -0
  87. package/dist/commands/audit-command-helpers.js +24 -0
  88. package/dist/commands/audit-command-helpers.js.map +1 -0
  89. package/dist/commands/audit.d.ts +4 -0
  90. package/dist/commands/audit.d.ts.map +1 -0
  91. package/dist/commands/audit.js +107 -0
  92. package/dist/commands/audit.js.map +1 -0
  93. package/dist/commands/device.d.ts +4 -0
  94. package/dist/commands/device.d.ts.map +1 -0
  95. package/dist/commands/device.js +177 -0
  96. package/dist/commands/device.js.map +1 -0
  97. package/dist/commands/document.d.ts +4 -0
  98. package/dist/commands/document.d.ts.map +1 -0
  99. package/dist/commands/document.js +117 -0
  100. package/dist/commands/document.js.map +1 -0
  101. package/dist/commands/event.d.ts +4 -0
  102. package/dist/commands/event.d.ts.map +1 -0
  103. package/dist/commands/event.js +136 -0
  104. package/dist/commands/event.js.map +1 -0
  105. package/dist/commands/experiment.d.ts +4 -0
  106. package/dist/commands/experiment.d.ts.map +1 -0
  107. package/dist/commands/experiment.js +140 -0
  108. package/dist/commands/experiment.js.map +1 -0
  109. package/dist/commands/export-intake-read-helpers.d.ts +150 -0
  110. package/dist/commands/export-intake-read-helpers.d.ts.map +1 -0
  111. package/dist/commands/export-intake-read-helpers.js +328 -0
  112. package/dist/commands/export-intake-read-helpers.js.map +1 -0
  113. package/dist/commands/export.d.ts +4 -0
  114. package/dist/commands/export.d.ts.map +1 -0
  115. package/dist/commands/export.js +179 -0
  116. package/dist/commands/export.js.map +1 -0
  117. package/dist/commands/food.d.ts +4 -0
  118. package/dist/commands/food.d.ts.map +1 -0
  119. package/dist/commands/food.js +190 -0
  120. package/dist/commands/food.js.map +1 -0
  121. package/dist/commands/health-command-factory.d.ts +230 -0
  122. package/dist/commands/health-command-factory.d.ts.map +1 -0
  123. package/dist/commands/health-command-factory.js +551 -0
  124. package/dist/commands/health-command-factory.js.map +1 -0
  125. package/dist/commands/health-entity-command-registry.d.ts +27 -0
  126. package/dist/commands/health-entity-command-registry.d.ts.map +1 -0
  127. package/dist/commands/health-entity-command-registry.js +84 -0
  128. package/dist/commands/health-entity-command-registry.js.map +1 -0
  129. package/dist/commands/inbox.d.ts +5 -0
  130. package/dist/commands/inbox.d.ts.map +1 -0
  131. package/dist/commands/inbox.js +841 -0
  132. package/dist/commands/inbox.js.map +1 -0
  133. package/dist/commands/intake.d.ts +4 -0
  134. package/dist/commands/intake.d.ts.map +1 -0
  135. package/dist/commands/intake.js +175 -0
  136. package/dist/commands/intake.js.map +1 -0
  137. package/dist/commands/intervention.d.ts +4 -0
  138. package/dist/commands/intervention.d.ts.map +1 -0
  139. package/dist/commands/intervention.js +122 -0
  140. package/dist/commands/intervention.js.map +1 -0
  141. package/dist/commands/journal.d.ts +12 -0
  142. package/dist/commands/journal.d.ts.map +1 -0
  143. package/dist/commands/journal.js +186 -0
  144. package/dist/commands/journal.js.map +1 -0
  145. package/dist/commands/meal.d.ts +4 -0
  146. package/dist/commands/meal.d.ts.map +1 -0
  147. package/dist/commands/meal.js +123 -0
  148. package/dist/commands/meal.js.map +1 -0
  149. package/dist/commands/profile.d.ts +4 -0
  150. package/dist/commands/profile.d.ts.map +1 -0
  151. package/dist/commands/profile.js +62 -0
  152. package/dist/commands/profile.js.map +1 -0
  153. package/dist/commands/protocol.d.ts +4 -0
  154. package/dist/commands/protocol.d.ts.map +1 -0
  155. package/dist/commands/protocol.js +79 -0
  156. package/dist/commands/protocol.js.map +1 -0
  157. package/dist/commands/provider.d.ts +4 -0
  158. package/dist/commands/provider.d.ts.map +1 -0
  159. package/dist/commands/provider.js +115 -0
  160. package/dist/commands/provider.js.map +1 -0
  161. package/dist/commands/read.d.ts +4 -0
  162. package/dist/commands/read.d.ts.map +1 -0
  163. package/dist/commands/read.js +55 -0
  164. package/dist/commands/read.js.map +1 -0
  165. package/dist/commands/recipe.d.ts +4 -0
  166. package/dist/commands/recipe.d.ts.map +1 -0
  167. package/dist/commands/recipe.js +116 -0
  168. package/dist/commands/recipe.js.map +1 -0
  169. package/dist/commands/record-mutation-command-helpers.d.ts +196 -0
  170. package/dist/commands/record-mutation-command-helpers.d.ts.map +1 -0
  171. package/dist/commands/record-mutation-command-helpers.js +150 -0
  172. package/dist/commands/record-mutation-command-helpers.js.map +1 -0
  173. package/dist/commands/research.d.ts +3 -0
  174. package/dist/commands/research.d.ts.map +1 -0
  175. package/dist/commands/research.js +104 -0
  176. package/dist/commands/research.js.map +1 -0
  177. package/dist/commands/sample-batch-command-helpers.d.ts +24 -0
  178. package/dist/commands/sample-batch-command-helpers.d.ts.map +1 -0
  179. package/dist/commands/sample-batch-command-helpers.js +99 -0
  180. package/dist/commands/sample-batch-command-helpers.js.map +1 -0
  181. package/dist/commands/sample-import-command-helpers.d.ts +24 -0
  182. package/dist/commands/sample-import-command-helpers.d.ts.map +1 -0
  183. package/dist/commands/sample-import-command-helpers.js +49 -0
  184. package/dist/commands/sample-import-command-helpers.js.map +1 -0
  185. package/dist/commands/sample-query-command-helpers.d.ts +11 -0
  186. package/dist/commands/sample-query-command-helpers.d.ts.map +1 -0
  187. package/dist/commands/sample-query-command-helpers.js +26 -0
  188. package/dist/commands/sample-query-command-helpers.js.map +1 -0
  189. package/dist/commands/samples.d.ts +4 -0
  190. package/dist/commands/samples.d.ts.map +1 -0
  191. package/dist/commands/samples.js +261 -0
  192. package/dist/commands/samples.js.map +1 -0
  193. package/dist/commands/search.d.ts +4 -0
  194. package/dist/commands/search.d.ts.map +1 -0
  195. package/dist/commands/search.js +295 -0
  196. package/dist/commands/search.js.map +1 -0
  197. package/dist/commands/supplement.d.ts +4 -0
  198. package/dist/commands/supplement.d.ts.map +1 -0
  199. package/dist/commands/supplement.js +338 -0
  200. package/dist/commands/supplement.js.map +1 -0
  201. package/dist/commands/vault.d.ts +4 -0
  202. package/dist/commands/vault.d.ts.map +1 -0
  203. package/dist/commands/vault.js +164 -0
  204. package/dist/commands/vault.js.map +1 -0
  205. package/dist/commands/workout.d.ts +4 -0
  206. package/dist/commands/workout.d.ts.map +1 -0
  207. package/dist/commands/workout.js +284 -0
  208. package/dist/commands/workout.js.map +1 -0
  209. package/dist/incur.generated.d.ts +2164 -0
  210. package/dist/incur.generated.d.ts.map +1 -0
  211. package/dist/incur.generated.js +2 -0
  212. package/dist/incur.generated.js.map +1 -0
  213. package/dist/index.d.ts +13 -0
  214. package/dist/index.d.ts.map +1 -0
  215. package/dist/index.js +14 -0
  216. package/dist/index.js.map +1 -0
  217. package/dist/research-cli-contracts.d.ts +22 -0
  218. package/dist/research-cli-contracts.d.ts.map +1 -0
  219. package/dist/research-cli-contracts.js +18 -0
  220. package/dist/research-cli-contracts.js.map +1 -0
  221. package/dist/research-runtime.d.ts +79 -0
  222. package/dist/research-runtime.d.ts.map +1 -0
  223. package/dist/research-runtime.js +351 -0
  224. package/dist/research-runtime.js.map +1 -0
  225. package/dist/run-terminal-logging.d.ts +12 -0
  226. package/dist/run-terminal-logging.d.ts.map +1 -0
  227. package/dist/run-terminal-logging.js +323 -0
  228. package/dist/run-terminal-logging.js.map +1 -0
  229. package/dist/setup-agentmail.d.ts +30 -0
  230. package/dist/setup-agentmail.d.ts.map +1 -0
  231. package/dist/setup-agentmail.js +136 -0
  232. package/dist/setup-agentmail.js.map +1 -0
  233. package/dist/setup-assistant-account.d.ts +29 -0
  234. package/dist/setup-assistant-account.d.ts.map +1 -0
  235. package/dist/setup-assistant-account.js +443 -0
  236. package/dist/setup-assistant-account.js.map +1 -0
  237. package/dist/setup-assistant.d.ts +34 -0
  238. package/dist/setup-assistant.d.ts.map +1 -0
  239. package/dist/setup-assistant.js +355 -0
  240. package/dist/setup-assistant.js.map +1 -0
  241. package/dist/setup-cli.d.ts +72 -0
  242. package/dist/setup-cli.d.ts.map +1 -0
  243. package/dist/setup-cli.js +387 -0
  244. package/dist/setup-cli.js.map +1 -0
  245. package/dist/setup-services/channels.d.ts +19 -0
  246. package/dist/setup-services/channels.d.ts.map +1 -0
  247. package/dist/setup-services/channels.js +721 -0
  248. package/dist/setup-services/channels.js.map +1 -0
  249. package/dist/setup-services/process.d.ts +18 -0
  250. package/dist/setup-services/process.d.ts.map +1 -0
  251. package/dist/setup-services/process.js +98 -0
  252. package/dist/setup-services/process.js.map +1 -0
  253. package/dist/setup-services/scheduled-updates.d.ts +9 -0
  254. package/dist/setup-services/scheduled-updates.d.ts.map +1 -0
  255. package/dist/setup-services/scheduled-updates.js +64 -0
  256. package/dist/setup-services/scheduled-updates.js.map +1 -0
  257. package/dist/setup-services/shell.d.ts +18 -0
  258. package/dist/setup-services/shell.d.ts.map +1 -0
  259. package/dist/setup-services/shell.js +447 -0
  260. package/dist/setup-services/shell.js.map +1 -0
  261. package/dist/setup-services/steps.d.ts +39 -0
  262. package/dist/setup-services/steps.d.ts.map +1 -0
  263. package/dist/setup-services/steps.js +86 -0
  264. package/dist/setup-services/steps.js.map +1 -0
  265. package/dist/setup-services/toolchain.d.ts +46 -0
  266. package/dist/setup-services/toolchain.d.ts.map +1 -0
  267. package/dist/setup-services/toolchain.js +232 -0
  268. package/dist/setup-services/toolchain.js.map +1 -0
  269. package/dist/setup-services.d.ts +44 -0
  270. package/dist/setup-services.d.ts.map +1 -0
  271. package/dist/setup-services.js +739 -0
  272. package/dist/setup-services.js.map +1 -0
  273. package/dist/setup-wizard.d.ts +101 -0
  274. package/dist/setup-wizard.d.ts.map +1 -0
  275. package/dist/setup-wizard.js +1458 -0
  276. package/dist/setup-wizard.js.map +1 -0
  277. package/dist/usecases/intervention.d.ts +63 -0
  278. package/dist/usecases/intervention.d.ts.map +1 -0
  279. package/dist/usecases/intervention.js +205 -0
  280. package/dist/usecases/intervention.js.map +1 -0
  281. package/dist/usecases/text-duration.d.ts +4 -0
  282. package/dist/usecases/text-duration.d.ts.map +1 -0
  283. package/dist/usecases/text-duration.js +63 -0
  284. package/dist/usecases/text-duration.js.map +1 -0
  285. package/dist/usecases/workout-format.d.ts +139 -0
  286. package/dist/usecases/workout-format.d.ts.map +1 -0
  287. package/dist/usecases/workout-format.js +445 -0
  288. package/dist/usecases/workout-format.js.map +1 -0
  289. package/dist/usecases/workout.d.ts +94 -0
  290. package/dist/usecases/workout.d.ts.map +1 -0
  291. package/dist/usecases/workout.js +411 -0
  292. package/dist/usecases/workout.js.map +1 -0
  293. package/dist/vault-cli-command-manifest.d.ts +562 -0
  294. package/dist/vault-cli-command-manifest.d.ts.map +1 -0
  295. package/dist/vault-cli-command-manifest.js +759 -0
  296. package/dist/vault-cli-command-manifest.js.map +1 -0
  297. package/dist/vault-cli.d.ts +6 -0
  298. package/dist/vault-cli.d.ts.map +1 -0
  299. package/dist/vault-cli.js +38 -0
  300. package/dist/vault-cli.js.map +1 -0
  301. package/package.json +85 -0
@@ -0,0 +1,721 @@
1
+ import { readAssistantAutomationState, saveAssistantAutomationState, } from '@murphai/assistant-core/assistant-state';
2
+ import { resolveAgentmailApiKey } from '@murphai/assistant-core/agentmail-runtime';
3
+ import { getAssistantChannelAdapter } from '@murphai/assistant-core/assistant-runtime';
4
+ import { describeLinqConnectorEndpoint as describeLinqEndpoint } from '@murphai/assistant-core/inbox-app/linq-endpoint';
5
+ import { resolveSetupChannelMissingEnv, SETUP_RUNTIME_ENV_NOTICE, } from '@murphai/assistant-core/setup-runtime-env';
6
+ import { setupChannelValues, } from '@murphai/assistant-core/setup-cli-contracts';
7
+ import { resolveTelegramBotToken } from '@murphai/assistant-core/telegram-runtime';
8
+ import { VaultCliError } from '@murphai/assistant-core/vault-cli-errors';
9
+ import { createStep } from './steps.js';
10
+ const IMESSAGE_SETUP_CONNECTOR_ID = 'imessage:self';
11
+ const IMESSAGE_SETUP_ACCOUNT_ID = 'self';
12
+ const TELEGRAM_SETUP_CONNECTOR_ID = 'telegram:bot';
13
+ const TELEGRAM_SETUP_ACCOUNT_ID = 'bot';
14
+ const LINQ_SETUP_CONNECTOR_ID = 'linq:default';
15
+ const LINQ_SETUP_ACCOUNT_ID = 'default';
16
+ const EMAIL_SETUP_CONNECTOR_ID = 'email:agentmail';
17
+ const EMAIL_SETUP_DISPLAY_NAME = 'Murph';
18
+ const SETUP_CHANNEL_ORDER = [
19
+ 'imessage',
20
+ 'telegram',
21
+ 'linq',
22
+ 'email',
23
+ ];
24
+ function isSetupChannelSupportedOnPlatform(channel, platform) {
25
+ return channel !== 'imessage' || platform === 'darwin';
26
+ }
27
+ function isSetupChannel(value) {
28
+ return setupChannelValues.includes(value);
29
+ }
30
+ export function normalizeSetupChannels(value) {
31
+ return [...new Set(value ?? [])];
32
+ }
33
+ function isIMessageSetupConnector(connector) {
34
+ return (connector.id === IMESSAGE_SETUP_CONNECTOR_ID ||
35
+ (connector.source === 'imessage' && connector.accountId === IMESSAGE_SETUP_ACCOUNT_ID));
36
+ }
37
+ function isTelegramSetupConnector(connector) {
38
+ return (connector.id === TELEGRAM_SETUP_CONNECTOR_ID ||
39
+ (connector.source === 'telegram' &&
40
+ connector.accountId === TELEGRAM_SETUP_ACCOUNT_ID));
41
+ }
42
+ function isLinqSetupConnector(connector) {
43
+ return (connector.id === LINQ_SETUP_CONNECTOR_ID ||
44
+ (connector.source === 'linq' && connector.accountId === LINQ_SETUP_ACCOUNT_ID));
45
+ }
46
+ function findReusableLinqSetupConnector(connectors) {
47
+ return (connectors.find((connector) => connector.id === LINQ_SETUP_CONNECTOR_ID) ??
48
+ connectors.find((connector) => connector.source === 'linq' && connector.accountId === LINQ_SETUP_ACCOUNT_ID) ??
49
+ connectors.find((connector) => connector.source === 'linq') ??
50
+ null);
51
+ }
52
+ function isEmailSetupConnector(connector) {
53
+ return connector.id === EMAIL_SETUP_CONNECTOR_ID || connector.source === 'email';
54
+ }
55
+ function isSetupAddedEmailConnectorResult(value) {
56
+ return 'selectedInbox' in value;
57
+ }
58
+ function describeLinqConnectorEndpoint(input) {
59
+ const endpoint = describeLinqEndpoint({
60
+ options: {
61
+ linqWebhookHost: input.options.linqWebhookHost,
62
+ linqWebhookPath: input.options.linqWebhookPath,
63
+ linqWebhookPort: input.options.linqWebhookPort ?? undefined,
64
+ },
65
+ });
66
+ return `${endpoint.host}:${endpoint.port}${endpoint.path}`;
67
+ }
68
+ function describeConfiguredEmailAction(input) {
69
+ if (input.added.provisionedMailbox) {
70
+ return 'Provisioned';
71
+ }
72
+ if (input.added.reusedMailbox || input.selectedInbox) {
73
+ return 'Reused';
74
+ }
75
+ return 'Provisioned';
76
+ }
77
+ const CHANNEL_SPECS = {
78
+ imessage: {
79
+ channel: 'imessage',
80
+ title: 'iMessage channel',
81
+ stepId: 'channel-imessage',
82
+ runtimeUnavailableMessage: 'Murph setup cannot configure iMessage because the inbox source management services are unavailable in this build.',
83
+ readiness: {
84
+ kind: 'always-ready',
85
+ },
86
+ plan(context) {
87
+ if (context.platform !== 'darwin') {
88
+ return {
89
+ supported: false,
90
+ connectorId: null,
91
+ detail: 'Skipped iMessage because it requires macOS. Use Telegram, Linq, or email on Linux, or run iMessage from a Mac host.',
92
+ missingEnv: [],
93
+ stepDetail: 'Skipped iMessage because it requires Messages.app and the local Messages database on macOS.',
94
+ };
95
+ }
96
+ return {
97
+ supported: true,
98
+ connectorId: IMESSAGE_SETUP_CONNECTOR_ID,
99
+ dryRunDetail: 'Would configure the local iMessage inbox connector and enable assistant auto-reply for new conversations.',
100
+ dryRunStepDetail: 'Would add the imessage:self inbox connector and enable assistant auto-reply for new iMessage conversations.',
101
+ missingEnv: [],
102
+ readyForSetup: true,
103
+ };
104
+ },
105
+ findExistingConnector(connectors) {
106
+ return connectors.find(isIMessageSetupConnector) ?? null;
107
+ },
108
+ async addConnector(context, sourceAdd) {
109
+ return sourceAdd({
110
+ account: IMESSAGE_SETUP_ACCOUNT_ID,
111
+ id: IMESSAGE_SETUP_CONNECTOR_ID,
112
+ includeOwn: true,
113
+ requestId: context.requestId,
114
+ source: 'imessage',
115
+ vault: context.vault,
116
+ });
117
+ },
118
+ describeReused({ connector }) {
119
+ return {
120
+ stepDetail: `Reusing the iMessage inbox connector "${connector.id}" and enabling assistant auto-reply for new iMessage conversations.`,
121
+ detail: `Reused the iMessage connector "${connector.id}" and enabled assistant auto-reply for new iMessage conversations.`,
122
+ };
123
+ },
124
+ describeAdded({ added }) {
125
+ return {
126
+ stepDetail: `Added the iMessage inbox connector "${added.connector.id}" and enabled assistant auto-reply for new iMessage conversations.`,
127
+ detail: `Configured the iMessage connector "${added.connector.id}" and enabled assistant auto-reply for new iMessage conversations.`,
128
+ };
129
+ },
130
+ matchesConfiguredConnector: isIMessageSetupConnector,
131
+ },
132
+ telegram: {
133
+ channel: 'telegram',
134
+ title: 'Telegram channel',
135
+ stepId: 'channel-telegram',
136
+ runtimeUnavailableMessage: 'Murph setup cannot configure Telegram because the inbox source management services are unavailable in this build.',
137
+ readiness: {
138
+ fallbackReason: 'Telegram readiness probe failed',
139
+ kind: 'doctor-probe',
140
+ },
141
+ plan(context) {
142
+ const token = resolveTelegramBotToken(context.env);
143
+ const readyForSetup = getAssistantChannelAdapter('telegram')?.isReadyForSetup(context.env) ??
144
+ Boolean(token);
145
+ const missingEnv = resolveSetupChannelMissingEnv('telegram', context.env);
146
+ return {
147
+ supported: true,
148
+ connectorId: TELEGRAM_SETUP_CONNECTOR_ID,
149
+ dryRunDetail: token
150
+ ? 'Would configure the Telegram bot connector and enable assistant auto-reply for Telegram direct chats.'
151
+ : `Telegram needs TELEGRAM_BOT_TOKEN in the current environment before setup can enable the channel. ${SETUP_RUNTIME_ENV_NOTICE}`,
152
+ dryRunStepDetail: token
153
+ ? 'Would verify the Telegram bot token, add or reuse the telegram:bot inbox connector, and enable assistant auto-reply for Telegram direct chats.'
154
+ : 'Would configure Telegram once TELEGRAM_BOT_TOKEN is available in the shell or local `.env`.',
155
+ missingEnv,
156
+ readyForSetup,
157
+ };
158
+ },
159
+ findExistingConnector(connectors) {
160
+ return connectors.find(isTelegramSetupConnector) ?? null;
161
+ },
162
+ async addConnector(context, sourceAdd) {
163
+ return sourceAdd({
164
+ account: TELEGRAM_SETUP_ACCOUNT_ID,
165
+ id: TELEGRAM_SETUP_CONNECTOR_ID,
166
+ requestId: context.requestId,
167
+ source: 'telegram',
168
+ vault: context.vault,
169
+ });
170
+ },
171
+ describeMissingEnv({ existingConnector }) {
172
+ return {
173
+ stepDetail: existingConnector
174
+ ? `Reused the Telegram inbox connector "${existingConnector.id}", but did not enable assistant auto-reply because TELEGRAM_BOT_TOKEN was not available in the shell or local \`.env\`.`
175
+ : 'Telegram was selected, but setup did not add the connector because TELEGRAM_BOT_TOKEN was not available in the shell or local `.env`.',
176
+ detail: existingConnector
177
+ ? `Reused the Telegram connector "${existingConnector.id}", but skipped assistant auto-reply until a bot token is available in the current environment. ${SETUP_RUNTIME_ENV_NOTICE}`
178
+ : `Telegram needs TELEGRAM_BOT_TOKEN in the current environment before setup can add the connector and enable assistant auto-reply. ${SETUP_RUNTIME_ENV_NOTICE}`,
179
+ };
180
+ },
181
+ describeReused({ connector, readiness }) {
182
+ return {
183
+ stepDetail: readiness.ready
184
+ ? `Reusing the Telegram inbox connector "${connector.id}" and enabling assistant auto-reply for Telegram direct chats.`
185
+ : `Reused the Telegram inbox connector "${connector.id}", but did not enable assistant auto-reply because the bot token could not authenticate${readiness.reason ? ` (${readiness.reason})` : ''}.`,
186
+ detail: readiness.ready
187
+ ? `Reused the Telegram connector "${connector.id}" and enabled assistant auto-reply for Telegram direct chats.`
188
+ : `Reused the Telegram connector "${connector.id}", but skipped assistant auto-reply until the bot token authenticates successfully with Telegram${readiness.reason ? ` (${readiness.reason})` : ''}.`,
189
+ };
190
+ },
191
+ describeAdded({ added, readiness }) {
192
+ return {
193
+ stepDetail: readiness.ready
194
+ ? `Added the Telegram inbox connector "${added.connector.id}" and enabled assistant auto-reply for Telegram direct chats.`
195
+ : `Added the Telegram inbox connector "${added.connector.id}", but did not enable assistant auto-reply because the bot token could not authenticate${readiness.reason ? ` (${readiness.reason})` : ''}.`,
196
+ detail: readiness.ready
197
+ ? `Configured the Telegram connector "${added.connector.id}" and enabled assistant auto-reply for Telegram direct chats.`
198
+ : `Configured the Telegram connector "${added.connector.id}", but skipped assistant auto-reply until the bot token authenticates successfully with Telegram${readiness.reason ? ` (${readiness.reason})` : ''}.`,
199
+ };
200
+ },
201
+ matchesConfiguredConnector: isTelegramSetupConnector,
202
+ },
203
+ linq: {
204
+ channel: 'linq',
205
+ title: 'Linq channel',
206
+ stepId: 'channel-linq',
207
+ runtimeUnavailableMessage: 'Murph setup cannot configure Linq because the inbox source management services are unavailable in this build.',
208
+ readiness: {
209
+ fallbackReason: 'Linq readiness probe failed',
210
+ kind: 'doctor-probe',
211
+ },
212
+ plan(context) {
213
+ const readyForSetup = getAssistantChannelAdapter('linq')?.isReadyForSetup(context.env) ?? false;
214
+ const missingEnv = resolveSetupChannelMissingEnv('linq', context.env);
215
+ return {
216
+ supported: true,
217
+ connectorId: LINQ_SETUP_CONNECTOR_ID,
218
+ dryRunDetail: readyForSetup
219
+ ? 'Would configure the Linq webhook connector and enable assistant auto-reply for Linq direct chats.'
220
+ : `Linq needs both LINQ_API_TOKEN and LINQ_WEBHOOK_SECRET in the current environment before setup can enable the channel. ${SETUP_RUNTIME_ENV_NOTICE}`,
221
+ dryRunStepDetail: readyForSetup
222
+ ? 'Would verify the Linq API token, add or reuse the linq:default inbox connector, and enable assistant auto-reply for Linq direct chats.'
223
+ : 'Would configure Linq once LINQ_API_TOKEN and LINQ_WEBHOOK_SECRET are available in the shell or local `.env`.',
224
+ missingEnv,
225
+ readyForSetup,
226
+ };
227
+ },
228
+ findExistingConnector(connectors) {
229
+ return findReusableLinqSetupConnector(connectors);
230
+ },
231
+ async addConnector(context, sourceAdd) {
232
+ return sourceAdd({
233
+ account: LINQ_SETUP_ACCOUNT_ID,
234
+ id: LINQ_SETUP_CONNECTOR_ID,
235
+ requestId: context.requestId,
236
+ source: 'linq',
237
+ vault: context.vault,
238
+ });
239
+ },
240
+ describeMissingEnv({ existingConnector }) {
241
+ return {
242
+ stepDetail: existingConnector
243
+ ? `Reused the Linq inbox connector "${existingConnector.id}", but did not enable assistant auto-reply because LINQ_API_TOKEN and LINQ_WEBHOOK_SECRET were not both available in the shell or local \`.env\`.`
244
+ : 'Linq was selected, but setup did not add the connector because LINQ_API_TOKEN and LINQ_WEBHOOK_SECRET were not both available in the shell or local `.env`.',
245
+ detail: existingConnector
246
+ ? `Reused the Linq connector "${existingConnector.id}", but skipped assistant auto-reply until both a Linq API token and webhook secret are available in the current environment. ${SETUP_RUNTIME_ENV_NOTICE}`
247
+ : `Linq needs LINQ_API_TOKEN and LINQ_WEBHOOK_SECRET in the current environment before setup can add the connector and enable assistant auto-reply. ${SETUP_RUNTIME_ENV_NOTICE}`,
248
+ };
249
+ },
250
+ describeReused({ connector, readiness }) {
251
+ const endpoint = describeLinqConnectorEndpoint(connector);
252
+ return {
253
+ stepDetail: readiness.ready
254
+ ? `Reusing the Linq inbox connector "${connector.id}" at ${endpoint} and enabling assistant auto-reply for Linq direct chats.`
255
+ : `Reused the Linq inbox connector "${connector.id}" at ${endpoint}, but did not enable assistant auto-reply because the API token could not authenticate${readiness.reason ? ` (${readiness.reason})` : ''}.`,
256
+ detail: readiness.ready
257
+ ? `Reused the Linq connector "${connector.id}" at ${endpoint} and enabled assistant auto-reply for Linq direct chats.`
258
+ : `Reused the Linq connector "${connector.id}" at ${endpoint}, but skipped assistant auto-reply until the Linq API token authenticates successfully${readiness.reason ? ` (${readiness.reason})` : ''}.`,
259
+ };
260
+ },
261
+ describeAdded({ added, readiness }) {
262
+ const endpoint = describeLinqConnectorEndpoint(added.connector);
263
+ return {
264
+ stepDetail: readiness.ready
265
+ ? `Added the Linq inbox connector "${added.connector.id}" at ${endpoint} and enabled assistant auto-reply for Linq direct chats.`
266
+ : `Added the Linq inbox connector "${added.connector.id}" at ${endpoint}, but did not enable assistant auto-reply because the API token could not authenticate${readiness.reason ? ` (${readiness.reason})` : ''}.`,
267
+ detail: readiness.ready
268
+ ? `Configured the Linq connector "${added.connector.id}" at ${endpoint} and enabled assistant auto-reply for Linq direct chats.`
269
+ : `Configured the Linq connector "${added.connector.id}" at ${endpoint}, but skipped assistant auto-reply until the Linq API token authenticates successfully${readiness.reason ? ` (${readiness.reason})` : ''}.`,
270
+ };
271
+ },
272
+ matchesConfiguredConnector: isLinqSetupConnector,
273
+ },
274
+ email: {
275
+ channel: 'email',
276
+ title: 'Email channel',
277
+ stepId: 'channel-email',
278
+ runtimeUnavailableMessage: 'Murph setup cannot configure email because the inbox source management services are unavailable in this build.',
279
+ readiness: {
280
+ fallbackReason: 'Email readiness probe failed',
281
+ kind: 'doctor-probe',
282
+ treatProbeWarnAsReady: true,
283
+ },
284
+ plan(context) {
285
+ const apiKey = resolveAgentmailApiKey(context.env);
286
+ const missingEnv = resolveSetupChannelMissingEnv('email', context.env);
287
+ return {
288
+ supported: true,
289
+ connectorId: EMAIL_SETUP_CONNECTOR_ID,
290
+ dryRunDetail: apiKey
291
+ ? 'Would reuse an existing AgentMail inbox when possible, or provision a new inbox connector and enable assistant auto-reply for direct email threads.'
292
+ : `Email needs AGENTMAIL_API_KEY in the current environment before setup can enable the channel. ${SETUP_RUNTIME_ENV_NOTICE}`,
293
+ dryRunStepDetail: apiKey
294
+ ? 'Would provision or reuse an AgentMail inbox, verify email polling, and enable assistant auto-reply for direct email threads.'
295
+ : 'Would configure email once AGENTMAIL_API_KEY is available in the shell or local `.env`.',
296
+ missingEnv,
297
+ readyForSetup: Boolean(apiKey),
298
+ };
299
+ },
300
+ findExistingConnector(connectors) {
301
+ return connectors.find(isEmailSetupConnector) ?? null;
302
+ },
303
+ async addConnector(context, sourceAdd) {
304
+ const apiKey = resolveAgentmailApiKey(context.env);
305
+ const selectedInbox = context.resolveAgentmailInboxSelection && apiKey
306
+ ? await context.resolveAgentmailInboxSelection({
307
+ allowPrompt: context.allowPrompt,
308
+ env: context.env,
309
+ })
310
+ : null;
311
+ const added = await sourceAdd({
312
+ account: selectedInbox?.accountId,
313
+ address: selectedInbox?.emailAddress ?? undefined,
314
+ id: EMAIL_SETUP_CONNECTOR_ID,
315
+ provision: selectedInbox === null,
316
+ emailDisplayName: EMAIL_SETUP_DISPLAY_NAME,
317
+ requestId: context.requestId,
318
+ source: 'email',
319
+ vault: context.vault,
320
+ });
321
+ return { ...added, selectedInbox };
322
+ },
323
+ describeMissingEnv({ existingConnector }) {
324
+ return {
325
+ stepDetail: existingConnector
326
+ ? `Reused the email inbox connector "${existingConnector.id}", but did not enable assistant auto-reply because AGENTMAIL_API_KEY was not available in the shell or local \`.env\`.`
327
+ : 'Email was selected, but setup did not add the connector because AGENTMAIL_API_KEY was not available in the shell or local `.env`.',
328
+ detail: existingConnector
329
+ ? `Reused the email connector "${existingConnector.id}", but skipped assistant auto-reply until an AgentMail API key is available in the current environment. ${SETUP_RUNTIME_ENV_NOTICE}`
330
+ : `Email needs AGENTMAIL_API_KEY in the current environment before setup can reuse or provision the connector and enable assistant auto-reply. ${SETUP_RUNTIME_ENV_NOTICE}`,
331
+ };
332
+ },
333
+ describeReused({ connector, readiness }) {
334
+ return {
335
+ stepDetail: readiness.ready
336
+ ? `Reusing the email inbox connector "${connector.id}" and enabling assistant auto-reply for direct email threads.`
337
+ : `Reused the email inbox connector "${connector.id}", but did not enable assistant auto-reply because AgentMail readiness checks failed${readiness.reason ? ` (${readiness.reason})` : ''}.`,
338
+ detail: readiness.ready
339
+ ? `Reused the email connector "${connector.id}" and enabled assistant auto-reply for direct email threads.`
340
+ : `Reused the email connector "${connector.id}", but skipped assistant auto-reply until AgentMail readiness checks succeed${readiness.reason ? ` (${readiness.reason})` : ''}.`,
341
+ };
342
+ },
343
+ describeAdded({ added, readiness }) {
344
+ const selectedInbox = isSetupAddedEmailConnectorResult(added)
345
+ ? added.selectedInbox ?? null
346
+ : null;
347
+ const configuredAddress = added.provisionedMailbox?.emailAddress ??
348
+ added.reusedMailbox?.emailAddress ??
349
+ selectedInbox?.emailAddress ??
350
+ added.connector.options.emailAddress ??
351
+ null;
352
+ const actionVerb = describeConfiguredEmailAction({
353
+ added,
354
+ selectedInbox,
355
+ });
356
+ return {
357
+ stepDetail: readiness.ready
358
+ ? `${actionVerb} the AgentMail inbox connector "${added.connector.id}"${configuredAddress ? ` at ${configuredAddress}` : ''} and enabled assistant auto-reply for direct email threads.`
359
+ : `${actionVerb} the AgentMail inbox connector "${added.connector.id}"${configuredAddress ? ` at ${configuredAddress}` : ''}, but did not enable assistant auto-reply because AgentMail readiness checks failed${readiness.reason ? ` (${readiness.reason})` : ''}.`,
360
+ detail: readiness.ready
361
+ ? `Configured the email connector "${added.connector.id}"${configuredAddress ? ` at ${configuredAddress}` : ''} and enabled assistant auto-reply for direct email threads.`
362
+ : `Configured the email connector "${added.connector.id}"${configuredAddress ? ` at ${configuredAddress}` : ''}, but skipped assistant auto-reply until AgentMail readiness checks succeed${readiness.reason ? ` (${readiness.reason})` : ''}.`,
363
+ };
364
+ },
365
+ matchesConfiguredConnector: isEmailSetupConnector,
366
+ },
367
+ };
368
+ const CHANNEL_CONFIGURERS = {
369
+ imessage: configureIMessageChannel,
370
+ telegram: configureTelegramChannel,
371
+ linq: configureLinqChannel,
372
+ email: configureEmailChannel,
373
+ };
374
+ export async function configureSetupChannels(input) {
375
+ const configured = [];
376
+ const platform = input.platform ?? process.platform;
377
+ const context = {
378
+ allowPrompt: input.allowPrompt ?? false,
379
+ dryRun: input.dryRun,
380
+ env: input.env,
381
+ inboxServices: input.inboxServices,
382
+ platform,
383
+ requestId: input.requestId,
384
+ resolveAgentmailInboxSelection: input.resolveAgentmailInboxSelection,
385
+ steps: input.steps,
386
+ vault: input.vault,
387
+ };
388
+ const selectedChannels = new Set(normalizeSetupChannels(input.channels));
389
+ for (const channel of SETUP_CHANNEL_ORDER) {
390
+ if (!selectedChannels.has(channel)) {
391
+ continue;
392
+ }
393
+ configured.push(await CHANNEL_CONFIGURERS[channel](context));
394
+ }
395
+ if (!input.dryRun) {
396
+ await reconcileDeselectedSetupChannels({
397
+ channels: input.channels,
398
+ inboxServices: input.inboxServices,
399
+ platform,
400
+ requestId: input.requestId,
401
+ vault: input.vault,
402
+ });
403
+ await updateAssistantChannelState({
404
+ autoReplyChannels: configured
405
+ .filter((channel) => channel.autoReply)
406
+ .map((channel) => channel.channel),
407
+ platform,
408
+ preferredChannels: filterPersistedSetupChannels(input.channels, platform),
409
+ vault: input.vault,
410
+ });
411
+ }
412
+ return configured;
413
+ }
414
+ function filterPersistedSetupChannels(channels, platform) {
415
+ return normalizeSetupChannels(channels).filter((channel) => isSetupChannelSupportedOnPlatform(channel, platform));
416
+ }
417
+ async function configureIMessageChannel(context) {
418
+ return configureSetupChannel(CHANNEL_SPECS.imessage, context);
419
+ }
420
+ async function configureTelegramChannel(context) {
421
+ return configureSetupChannel(CHANNEL_SPECS.telegram, context);
422
+ }
423
+ async function configureLinqChannel(context) {
424
+ return configureSetupChannel(CHANNEL_SPECS.linq, context);
425
+ }
426
+ async function configureEmailChannel(context) {
427
+ return configureSetupChannel(CHANNEL_SPECS.email, context);
428
+ }
429
+ async function configureSetupChannel(spec, context) {
430
+ const plan = spec.plan(context);
431
+ if (isUnsupportedSetupChannelPlan(plan)) {
432
+ return recordSetupChannelResult(spec, context, {
433
+ autoReplyReady: false,
434
+ connectorEnabled: false,
435
+ connectorId: plan.connectorId,
436
+ connectorPresent: false,
437
+ detail: plan.detail,
438
+ missingEnv: plan.missingEnv,
439
+ outcome: 'unsupported',
440
+ stepDetail: plan.stepDetail,
441
+ stepStatus: 'skipped',
442
+ });
443
+ }
444
+ if (context.dryRun) {
445
+ return recordSetupChannelResult(spec, context, {
446
+ autoReplyReady: plan.readyForSetup,
447
+ connectorEnabled: plan.readyForSetup,
448
+ connectorId: plan.connectorId,
449
+ connectorPresent: false,
450
+ detail: plan.dryRunDetail,
451
+ missingEnv: plan.missingEnv,
452
+ outcome: 'dry-run',
453
+ stepDetail: plan.dryRunStepDetail,
454
+ stepStatus: 'planned',
455
+ });
456
+ }
457
+ const doctor = context.inboxServices.doctor;
458
+ const sourceList = context.inboxServices.sourceList;
459
+ const sourceAdd = context.inboxServices.sourceAdd;
460
+ const sourceSetEnabled = context.inboxServices.sourceSetEnabled;
461
+ if (!sourceList || !sourceAdd) {
462
+ throw new VaultCliError('runtime_unavailable', spec.runtimeUnavailableMessage);
463
+ }
464
+ const listed = await sourceList({
465
+ vault: context.vault,
466
+ requestId: context.requestId,
467
+ });
468
+ const existingConnector = spec.findExistingConnector(listed.connectors);
469
+ if (!plan.readyForSetup) {
470
+ if (!spec.describeMissingEnv) {
471
+ throw new Error(`Missing environment message handler is required for ${spec.channel}.`);
472
+ }
473
+ const messages = spec.describeMissingEnv({
474
+ existingConnector,
475
+ });
476
+ const connectorPresent = existingConnector !== null;
477
+ const connectorEnabled = existingConnector?.enabled ?? false;
478
+ return recordSetupChannelResult(spec, context, {
479
+ autoReplyReady: false,
480
+ connectorEnabled,
481
+ connectorId: existingConnector?.id ?? null,
482
+ connectorPresent,
483
+ detail: messages.detail,
484
+ missingEnv: plan.missingEnv,
485
+ outcome: 'missing-env',
486
+ stepDetail: messages.stepDetail,
487
+ stepStatus: existingConnector ? 'reused' : 'skipped',
488
+ });
489
+ }
490
+ if (existingConnector) {
491
+ const connectorEnabled = await ensureSetupConnectorEnabled({
492
+ connectorId: existingConnector.id,
493
+ enabled: existingConnector.enabled,
494
+ requestId: context.requestId,
495
+ sourceSetEnabled,
496
+ vault: context.vault,
497
+ });
498
+ const readiness = await resolveSetupChannelReadiness({
499
+ connectorId: existingConnector.id,
500
+ doctor,
501
+ requestId: context.requestId,
502
+ readiness: spec.readiness,
503
+ vault: context.vault,
504
+ });
505
+ const autoReplyReady = readiness.ready;
506
+ const messages = spec.describeReused({
507
+ connector: existingConnector,
508
+ readiness,
509
+ });
510
+ return recordSetupChannelResult(spec, context, {
511
+ autoReplyReady,
512
+ connectorEnabled,
513
+ connectorId: existingConnector.id,
514
+ connectorPresent: true,
515
+ detail: messages.detail,
516
+ missingEnv: [],
517
+ outcome: 'reused',
518
+ stepDetail: messages.stepDetail,
519
+ stepStatus: 'reused',
520
+ });
521
+ }
522
+ const added = await spec.addConnector(context, sourceAdd);
523
+ const autoReplyReadiness = await resolveSetupChannelReadiness({
524
+ connectorId: added.connector.id,
525
+ doctor,
526
+ requestId: context.requestId,
527
+ readiness: spec.readiness,
528
+ vault: context.vault,
529
+ });
530
+ const autoReplyReady = autoReplyReadiness.ready;
531
+ const messages = spec.describeAdded({
532
+ added,
533
+ readiness: autoReplyReadiness,
534
+ });
535
+ return recordSetupChannelResult(spec, context, {
536
+ autoReplyReady,
537
+ connectorEnabled: added.connector.enabled,
538
+ connectorId: added.connector.id,
539
+ connectorPresent: true,
540
+ detail: messages.detail,
541
+ missingEnv: [],
542
+ outcome: 'added',
543
+ stepDetail: messages.stepDetail,
544
+ stepStatus: 'completed',
545
+ });
546
+ }
547
+ function isUnsupportedSetupChannelPlan(plan) {
548
+ return plan.supported === false;
549
+ }
550
+ function recordSetupChannelResult(spec, context, resolution) {
551
+ context.steps.push(createStep({
552
+ detail: resolution.stepDetail,
553
+ id: spec.stepId,
554
+ kind: 'configure',
555
+ status: resolution.stepStatus,
556
+ title: spec.title,
557
+ }));
558
+ return {
559
+ autoReply: resolution.autoReplyReady,
560
+ channel: spec.channel,
561
+ configured: mapConfiguredSetupChannelResolution(resolution),
562
+ connectorId: resolution.connectorId,
563
+ detail: resolution.detail,
564
+ // Preserve the historical setup result contract at the boundary while the
565
+ // orchestration tracks connector presence/readiness separately.
566
+ enabled: true,
567
+ missingEnv: resolution.missingEnv,
568
+ };
569
+ }
570
+ function mapConfiguredSetupChannelResolution(resolution) {
571
+ switch (resolution.outcome) {
572
+ case 'missing-env':
573
+ return resolution.connectorPresent;
574
+ case 'reused':
575
+ case 'added':
576
+ return resolution.autoReplyReady;
577
+ case 'unsupported':
578
+ case 'dry-run':
579
+ return false;
580
+ }
581
+ }
582
+ async function resolveSetupChannelReadiness(input) {
583
+ if (input.readiness.kind === 'always-ready') {
584
+ return {
585
+ ready: true,
586
+ reason: null,
587
+ };
588
+ }
589
+ return probeSetupReadiness({
590
+ connectorId: input.connectorId,
591
+ doctor: input.doctor,
592
+ fallbackReason: input.readiness.fallbackReason,
593
+ requestId: input.requestId,
594
+ treatProbeWarnAsReady: input.readiness.treatProbeWarnAsReady,
595
+ vault: input.vault,
596
+ });
597
+ }
598
+ async function probeSetupReadiness(input) {
599
+ if (!input.doctor) {
600
+ return {
601
+ ready: true,
602
+ reason: null,
603
+ };
604
+ }
605
+ const result = await input.doctor({
606
+ requestId: input.requestId,
607
+ sourceId: input.connectorId,
608
+ vault: input.vault,
609
+ });
610
+ const probeCheck = result.checks.find((check) => check.name === 'probe') ?? null;
611
+ const driverImportCheck = result.checks.find((check) => check.name === 'driver-import') ?? null;
612
+ const ready = Boolean((probeCheck?.status === 'pass' ||
613
+ (input.treatProbeWarnAsReady === true && probeCheck?.status === 'warn')) &&
614
+ (driverImportCheck === null || driverImportCheck.status === 'pass'));
615
+ return {
616
+ ready,
617
+ reason: ready
618
+ ? null
619
+ : probeCheck?.message ?? driverImportCheck?.message ?? input.fallbackReason,
620
+ };
621
+ }
622
+ async function updateAssistantChannelState(input) {
623
+ const state = await readAssistantAutomationState(input.vault);
624
+ const preservedAutoReplyChannels = state.autoReplyChannels.filter((channel) => isSetupChannel(channel) &&
625
+ !isSetupChannelSupportedOnPlatform(channel, input.platform));
626
+ const preservedPreferredChannels = state.preferredChannels.filter((channel) => isSetupChannel(channel) &&
627
+ !isSetupChannelSupportedOnPlatform(channel, input.platform));
628
+ const autoReplyChannels = normalizeSetupChannels([
629
+ ...input.autoReplyChannels,
630
+ ...preservedAutoReplyChannels,
631
+ ]);
632
+ const preferredChannels = normalizeSetupChannels([
633
+ ...input.preferredChannels,
634
+ ...preservedPreferredChannels,
635
+ ]);
636
+ const nextBacklogChannels = normalizeSetupChannels(state.autoReplyBacklogChannels.filter((channel) => channel === 'email' && autoReplyChannels.includes(channel)));
637
+ if (autoReplyChannels.includes('email') && !state.autoReplyChannels.includes('email')) {
638
+ nextBacklogChannels.push('email');
639
+ }
640
+ const autoReplyChanged = autoReplyChannels.length !== state.autoReplyChannels.length ||
641
+ autoReplyChannels.some((channel, index) => state.autoReplyChannels[index] !== channel);
642
+ const preferredChanged = preferredChannels.length !== state.preferredChannels.length ||
643
+ preferredChannels.some((channel, index) => state.preferredChannels[index] !== channel);
644
+ const backlogChanged = nextBacklogChannels.length !== state.autoReplyBacklogChannels.length ||
645
+ nextBacklogChannels.some((channel, index) => state.autoReplyBacklogChannels[index] !== channel);
646
+ if (!autoReplyChanged && !preferredChanged && !backlogChanged) {
647
+ return;
648
+ }
649
+ await saveAssistantAutomationState(input.vault, {
650
+ version: 2,
651
+ inboxScanCursor: state.inboxScanCursor,
652
+ autoReplyScanCursor: autoReplyChannels.length === 0
653
+ ? null
654
+ : autoReplyChanged
655
+ ? null
656
+ : state.autoReplyScanCursor,
657
+ autoReplyChannels,
658
+ preferredChannels,
659
+ autoReplyBacklogChannels: nextBacklogChannels,
660
+ autoReplyPrimed: autoReplyChannels.length === 0
661
+ ? true
662
+ : autoReplyChanged
663
+ ? false
664
+ : state.autoReplyPrimed,
665
+ preferredScheduledUpdates: state.preferredScheduledUpdates,
666
+ updatedAt: new Date().toISOString(),
667
+ });
668
+ }
669
+ async function reconcileDeselectedSetupChannels(input) {
670
+ const sourceList = input.inboxServices.sourceList;
671
+ const sourceSetEnabled = input.inboxServices.sourceSetEnabled;
672
+ if (!sourceList || !sourceSetEnabled) {
673
+ return;
674
+ }
675
+ const selectedChannels = new Set(normalizeSetupChannels(input.channels));
676
+ const listed = await sourceList({
677
+ vault: input.vault,
678
+ requestId: input.requestId,
679
+ });
680
+ for (const connector of listed.connectors) {
681
+ if (!connector.enabled) {
682
+ continue;
683
+ }
684
+ const setupChannel = resolveSetupChannelForConnector(connector);
685
+ if (!setupChannel ||
686
+ !isSetupChannelSupportedOnPlatform(setupChannel, input.platform) ||
687
+ selectedChannels.has(setupChannel)) {
688
+ continue;
689
+ }
690
+ await sourceSetEnabled({
691
+ connectorId: connector.id,
692
+ enabled: false,
693
+ requestId: input.requestId,
694
+ vault: input.vault,
695
+ });
696
+ }
697
+ }
698
+ async function ensureSetupConnectorEnabled(input) {
699
+ if (input.enabled) {
700
+ return true;
701
+ }
702
+ if (!input.sourceSetEnabled) {
703
+ return false;
704
+ }
705
+ await input.sourceSetEnabled({
706
+ connectorId: input.connectorId,
707
+ enabled: true,
708
+ requestId: input.requestId,
709
+ vault: input.vault,
710
+ });
711
+ return true;
712
+ }
713
+ function resolveSetupChannelForConnector(connector) {
714
+ for (const channel of SETUP_CHANNEL_ORDER) {
715
+ if (CHANNEL_SPECS[channel].matchesConfiguredConnector(connector)) {
716
+ return channel;
717
+ }
718
+ }
719
+ return null;
720
+ }
721
+ //# sourceMappingURL=channels.js.map