@portel/photon 1.4.0 → 1.5.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 (379) hide show
  1. package/README.md +287 -1160
  2. package/dist/auto-ui/beam.d.ts +9 -0
  3. package/dist/auto-ui/beam.d.ts.map +1 -0
  4. package/dist/auto-ui/beam.js +2381 -0
  5. package/dist/auto-ui/beam.js.map +1 -0
  6. package/dist/auto-ui/components/card.d.ts +13 -0
  7. package/dist/auto-ui/components/card.d.ts.map +1 -0
  8. package/dist/auto-ui/components/card.js +64 -0
  9. package/dist/auto-ui/components/card.js.map +1 -0
  10. package/dist/auto-ui/components/form.d.ts +15 -0
  11. package/dist/auto-ui/components/form.d.ts.map +1 -0
  12. package/dist/auto-ui/components/form.js +72 -0
  13. package/dist/auto-ui/components/form.js.map +1 -0
  14. package/dist/auto-ui/components/list.d.ts +13 -0
  15. package/dist/auto-ui/components/list.d.ts.map +1 -0
  16. package/dist/auto-ui/components/list.js +58 -0
  17. package/dist/auto-ui/components/list.js.map +1 -0
  18. package/dist/auto-ui/components/progress.d.ts +18 -0
  19. package/dist/auto-ui/components/progress.d.ts.map +1 -0
  20. package/dist/auto-ui/components/progress.js +125 -0
  21. package/dist/auto-ui/components/progress.js.map +1 -0
  22. package/dist/auto-ui/components/table.d.ts +13 -0
  23. package/dist/auto-ui/components/table.d.ts.map +1 -0
  24. package/dist/auto-ui/components/table.js +82 -0
  25. package/dist/auto-ui/components/table.js.map +1 -0
  26. package/dist/auto-ui/components/tree.d.ts +13 -0
  27. package/dist/auto-ui/components/tree.d.ts.map +1 -0
  28. package/dist/auto-ui/components/tree.js +61 -0
  29. package/dist/auto-ui/components/tree.js.map +1 -0
  30. package/dist/auto-ui/daemon-tools.d.ts +45 -0
  31. package/dist/auto-ui/daemon-tools.d.ts.map +1 -0
  32. package/dist/auto-ui/daemon-tools.js +580 -0
  33. package/dist/auto-ui/daemon-tools.js.map +1 -0
  34. package/dist/auto-ui/design-system/index.d.ts +21 -0
  35. package/dist/auto-ui/design-system/index.d.ts.map +1 -0
  36. package/dist/auto-ui/design-system/index.js +27 -0
  37. package/dist/auto-ui/design-system/index.js.map +1 -0
  38. package/dist/auto-ui/design-system/tokens.d.ts +9 -0
  39. package/dist/auto-ui/design-system/tokens.d.ts.map +1 -0
  40. package/dist/auto-ui/design-system/tokens.js +27 -0
  41. package/dist/auto-ui/design-system/tokens.js.map +1 -0
  42. package/dist/auto-ui/design-system/transaction-ui.d.ts +70 -0
  43. package/dist/auto-ui/design-system/transaction-ui.d.ts.map +1 -0
  44. package/dist/auto-ui/design-system/transaction-ui.js +982 -0
  45. package/dist/auto-ui/design-system/transaction-ui.js.map +1 -0
  46. package/dist/auto-ui/frontend/index.html +84 -0
  47. package/dist/auto-ui/index.d.ts +21 -0
  48. package/dist/auto-ui/index.d.ts.map +1 -0
  49. package/dist/auto-ui/index.js +25 -0
  50. package/dist/auto-ui/index.js.map +1 -0
  51. package/dist/auto-ui/openapi-generator.d.ts +71 -0
  52. package/dist/auto-ui/openapi-generator.d.ts.map +1 -0
  53. package/dist/auto-ui/openapi-generator.js +223 -0
  54. package/dist/auto-ui/openapi-generator.js.map +1 -0
  55. package/dist/auto-ui/photon-bridge.d.ts +159 -0
  56. package/dist/auto-ui/photon-bridge.d.ts.map +1 -0
  57. package/dist/auto-ui/photon-bridge.js +262 -0
  58. package/dist/auto-ui/photon-bridge.js.map +1 -0
  59. package/dist/auto-ui/photon-host.d.ts +113 -0
  60. package/dist/auto-ui/photon-host.d.ts.map +1 -0
  61. package/dist/auto-ui/photon-host.js +284 -0
  62. package/dist/auto-ui/photon-host.js.map +1 -0
  63. package/dist/auto-ui/platform-compat.d.ts +71 -0
  64. package/dist/auto-ui/platform-compat.d.ts.map +1 -0
  65. package/dist/auto-ui/platform-compat.js +574 -0
  66. package/dist/auto-ui/platform-compat.js.map +1 -0
  67. package/dist/auto-ui/playground-html.d.ts +15 -0
  68. package/dist/auto-ui/playground-html.d.ts.map +1 -0
  69. package/dist/auto-ui/playground-html.js +1113 -0
  70. package/dist/auto-ui/playground-html.js.map +1 -0
  71. package/dist/auto-ui/playground-server.d.ts +7 -0
  72. package/dist/auto-ui/playground-server.d.ts.map +1 -0
  73. package/dist/auto-ui/playground-server.js +840 -0
  74. package/dist/auto-ui/playground-server.js.map +1 -0
  75. package/dist/auto-ui/registry.d.ts +13 -0
  76. package/dist/auto-ui/registry.d.ts.map +1 -0
  77. package/dist/auto-ui/registry.js +62 -0
  78. package/dist/auto-ui/registry.js.map +1 -0
  79. package/dist/auto-ui/renderer.d.ts +14 -0
  80. package/dist/auto-ui/renderer.d.ts.map +1 -0
  81. package/dist/auto-ui/renderer.js +88 -0
  82. package/dist/auto-ui/renderer.js.map +1 -0
  83. package/dist/auto-ui/rendering/components.d.ts +29 -0
  84. package/dist/auto-ui/rendering/components.d.ts.map +1 -0
  85. package/dist/auto-ui/rendering/components.js +773 -0
  86. package/dist/auto-ui/rendering/components.js.map +1 -0
  87. package/dist/auto-ui/rendering/field-analyzer.d.ts +48 -0
  88. package/dist/auto-ui/rendering/field-analyzer.d.ts.map +1 -0
  89. package/dist/auto-ui/rendering/field-analyzer.js +270 -0
  90. package/dist/auto-ui/rendering/field-analyzer.js.map +1 -0
  91. package/dist/auto-ui/rendering/field-renderers.d.ts +64 -0
  92. package/dist/auto-ui/rendering/field-renderers.d.ts.map +1 -0
  93. package/dist/auto-ui/rendering/field-renderers.js +317 -0
  94. package/dist/auto-ui/rendering/field-renderers.js.map +1 -0
  95. package/dist/auto-ui/rendering/index.d.ts +28 -0
  96. package/dist/auto-ui/rendering/index.d.ts.map +1 -0
  97. package/dist/auto-ui/rendering/index.js +60 -0
  98. package/dist/auto-ui/rendering/index.js.map +1 -0
  99. package/dist/auto-ui/rendering/layout-selector.d.ts +48 -0
  100. package/dist/auto-ui/rendering/layout-selector.d.ts.map +1 -0
  101. package/dist/auto-ui/rendering/layout-selector.js +352 -0
  102. package/dist/auto-ui/rendering/layout-selector.js.map +1 -0
  103. package/dist/auto-ui/rendering/template-engine.d.ts +41 -0
  104. package/dist/auto-ui/rendering/template-engine.d.ts.map +1 -0
  105. package/dist/auto-ui/rendering/template-engine.js +238 -0
  106. package/dist/auto-ui/rendering/template-engine.js.map +1 -0
  107. package/dist/auto-ui/streamable-http-transport.d.ts +79 -0
  108. package/dist/auto-ui/streamable-http-transport.d.ts.map +1 -0
  109. package/dist/auto-ui/streamable-http-transport.js +1314 -0
  110. package/dist/auto-ui/streamable-http-transport.js.map +1 -0
  111. package/dist/auto-ui/types.d.ts +310 -0
  112. package/dist/auto-ui/types.d.ts.map +1 -0
  113. package/dist/auto-ui/types.js +71 -0
  114. package/dist/auto-ui/types.js.map +1 -0
  115. package/dist/beam.bundle.js +13506 -0
  116. package/dist/beam.bundle.js.map +7 -0
  117. package/dist/claude-code-plugin.d.ts.map +1 -1
  118. package/dist/claude-code-plugin.js +30 -30
  119. package/dist/claude-code-plugin.js.map +1 -1
  120. package/dist/cli/commands/info.d.ts +11 -0
  121. package/dist/cli/commands/info.d.ts.map +1 -0
  122. package/dist/cli/commands/info.js +313 -0
  123. package/dist/cli/commands/info.js.map +1 -0
  124. package/dist/cli/commands/marketplace.d.ts +11 -0
  125. package/dist/cli/commands/marketplace.d.ts.map +1 -0
  126. package/dist/cli/commands/marketplace.js +198 -0
  127. package/dist/cli/commands/marketplace.js.map +1 -0
  128. package/dist/cli/commands/package-app.d.ts +9 -0
  129. package/dist/cli/commands/package-app.d.ts.map +1 -0
  130. package/dist/cli/commands/package-app.js +191 -0
  131. package/dist/cli/commands/package-app.js.map +1 -0
  132. package/dist/cli/commands/package.d.ts +11 -0
  133. package/dist/cli/commands/package.d.ts.map +1 -0
  134. package/dist/cli/commands/package.js +573 -0
  135. package/dist/cli/commands/package.js.map +1 -0
  136. package/dist/cli-alias.d.ts.map +1 -1
  137. package/dist/cli-alias.js +30 -28
  138. package/dist/cli-alias.js.map +1 -1
  139. package/dist/cli-formatter.d.ts +8 -24
  140. package/dist/cli-formatter.d.ts.map +1 -1
  141. package/dist/cli-formatter.js +8 -325
  142. package/dist/cli-formatter.js.map +1 -1
  143. package/dist/cli.d.ts +15 -1
  144. package/dist/cli.d.ts.map +1 -1
  145. package/dist/cli.js +1157 -1132
  146. package/dist/cli.js.map +1 -1
  147. package/dist/daemon/client.d.ts +81 -0
  148. package/dist/daemon/client.d.ts.map +1 -1
  149. package/dist/daemon/client.js +583 -13
  150. package/dist/daemon/client.js.map +1 -1
  151. package/dist/daemon/manager.d.ts +46 -12
  152. package/dist/daemon/manager.d.ts.map +1 -1
  153. package/dist/daemon/manager.js +102 -61
  154. package/dist/daemon/manager.js.map +1 -1
  155. package/dist/daemon/protocol.d.ts +74 -6
  156. package/dist/daemon/protocol.d.ts.map +1 -1
  157. package/dist/daemon/protocol.js +76 -1
  158. package/dist/daemon/protocol.js.map +1 -1
  159. package/dist/daemon/server.d.ts +6 -6
  160. package/dist/daemon/server.js +778 -117
  161. package/dist/daemon/server.js.map +1 -1
  162. package/dist/daemon/session-manager.d.ts +8 -1
  163. package/dist/daemon/session-manager.d.ts.map +1 -1
  164. package/dist/daemon/session-manager.js +32 -9
  165. package/dist/daemon/session-manager.js.map +1 -1
  166. package/dist/deploy/cloudflare.d.ts +12 -0
  167. package/dist/deploy/cloudflare.d.ts.map +1 -0
  168. package/dist/deploy/cloudflare.js +216 -0
  169. package/dist/deploy/cloudflare.js.map +1 -0
  170. package/dist/index.d.ts +1 -0
  171. package/dist/index.d.ts.map +1 -1
  172. package/dist/index.js +3 -0
  173. package/dist/index.js.map +1 -1
  174. package/dist/loader.d.ts +172 -15
  175. package/dist/loader.d.ts.map +1 -1
  176. package/dist/loader.js +1132 -267
  177. package/dist/loader.js.map +1 -1
  178. package/dist/markdown-utils.d.ts +8 -0
  179. package/dist/markdown-utils.d.ts.map +1 -0
  180. package/dist/markdown-utils.js +63 -0
  181. package/dist/markdown-utils.js.map +1 -0
  182. package/dist/marketplace-manager.d.ts +10 -0
  183. package/dist/marketplace-manager.d.ts.map +1 -1
  184. package/dist/marketplace-manager.js +112 -28
  185. package/dist/marketplace-manager.js.map +1 -1
  186. package/dist/mcp-client.d.ts +9 -0
  187. package/dist/mcp-client.d.ts.map +1 -0
  188. package/dist/mcp-client.js +11 -0
  189. package/dist/mcp-client.js.map +1 -0
  190. package/dist/mcp-elicitation.d.ts +32 -0
  191. package/dist/mcp-elicitation.d.ts.map +1 -0
  192. package/dist/mcp-elicitation.js +26 -0
  193. package/dist/mcp-elicitation.js.map +1 -0
  194. package/dist/path-resolver.d.ts +9 -12
  195. package/dist/path-resolver.d.ts.map +1 -1
  196. package/dist/path-resolver.js +13 -43
  197. package/dist/path-resolver.js.map +1 -1
  198. package/dist/photon-cli-runner.d.ts.map +1 -1
  199. package/dist/photon-cli-runner.js +216 -73
  200. package/dist/photon-cli-runner.js.map +1 -1
  201. package/dist/photon-doc-extractor.d.ts +88 -0
  202. package/dist/photon-doc-extractor.d.ts.map +1 -1
  203. package/dist/photon-doc-extractor.js +536 -27
  204. package/dist/photon-doc-extractor.js.map +1 -1
  205. package/dist/photons/maker.photon.d.ts +182 -0
  206. package/dist/photons/maker.photon.d.ts.map +1 -0
  207. package/dist/photons/maker.photon.js +504 -0
  208. package/dist/photons/maker.photon.js.map +1 -0
  209. package/dist/photons/maker.photon.ts +626 -0
  210. package/dist/photons/marketplace.photon.d.ts +110 -0
  211. package/dist/photons/marketplace.photon.d.ts.map +1 -0
  212. package/dist/photons/marketplace.photon.js +260 -0
  213. package/dist/photons/marketplace.photon.js.map +1 -0
  214. package/dist/photons/marketplace.photon.ts +378 -0
  215. package/dist/photons/tunnel.photon.d.ts +80 -0
  216. package/dist/photons/tunnel.photon.d.ts.map +1 -0
  217. package/dist/photons/tunnel.photon.js +269 -0
  218. package/dist/photons/tunnel.photon.js.map +1 -0
  219. package/dist/photons/tunnel.photon.ts +345 -0
  220. package/dist/security-scanner.d.ts.map +1 -1
  221. package/dist/security-scanner.js +18 -15
  222. package/dist/security-scanner.js.map +1 -1
  223. package/dist/serv/auth/jwt.d.ts +89 -0
  224. package/dist/serv/auth/jwt.d.ts.map +1 -0
  225. package/dist/serv/auth/jwt.js +239 -0
  226. package/dist/serv/auth/jwt.js.map +1 -0
  227. package/dist/serv/auth/oauth.d.ts +117 -0
  228. package/dist/serv/auth/oauth.d.ts.map +1 -0
  229. package/dist/serv/auth/oauth.js +395 -0
  230. package/dist/serv/auth/oauth.js.map +1 -0
  231. package/dist/serv/auth/well-known.d.ts +60 -0
  232. package/dist/serv/auth/well-known.d.ts.map +1 -0
  233. package/dist/serv/auth/well-known.js +154 -0
  234. package/dist/serv/auth/well-known.js.map +1 -0
  235. package/dist/serv/db/d1-client.d.ts +65 -0
  236. package/dist/serv/db/d1-client.d.ts.map +1 -0
  237. package/dist/serv/db/d1-client.js +137 -0
  238. package/dist/serv/db/d1-client.js.map +1 -0
  239. package/dist/serv/db/d1-stores.d.ts +62 -0
  240. package/dist/serv/db/d1-stores.d.ts.map +1 -0
  241. package/dist/serv/db/d1-stores.js +307 -0
  242. package/dist/serv/db/d1-stores.js.map +1 -0
  243. package/dist/serv/index.d.ts +114 -0
  244. package/dist/serv/index.d.ts.map +1 -0
  245. package/dist/serv/index.js +172 -0
  246. package/dist/serv/index.js.map +1 -0
  247. package/dist/serv/local.d.ts +118 -0
  248. package/dist/serv/local.d.ts.map +1 -0
  249. package/dist/serv/local.js +392 -0
  250. package/dist/serv/local.js.map +1 -0
  251. package/dist/serv/middleware/auth.d.ts +66 -0
  252. package/dist/serv/middleware/auth.d.ts.map +1 -0
  253. package/dist/serv/middleware/auth.js +178 -0
  254. package/dist/serv/middleware/auth.js.map +1 -0
  255. package/dist/serv/middleware/tenant.d.ts +94 -0
  256. package/dist/serv/middleware/tenant.d.ts.map +1 -0
  257. package/dist/serv/middleware/tenant.js +152 -0
  258. package/dist/serv/middleware/tenant.js.map +1 -0
  259. package/dist/serv/runtime/executor.d.ts +76 -0
  260. package/dist/serv/runtime/executor.d.ts.map +1 -0
  261. package/dist/serv/runtime/executor.js +105 -0
  262. package/dist/serv/runtime/executor.js.map +1 -0
  263. package/dist/serv/runtime/index.d.ts +8 -0
  264. package/dist/serv/runtime/index.d.ts.map +1 -0
  265. package/dist/serv/runtime/index.js +10 -0
  266. package/dist/serv/runtime/index.js.map +1 -0
  267. package/dist/serv/runtime/oauth-context.d.ts +121 -0
  268. package/dist/serv/runtime/oauth-context.d.ts.map +1 -0
  269. package/dist/serv/runtime/oauth-context.js +153 -0
  270. package/dist/serv/runtime/oauth-context.js.map +1 -0
  271. package/dist/serv/session/kv-store.d.ts +54 -0
  272. package/dist/serv/session/kv-store.d.ts.map +1 -0
  273. package/dist/serv/session/kv-store.js +149 -0
  274. package/dist/serv/session/kv-store.js.map +1 -0
  275. package/dist/serv/session/store.d.ts +113 -0
  276. package/dist/serv/session/store.d.ts.map +1 -0
  277. package/dist/serv/session/store.js +284 -0
  278. package/dist/serv/session/store.js.map +1 -0
  279. package/dist/serv/types/index.d.ts +147 -0
  280. package/dist/serv/types/index.d.ts.map +1 -0
  281. package/dist/serv/types/index.js +8 -0
  282. package/dist/serv/types/index.js.map +1 -0
  283. package/dist/serv/vault/token-vault.d.ts +102 -0
  284. package/dist/serv/vault/token-vault.d.ts.map +1 -0
  285. package/dist/serv/vault/token-vault.js +177 -0
  286. package/dist/serv/vault/token-vault.js.map +1 -0
  287. package/dist/server.d.ts +173 -0
  288. package/dist/server.d.ts.map +1 -1
  289. package/dist/server.js +1622 -86
  290. package/dist/server.js.map +1 -1
  291. package/dist/shared/cli-sections.d.ts +6 -0
  292. package/dist/shared/cli-sections.d.ts.map +1 -0
  293. package/dist/shared/cli-sections.js +16 -0
  294. package/dist/shared/cli-sections.js.map +1 -0
  295. package/dist/shared/cli-utils.d.ts +81 -0
  296. package/dist/shared/cli-utils.d.ts.map +1 -0
  297. package/dist/shared/cli-utils.js +174 -0
  298. package/dist/shared/cli-utils.js.map +1 -0
  299. package/dist/shared/config-docs.d.ts +6 -0
  300. package/dist/shared/config-docs.d.ts.map +1 -0
  301. package/dist/shared/config-docs.js +6 -0
  302. package/dist/shared/config-docs.js.map +1 -0
  303. package/dist/shared/error-handler.d.ts +128 -0
  304. package/dist/shared/error-handler.d.ts.map +1 -0
  305. package/dist/shared/error-handler.js +342 -0
  306. package/dist/shared/error-handler.js.map +1 -0
  307. package/dist/shared/logger.d.ts +42 -0
  308. package/dist/shared/logger.d.ts.map +1 -0
  309. package/dist/shared/logger.js +123 -0
  310. package/dist/shared/logger.js.map +1 -0
  311. package/dist/shared/performance.d.ts +65 -0
  312. package/dist/shared/performance.d.ts.map +1 -0
  313. package/dist/shared/performance.js +136 -0
  314. package/dist/shared/performance.js.map +1 -0
  315. package/dist/shared/task-runner.d.ts +2 -0
  316. package/dist/shared/task-runner.d.ts.map +1 -0
  317. package/dist/shared/task-runner.js +16 -0
  318. package/dist/shared/task-runner.js.map +1 -0
  319. package/dist/shared/validation.d.ts +6 -0
  320. package/dist/shared/validation.d.ts.map +1 -0
  321. package/dist/shared/validation.js +6 -0
  322. package/dist/shared/validation.js.map +1 -0
  323. package/dist/shared-utils.d.ts +63 -0
  324. package/dist/shared-utils.d.ts.map +1 -0
  325. package/dist/shared-utils.js +123 -0
  326. package/dist/shared-utils.js.map +1 -0
  327. package/dist/template-manager.d.ts +23 -2
  328. package/dist/template-manager.d.ts.map +1 -1
  329. package/dist/template-manager.js +177 -88
  330. package/dist/template-manager.js.map +1 -1
  331. package/dist/test-client.d.ts.map +1 -1
  332. package/dist/test-client.js +10 -8
  333. package/dist/test-client.js.map +1 -1
  334. package/dist/test-runner.d.ts +52 -0
  335. package/dist/test-runner.d.ts.map +1 -0
  336. package/dist/test-runner.js +785 -0
  337. package/dist/test-runner.js.map +1 -0
  338. package/dist/testing.d.ts +103 -0
  339. package/dist/testing.d.ts.map +1 -0
  340. package/dist/testing.js +163 -0
  341. package/dist/testing.js.map +1 -0
  342. package/dist/version-checker.d.ts.map +1 -1
  343. package/dist/version-checker.js +2 -2
  344. package/dist/version-checker.js.map +1 -1
  345. package/dist/version.d.ts +2 -0
  346. package/dist/version.d.ts.map +1 -0
  347. package/dist/version.js +5 -0
  348. package/dist/version.js.map +1 -0
  349. package/dist/watcher.d.ts +6 -3
  350. package/dist/watcher.d.ts.map +1 -1
  351. package/dist/watcher.js +49 -10
  352. package/dist/watcher.js.map +1 -1
  353. package/package.json +47 -7
  354. package/templates/cloudflare/worker.ts.template +381 -0
  355. package/templates/cloudflare/wrangler.toml.template +9 -0
  356. package/dist/base.d.ts +0 -58
  357. package/dist/base.d.ts.map +0 -1
  358. package/dist/base.js +0 -92
  359. package/dist/base.js.map +0 -1
  360. package/dist/dependency-manager.d.ts +0 -49
  361. package/dist/dependency-manager.d.ts.map +0 -1
  362. package/dist/dependency-manager.js +0 -165
  363. package/dist/dependency-manager.js.map +0 -1
  364. package/dist/registry-manager.d.ts +0 -76
  365. package/dist/registry-manager.d.ts.map +0 -1
  366. package/dist/registry-manager.js +0 -220
  367. package/dist/registry-manager.js.map +0 -1
  368. package/dist/schema-extractor.d.ts +0 -110
  369. package/dist/schema-extractor.d.ts.map +0 -1
  370. package/dist/schema-extractor.js +0 -727
  371. package/dist/schema-extractor.js.map +0 -1
  372. package/dist/test-marketplace-sources.d.ts +0 -5
  373. package/dist/test-marketplace-sources.d.ts.map +0 -1
  374. package/dist/test-marketplace-sources.js +0 -53
  375. package/dist/test-marketplace-sources.js.map +0 -1
  376. package/dist/types.d.ts +0 -109
  377. package/dist/types.d.ts.map +0 -1
  378. package/dist/types.js +0 -12
  379. package/dist/types.js.map +0 -1
@@ -1,5 +1,7 @@
1
1
  import * as fs from 'fs/promises';
2
+ import * as path from 'path';
2
3
  import { SchemaExtractor } from '@portel/photon-core';
4
+ import { PHOTON_VERSION } from './version.js';
3
5
  /**
4
6
  * Extracts comprehensive documentation from Photon files
5
7
  *
@@ -22,20 +24,34 @@ export class PhotonDocExtractor {
22
24
  this.content = await fs.readFile(this.filePath, 'utf-8');
23
25
  const statefulTag = this.extractTag('stateful');
24
26
  const idleTimeoutTag = this.extractTag('idleTimeout');
27
+ const internalTag = this.extractTag('internal');
28
+ const tools = await this.extractTools();
29
+ const photonType = this.detectPhotonType(tools);
30
+ const features = this.detectFeatures(tools, statefulTag !== undefined);
31
+ const externalDeps = this.extractDependencies();
32
+ const diagram = this.generateDiagramSync(tools, photonType, externalDeps);
25
33
  return {
26
34
  name: this.extractName(),
27
- version: this.extractTag('version') || '1.0.0',
35
+ version: this.extractTag('version') || PHOTON_VERSION,
28
36
  description: this.extractDescription(),
29
37
  author: this.extractTag('author'),
30
38
  license: this.extractTag('license'),
31
39
  repository: this.extractTag('repository'),
32
40
  homepage: this.extractTag('homepage'),
41
+ icon: this.extractTag('icon'),
42
+ internal: internalTag !== undefined,
33
43
  configParams: this.extractConfigParams(),
34
44
  setupInstructions: this.extractSetupInstructions(),
35
- tools: await this.extractTools(),
45
+ tools,
36
46
  dependencies: this.extractTag('dependencies'),
37
- stateful: statefulTag === 'true',
47
+ runtime: this.extractTag('runtime'),
48
+ stateful: statefulTag !== undefined,
38
49
  idleTimeout: idleTimeoutTag ? parseInt(idleTimeoutTag, 10) : undefined,
50
+ assets: await this.extractAssets(),
51
+ photonType,
52
+ features,
53
+ externalDeps,
54
+ diagram,
39
55
  };
40
56
  }
41
57
  /**
@@ -62,9 +78,18 @@ export class PhotonDocExtractor {
62
78
  * Extract a specific JSDoc tag value
63
79
  */
64
80
  extractTag(tagName) {
65
- const regex = new RegExp(`@${tagName}\\s+(.+?)(?=\\n|$)`, 'm');
66
- const match = this.content.match(regex);
67
- return match ? match[1].trim() : undefined;
81
+ // First try to match tag with value: @tagName value
82
+ const regexWithValue = new RegExp(`@${tagName}\\s+(.+?)(?=\\n|$)`, 'm');
83
+ const matchWithValue = this.content.match(regexWithValue);
84
+ if (matchWithValue) {
85
+ return matchWithValue[1].trim();
86
+ }
87
+ // Then check for boolean tag without value: @tagName (followed by newline, *, or end)
88
+ const regexBoolean = new RegExp(`@${tagName}(?:\\s*\\n|\\s*\\*|$)`, 'm');
89
+ if (this.content.match(regexBoolean)) {
90
+ return 'true'; // Presence of tag means true
91
+ }
92
+ return undefined;
68
93
  }
69
94
  /**
70
95
  * Extract configuration parameters from constructor
@@ -80,7 +105,10 @@ export class PhotonDocExtractor {
80
105
  return params.map((param) => {
81
106
  // Convert to environment variable format
82
107
  // ClassName -> class-name -> CLASS_NAME_PARAM_NAME
83
- const kebabCase = className.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
108
+ const kebabCase = className
109
+ .replace(/([A-Z])/g, '-$1')
110
+ .toLowerCase()
111
+ .replace(/^-/, '');
84
112
  const envPrefix = kebabCase.toUpperCase().replace(/-/g, '_');
85
113
  const envVar = `${envPrefix}_${param.name.toUpperCase()}`;
86
114
  // Find description from Configuration section
@@ -138,21 +166,74 @@ export class PhotonDocExtractor {
138
166
  // Clean up the configuration text
139
167
  return configMatch[1]
140
168
  .split('\n')
141
- .map(line => line.replace(/^\s*\*\s?/, '').trim())
142
- .filter(line => line.length > 0)
169
+ .map((line) => line.replace(/^\s*\*\s?/, '').trim())
170
+ .filter((line) => line.length > 0)
143
171
  .join('\n')
144
172
  .trim();
145
173
  }
174
+ /**
175
+ * Extract assets associated with the Photon
176
+ * Scans for ui/, prompts/, resources/ folders and @ui annotations
177
+ */
178
+ async extractAssets() {
179
+ const assets = new Set();
180
+ const dir = path.dirname(this.filePath);
181
+ const basename = path.basename(this.filePath, '.photon.ts');
182
+ // Convention: asset folder has same name as photon (without .photon.ts)
183
+ // e.g. test-ui.photon.ts -> test-ui/
184
+ const assetFolder = path.join(dir, basename);
185
+ // Check if asset folder exists
186
+ try {
187
+ const stats = await fs.stat(assetFolder);
188
+ if (stats.isDirectory()) {
189
+ // Recursively find all files in the asset folder
190
+ const findFiles = async (currentDir, relativePath) => {
191
+ const entries = await fs.readdir(currentDir, { withFileTypes: true });
192
+ for (const entry of entries) {
193
+ const entryPath = path.join(currentDir, entry.name);
194
+ const entryRelative = path.join(relativePath, entry.name);
195
+ if (entry.isDirectory()) {
196
+ await findFiles(entryPath, entryRelative);
197
+ }
198
+ else {
199
+ // Add relative path from photon file's directory
200
+ // e.g. test-ui/ui/index.html
201
+ assets.add(path.join(basename, entryRelative));
202
+ }
203
+ }
204
+ };
205
+ await findFiles(assetFolder, '');
206
+ }
207
+ }
208
+ catch {
209
+ // Asset folder doesn't exist, ignore
210
+ }
211
+ // Extract explicit @ui assets from JSDoc
212
+ // Format: @ui <id> <path>
213
+ const uiRegex = /@ui[ \t]+\S+[ \t]+(\S+)/g;
214
+ let match;
215
+ while ((match = uiRegex.exec(this.content)) !== null) {
216
+ const assetPath = match[1];
217
+ // Only include relative paths
218
+ if (assetPath.startsWith('./') || !path.isAbsolute(assetPath)) {
219
+ // Normalize path
220
+ const normalized = assetPath.startsWith('./') ? assetPath.slice(2) : assetPath;
221
+ assets.add(normalized);
222
+ }
223
+ }
224
+ return Array.from(assets);
225
+ }
146
226
  /**
147
227
  * Extract tool methods with their documentation
148
228
  */
149
229
  async extractTools() {
150
230
  const tools = [];
151
- // First, find all async methods
152
- const methodRegex = /async\s+(\w+)\s*\([^)]*\)/g;
231
+ // Find all async methods (including generators with async *)
232
+ const methodRegex = /async\s+(\*?)\s*(\w+)\s*\([^)]*\)/g;
153
233
  let match;
154
234
  while ((match = methodRegex.exec(this.content)) !== null) {
155
- const methodName = match[1];
235
+ const isGenerator = match[1] === '*';
236
+ const methodName = match[2];
156
237
  const methodIndex = match.index;
157
238
  // Skip private methods (starting with _) and lifecycle methods
158
239
  if (methodName.startsWith('_') ||
@@ -177,6 +258,7 @@ export class PhotonDocExtractor {
177
258
  const jsdoc = jsdocMatch[1];
178
259
  const tool = this.parseToolMethodFromJSDoc(jsdoc, methodName);
179
260
  if (tool) {
261
+ tool.isGenerator = isGenerator;
180
262
  tools.push(tool);
181
263
  }
182
264
  }
@@ -215,24 +297,50 @@ export class PhotonDocExtractor {
215
297
  constraints.push(`pattern: ${patternMatch[1]}`);
216
298
  cleanDesc = cleanDesc.replace(/\{@pattern\s+[^}]+\}\s*/g, '');
217
299
  }
218
- // Extract {@example value} - handle nested braces in JSON examples
300
+ // Extract {@choice value1,value2,...}
301
+ const choiceMatch = cleanDesc.match(/\{@choice\s+([^}]+)\}/);
302
+ if (choiceMatch) {
303
+ constraints.push(`choice: ${choiceMatch[1]}`);
304
+ cleanDesc = cleanDesc.replace(/\{@choice\s+[^}]+\}\s*/g, '');
305
+ }
306
+ // Extract {@field type}
307
+ const fieldMatch = cleanDesc.match(/\{@field\s+([a-z]+)\}/);
308
+ if (fieldMatch) {
309
+ constraints.push(`field: ${fieldMatch[1]}`);
310
+ cleanDesc = cleanDesc.replace(/\{@field\s+[a-z]+\}\s*/g, '');
311
+ }
312
+ // Extract {@example value} - handle nested braces and brackets in JSON examples
219
313
  const exampleStart = cleanDesc.indexOf('{@example ');
220
314
  if (exampleStart !== -1) {
221
315
  const contentStart = exampleStart + '{@example '.length;
222
- let depth = 0;
316
+ let braceDepth = 0;
317
+ let bracketDepth = 0;
223
318
  let i = contentStart;
224
- // Find the closing } by counting braces
319
+ let inString = false;
320
+ // Find the closing } by counting braces and brackets, respecting strings
225
321
  while (i < cleanDesc.length) {
226
- if (cleanDesc[i] === '{')
227
- depth++;
228
- else if (cleanDesc[i] === '}') {
229
- if (depth === 0) {
230
- // Found the closing brace of the {@example} tag
231
- example = cleanDesc.substring(contentStart, i).trim();
232
- cleanDesc = cleanDesc.substring(0, exampleStart) + cleanDesc.substring(i + 1);
233
- break;
322
+ const ch = cleanDesc[i];
323
+ const prevCh = i > 0 ? cleanDesc[i - 1] : '';
324
+ // Handle string boundaries (skip escaped quotes)
325
+ if (ch === '"' && prevCh !== '\\') {
326
+ inString = !inString;
327
+ }
328
+ else if (!inString) {
329
+ if (ch === '{')
330
+ braceDepth++;
331
+ else if (ch === '[')
332
+ bracketDepth++;
333
+ else if (ch === ']')
334
+ bracketDepth--;
335
+ else if (ch === '}') {
336
+ if (braceDepth === 0 && bracketDepth === 0) {
337
+ // Found the closing brace of the {@example} tag
338
+ example = cleanDesc.substring(contentStart, i).trim();
339
+ cleanDesc = cleanDesc.substring(0, exampleStart) + cleanDesc.substring(i + 1);
340
+ break;
341
+ }
342
+ braceDepth--;
234
343
  }
235
- depth--;
236
344
  }
237
345
  i++;
238
346
  }
@@ -254,7 +362,7 @@ export class PhotonDocExtractor {
254
362
  const description = descMatch
255
363
  ? descMatch[1]
256
364
  .split('\n')
257
- .map(line => line.replace(/^\s*\*\s?/, '').trim())
365
+ .map((line) => line.replace(/^\s*\*\s?/, '').trim())
258
366
  .join(' ')
259
367
  .trim()
260
368
  : '';
@@ -271,7 +379,10 @@ export class PhotonDocExtractor {
271
379
  // Format: "Param description (optional)" or "Param description (default: value)"
272
380
  let cleanDesc = parsed.description;
273
381
  const optional = /\(optional\)/i.test(cleanDesc) || /\(default:/i.test(cleanDesc);
274
- cleanDesc = cleanDesc.replace(/\(optional\)/gi, '').replace(/\(default:.*?\)/gi, '').trim();
382
+ cleanDesc = cleanDesc
383
+ .replace(/\(optional\)/gi, '')
384
+ .replace(/\(default:.*?\)/gi, '')
385
+ .trim();
275
386
  params.push({
276
387
  name: paramName,
277
388
  type: 'any', // Type extraction from JSDoc would need more parsing
@@ -288,7 +399,7 @@ export class PhotonDocExtractor {
288
399
  if (exampleMatch) {
289
400
  const exampleText = exampleMatch[1]
290
401
  .split('\n')
291
- .map(line => line.replace(/^\s*\*\s?/, ''))
402
+ .map((line) => line.replace(/^\s*\*\s?/, ''))
292
403
  .join('\n')
293
404
  .trim();
294
405
  // Only use it if it looks like actual code (not just a simple value from inline tag)
@@ -304,5 +415,403 @@ export class PhotonDocExtractor {
304
415
  example,
305
416
  };
306
417
  }
418
+ // ============================================
419
+ // FEATURE DETECTION
420
+ // ============================================
421
+ /**
422
+ * Detect platform features used by this Photon
423
+ */
424
+ detectFeatures(tools, isStateful) {
425
+ const features = [];
426
+ // generator — any async * method
427
+ if (tools.some((t) => t.isGenerator)) {
428
+ features.push('generator');
429
+ }
430
+ // custom-ui — @ui JSDoc tag
431
+ if (this.extractTag('ui') !== undefined || /@ui\s+\S+/.test(this.content)) {
432
+ features.push('custom-ui');
433
+ }
434
+ // elicitation — yield { ask: patterns
435
+ if (/yield\s*\{\s*ask\s*:/.test(this.content) || /yield\*\s/.test(this.content)) {
436
+ features.push('elicitation');
437
+ }
438
+ // streaming — yield { emit: or yield { step:
439
+ if (/yield\s*\{\s*(emit|step)\s*:/.test(this.content)) {
440
+ features.push('streaming');
441
+ }
442
+ // oauth — yield { ask: 'oauth'
443
+ if (/yield\s*\{\s*ask\s*:\s*['"]oauth['"]/.test(this.content)) {
444
+ features.push('oauth');
445
+ }
446
+ // stateful — @stateful tag
447
+ if (isStateful) {
448
+ features.push('stateful');
449
+ }
450
+ // webhooks — webhook endpoint patterns
451
+ if (/webhook/i.test(this.content) && /@webhook/.test(this.content)) {
452
+ features.push('webhooks');
453
+ }
454
+ // channels — channel in emit patterns
455
+ if (/channel/i.test(this.content) && /emit/.test(this.content)) {
456
+ features.push('channels');
457
+ }
458
+ // locks — acquireLock / releaseLock
459
+ if (/acquireLock|releaseLock/.test(this.content)) {
460
+ features.push('locks');
461
+ }
462
+ // mcp-bridge — this.mcp( calls
463
+ if (/this\.mcp\(/.test(this.content)) {
464
+ features.push('mcp-bridge');
465
+ }
466
+ // photon-bridge — this.photon( calls
467
+ if (/this\.photon\(/.test(this.content)) {
468
+ features.push('photon-bridge');
469
+ }
470
+ // wizard — @wizard tag
471
+ if (this.extractTag('wizard') !== undefined) {
472
+ features.push('wizard');
473
+ }
474
+ // dashboard — @ui + main method with linkedUi pattern
475
+ if (features.includes('custom-ui') &&
476
+ /async\s+\*?\s*main\b/.test(this.content) &&
477
+ /linkedUi|dashboard/i.test(this.content)) {
478
+ features.push('dashboard');
479
+ }
480
+ return features;
481
+ }
482
+ // ============================================
483
+ // DIAGRAM GENERATION
484
+ // ============================================
485
+ /**
486
+ * Generate a Mermaid diagram for this Photon
487
+ * Automatically detects the Photon type and generates appropriate diagram
488
+ */
489
+ async generateDiagram() {
490
+ if (!this.content) {
491
+ this.content = await fs.readFile(this.filePath, 'utf-8');
492
+ }
493
+ const tools = await this.extractTools();
494
+ const photonType = this.detectPhotonType(tools);
495
+ const name = this.extractName();
496
+ const deps = this.extractDependencies();
497
+ switch (photonType) {
498
+ case 'workflow':
499
+ return this.generateWorkflowDiagram(name, tools, deps);
500
+ case 'streaming':
501
+ return this.generateStreamingDiagram(name, tools, deps);
502
+ default:
503
+ return this.generateApiSurfaceDiagram(name, tools, deps);
504
+ }
505
+ }
506
+ /**
507
+ * Generate diagram synchronously when content and tools are already loaded
508
+ */
509
+ generateDiagramSync(tools, photonType, deps) {
510
+ const name = this.extractName();
511
+ switch (photonType) {
512
+ case 'workflow':
513
+ return this.generateWorkflowDiagram(name, tools, deps);
514
+ case 'streaming':
515
+ return this.generateStreamingDiagram(name, tools, deps);
516
+ default:
517
+ return this.generateApiSurfaceDiagram(name, tools, deps);
518
+ }
519
+ }
520
+ /**
521
+ * Detect the type of Photon based on its methods
522
+ */
523
+ detectPhotonType(tools) {
524
+ const hasGenerator = tools.some((t) => t.isGenerator);
525
+ const hasAskEmit = this.hasAskEmitPatterns();
526
+ if (hasGenerator && hasAskEmit)
527
+ return 'workflow';
528
+ if (hasGenerator)
529
+ return 'streaming';
530
+ return 'api';
531
+ }
532
+ /**
533
+ * Check if content has ask/emit yield patterns
534
+ */
535
+ hasAskEmitPatterns() {
536
+ return /yield\s*\{\s*(ask|emit)\s*:/.test(this.content);
537
+ }
538
+ /**
539
+ * Extract dependencies from JSDoc tags
540
+ */
541
+ extractDependencies() {
542
+ const mcpsTag = this.extractTag('mcps');
543
+ const photonsTag = this.extractTag('photons');
544
+ const depsTag = this.extractTag('dependencies');
545
+ return {
546
+ mcps: mcpsTag ? mcpsTag.split(/[,\s]+/).filter(Boolean) : [],
547
+ photons: photonsTag ? photonsTag.split(/[,\s]+/).filter(Boolean) : [],
548
+ npm: depsTag
549
+ ? depsTag
550
+ .split(/[,\s]+/)
551
+ .map((d) => d.split('@')[0])
552
+ .filter(Boolean)
553
+ : [],
554
+ };
555
+ }
556
+ /**
557
+ * Extract yield statements from content
558
+ */
559
+ extractYieldStatements() {
560
+ const yields = [];
561
+ // Match: const varName = yield { ask: 'type', message: '...' }
562
+ // or: yield { emit: 'type', message: '...' }
563
+ const yieldRegex = /(?:const\s+(\w+)\s*(?::\s*\w+)?\s*=\s*)?yield\s*\{\s*(ask|emit)\s*:\s*['"](\w+)['"]\s*(?:,\s*message\s*:\s*[`'"]([^`'"]*)[`'"])?/g;
564
+ let match;
565
+ while ((match = yieldRegex.exec(this.content)) !== null) {
566
+ yields.push({
567
+ variable: match[1],
568
+ type: match[2],
569
+ subtype: match[3],
570
+ message: match[4],
571
+ });
572
+ }
573
+ return yields;
574
+ }
575
+ /**
576
+ * Extract MCP and Photon calls from content
577
+ */
578
+ extractExternalCalls() {
579
+ const calls = [];
580
+ // Match: this.mcp('name').method() or await this.mcp('name').method()
581
+ const mcpRegex = /this\.mcp\(['"](\w+)['"]\)\.(\w+)/g;
582
+ let match;
583
+ while ((match = mcpRegex.exec(this.content)) !== null) {
584
+ calls.push({ type: 'mcp', name: match[1], method: match[2] });
585
+ }
586
+ // Match: this.photon('name').method() or yield* this.photon('name').method()
587
+ const photonRegex = /this\.photon\(['"](\w+)['"]\)\.(\w+)/g;
588
+ while ((match = photonRegex.exec(this.content)) !== null) {
589
+ calls.push({ type: 'photon', name: match[1], method: match[2] });
590
+ }
591
+ return calls;
592
+ }
593
+ /**
594
+ * Infer emoji based on method/tool name
595
+ */
596
+ inferEmoji(name) {
597
+ const lower = name.toLowerCase();
598
+ if (/^(read|get|fetch|load|find|query|search|list)/.test(lower))
599
+ return '📖';
600
+ if (/^(write|create|save|put|add|insert|set)/.test(lower))
601
+ return '✏️';
602
+ if (/^(delete|remove|drop|clear)/.test(lower))
603
+ return '🗑️';
604
+ if (/^(send|post|push|publish|notify)/.test(lower))
605
+ return '📤';
606
+ if (/^(update|modify|patch|edit)/.test(lower))
607
+ return '🔄';
608
+ if (/^(validate|check|verify|test)/.test(lower))
609
+ return '✅';
610
+ if (/^(config|setup|init)/.test(lower))
611
+ return '⚙️';
612
+ if (/^(run|execute|start|begin)/.test(lower))
613
+ return '▶️';
614
+ if (/^(stop|cancel|abort|end)/.test(lower))
615
+ return '⏹️';
616
+ if (/^(connect|login|auth)/.test(lower))
617
+ return '🔌';
618
+ if (/^(download|export)/.test(lower))
619
+ return '📥';
620
+ if (/^(upload|import)/.test(lower))
621
+ return '📤';
622
+ return '🔧';
623
+ }
624
+ /**
625
+ * Get emoji for ask type
626
+ */
627
+ getAskEmoji(subtype) {
628
+ switch (subtype) {
629
+ case 'confirm':
630
+ return '🙋';
631
+ case 'select':
632
+ return '📋';
633
+ case 'text':
634
+ return '✏️';
635
+ case 'number':
636
+ return '🔢';
637
+ case 'password':
638
+ return '🔒';
639
+ case 'date':
640
+ return '📅';
641
+ case 'file':
642
+ return '📁';
643
+ default:
644
+ return '❓';
645
+ }
646
+ }
647
+ /**
648
+ * Get emoji for emit type
649
+ */
650
+ getEmitEmoji(subtype) {
651
+ switch (subtype) {
652
+ case 'status':
653
+ return '📢';
654
+ case 'progress':
655
+ return '⏳';
656
+ case 'log':
657
+ return '📝';
658
+ case 'toast':
659
+ return '🎉';
660
+ case 'thinking':
661
+ return '🧠';
662
+ case 'artifact':
663
+ return '📊';
664
+ case 'stream':
665
+ return '💬';
666
+ default:
667
+ return '📣';
668
+ }
669
+ }
670
+ /**
671
+ * Generate API surface diagram for tool collection Photons
672
+ */
673
+ generateApiSurfaceDiagram(name, tools, deps) {
674
+ const lines = ['flowchart LR'];
675
+ // Main photon subgraph
676
+ lines.push(` subgraph ${this.sanitizeId(name)}["📦 ${this.titleCase(name)}"]`);
677
+ lines.push(' direction TB');
678
+ lines.push(' PHOTON((🎯))');
679
+ tools.forEach((tool, i) => {
680
+ const emoji = this.inferEmoji(tool.name);
681
+ const id = `T${i}`;
682
+ lines.push(` ${id}[${emoji} ${tool.name}]`);
683
+ lines.push(` PHOTON --> ${id}`);
684
+ });
685
+ lines.push(' end');
686
+ // Dependencies subgraph (if any)
687
+ const hasDeps = deps.mcps.length > 0 || deps.photons.length > 0 || deps.npm.length > 0;
688
+ if (hasDeps) {
689
+ lines.push('');
690
+ lines.push(' subgraph deps["Dependencies"]');
691
+ lines.push(' direction TB');
692
+ deps.mcps.forEach((mcp, i) => {
693
+ lines.push(` MCP${i}[🔌 ${mcp}]`);
694
+ });
695
+ deps.photons.forEach((photon, i) => {
696
+ lines.push(` PHO${i}[📦 ${photon}]`);
697
+ });
698
+ deps.npm.forEach((pkg, i) => {
699
+ lines.push(` NPM${i}[📚 ${pkg}]`);
700
+ });
701
+ lines.push(' end');
702
+ }
703
+ return lines.join('\n');
704
+ }
705
+ /**
706
+ * Generate streaming diagram for generator Photons without ask/emit
707
+ */
708
+ generateStreamingDiagram(name, tools, deps) {
709
+ // For streaming, show tools with streaming indicator
710
+ const lines = ['flowchart LR'];
711
+ lines.push(` subgraph ${this.sanitizeId(name)}["📦 ${this.titleCase(name)}"]`);
712
+ lines.push(' direction TB');
713
+ lines.push(' PHOTON((🎯))');
714
+ tools.forEach((tool, i) => {
715
+ const emoji = tool.isGenerator ? '🌊' : this.inferEmoji(tool.name);
716
+ const id = `T${i}`;
717
+ const suffix = tool.isGenerator ? ' (stream)' : '';
718
+ lines.push(` ${id}[${emoji} ${tool.name}${suffix}]`);
719
+ lines.push(` PHOTON --> ${id}`);
720
+ });
721
+ lines.push(' end');
722
+ return lines.join('\n');
723
+ }
724
+ /**
725
+ * Generate workflow flowchart for Photons with ask/emit patterns
726
+ */
727
+ generateWorkflowDiagram(name, tools, deps) {
728
+ const yields = this.extractYieldStatements();
729
+ const externalCalls = this.extractExternalCalls();
730
+ const lines = ['flowchart TD'];
731
+ lines.push(` subgraph ${this.sanitizeId(name)}["📦 ${this.titleCase(name)}"]`);
732
+ lines.push(' START([▶ Start])');
733
+ let prevNode = 'START';
734
+ let nodeCounter = 0;
735
+ // Process yields and calls in order they appear
736
+ for (const y of yields) {
737
+ const nodeId = `N${nodeCounter++}`;
738
+ if (y.type === 'emit') {
739
+ const emoji = this.getEmitEmoji(y.subtype);
740
+ const msg = y.message ? this.truncate(y.message, 30) : y.subtype;
741
+ lines.push(` ${nodeId}[${emoji} ${msg}]`);
742
+ lines.push(` ${prevNode} --> ${nodeId}`);
743
+ prevNode = nodeId;
744
+ }
745
+ else if (y.type === 'ask') {
746
+ const emoji = this.getAskEmoji(y.subtype);
747
+ const msg = y.message ? this.truncate(y.message, 25) : y.subtype;
748
+ lines.push(` ${nodeId}{${emoji} ${msg}}`);
749
+ lines.push(` ${prevNode} --> ${nodeId}`);
750
+ // For confirm, add Yes/No branches
751
+ if (y.subtype === 'confirm') {
752
+ const cancelId = `N${nodeCounter++}`;
753
+ const continueId = `N${nodeCounter++}`;
754
+ lines.push(` ${cancelId}([❌ Cancelled])`);
755
+ lines.push(` ${nodeId} -->|No| ${cancelId}`);
756
+ lines.push(` ${nodeId} -->|Yes| ${continueId}`);
757
+ // Create a dummy continue node for the flow
758
+ lines.push(` ${continueId}[Continue]`);
759
+ prevNode = continueId;
760
+ }
761
+ else {
762
+ prevNode = nodeId;
763
+ }
764
+ }
765
+ }
766
+ // Add external calls
767
+ for (const call of externalCalls) {
768
+ const nodeId = `N${nodeCounter++}`;
769
+ const emoji = call.type === 'mcp' ? '🔌' : '📦';
770
+ lines.push(` ${nodeId}[${emoji} ${call.name}.${call.method}]`);
771
+ lines.push(` ${prevNode} --> ${nodeId}`);
772
+ prevNode = nodeId;
773
+ }
774
+ // End node
775
+ lines.push(` SUCCESS([✅ Success])`);
776
+ lines.push(` ${prevNode} --> SUCCESS`);
777
+ lines.push(' end');
778
+ // Dependencies
779
+ const hasDeps = deps.mcps.length > 0 || deps.photons.length > 0;
780
+ if (hasDeps) {
781
+ lines.push('');
782
+ lines.push(' subgraph deps["Dependencies"]');
783
+ deps.mcps.forEach((mcp, i) => {
784
+ lines.push(` DEP_MCP${i}[🔌 ${mcp}]`);
785
+ });
786
+ deps.photons.forEach((photon, i) => {
787
+ lines.push(` DEP_PHO${i}[📦 ${photon}]`);
788
+ });
789
+ lines.push(' end');
790
+ }
791
+ return lines.join('\n');
792
+ }
793
+ /**
794
+ * Sanitize string for use as Mermaid node ID
795
+ */
796
+ sanitizeId(str) {
797
+ return str.replace(/[^a-zA-Z0-9_]/g, '_');
798
+ }
799
+ /**
800
+ * Convert kebab-case to Title Case
801
+ */
802
+ titleCase(str) {
803
+ return str
804
+ .split('-')
805
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
806
+ .join(' ');
807
+ }
808
+ /**
809
+ * Truncate string to max length
810
+ */
811
+ truncate(str, maxLen) {
812
+ if (str.length <= maxLen)
813
+ return str;
814
+ return str.slice(0, maxLen - 3) + '...';
815
+ }
307
816
  }
308
817
  //# sourceMappingURL=photon-doc-extractor.js.map