@guuey/create-agentic-app 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/README.md +22 -2
  2. package/dist/{chunk-JD4RAKEG.js → chunk-5V2IFXD4.js} +96 -21
  3. package/dist/cli.cjs +145 -17
  4. package/dist/cli.js +60 -5
  5. package/dist/index.cjs +97 -21
  6. package/dist/index.d.cts +33 -2
  7. package/dist/index.d.ts +33 -2
  8. package/dist/index.js +3 -1
  9. package/dist/templates/{openai-agents-sdk → agentic-app/claude-agent-sdk}/AGENTS.md +2 -2
  10. package/dist/templates/{openai-agents-sdk → agentic-app/claude-agent-sdk}/README.md +23 -7
  11. package/dist/templates/agentic-app/claude-agent-sdk/gitignore +5 -0
  12. package/dist/templates/agentic-app/claude-agent-sdk/guuey.app.json +28 -0
  13. package/dist/templates/agentic-app/claude-agent-sdk/guuey.app.schema.json +119 -0
  14. package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/package.json +6 -3
  15. package/dist/templates/agentic-app/claude-agent-sdk/scripts/bootstrap.mjs +398 -0
  16. package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/web/index.html +0 -1
  17. package/dist/templates/agentic-app/claude-agent-sdk/web/package.json +29 -0
  18. package/dist/templates/agentic-app/claude-agent-sdk/web/src/components/AgentChat.tsx +91 -0
  19. package/dist/templates/agentic-app/claude-agent-sdk/web/src/components/AppShell.tsx +139 -0
  20. package/dist/templates/agentic-app/claude-agent-sdk/web/src/components/BootstrapGate.tsx +30 -0
  21. package/dist/templates/agentic-app/claude-agent-sdk/web/src/components/QrLink.tsx +25 -0
  22. package/dist/templates/agentic-app/claude-agent-sdk/web/src/components/Shell.tsx +50 -0
  23. package/dist/templates/agentic-app/claude-agent-sdk/web/src/config.ts +148 -0
  24. package/dist/templates/agentic-app/claude-agent-sdk/web/src/lib/identity.ts +67 -0
  25. package/dist/templates/agentic-app/claude-agent-sdk/web/src/lib/oidc.ts +79 -0
  26. package/dist/templates/agentic-app/claude-agent-sdk/web/src/lib/status.ts +45 -0
  27. package/dist/templates/agentic-app/claude-agent-sdk/web/src/lib/widget.ts +96 -0
  28. package/dist/templates/agentic-app/claude-agent-sdk/web/src/main.tsx +51 -0
  29. package/dist/templates/agentic-app/claude-agent-sdk/web/src/pages/Dashboard.tsx +33 -0
  30. package/dist/templates/agentic-app/claude-agent-sdk/web/src/pages/Home.tsx +133 -0
  31. package/dist/templates/agentic-app/claude-agent-sdk/web/src/pages/Landing.tsx +65 -0
  32. package/dist/templates/agentic-app/claude-agent-sdk/web/src/pages/Login.tsx +81 -0
  33. package/dist/templates/agentic-app/claude-agent-sdk/web/src/pages/Reports.tsx +9 -0
  34. package/dist/templates/agentic-app/claude-agent-sdk/web/src/pages/TalkOnMobile.tsx +34 -0
  35. package/dist/templates/agentic-app/claude-agent-sdk/web/src/routes.ts +7 -0
  36. package/dist/templates/agentic-app/claude-agent-sdk/web/src/styles-app.css +130 -0
  37. package/dist/templates/agentic-app/claude-agent-sdk/web/src/styles.css +248 -0
  38. package/dist/templates/agentic-app/claude-agent-sdk/web/src/vite-env.d.ts +14 -0
  39. package/dist/templates/agentic-app/claude-agent-sdk/web/tsconfig.json +18 -0
  40. package/dist/templates/agentic-app/claude-agent-sdk/web/vite.config.ts +46 -0
  41. package/dist/templates/{google-adk → agentic-app/google-adk}/AGENTS.md +2 -2
  42. package/dist/templates/agentic-app/google-adk/gitignore +5 -0
  43. package/dist/templates/agentic-app/google-adk/guuey.app.json +28 -0
  44. package/dist/templates/agentic-app/google-adk/guuey.app.schema.json +119 -0
  45. package/dist/templates/{google-adk → agentic-app/google-adk}/package.json +6 -3
  46. package/dist/templates/agentic-app/google-adk/scripts/bootstrap.mjs +398 -0
  47. package/dist/templates/{google-adk → agentic-app/google-adk}/web/index.html +0 -1
  48. package/dist/templates/agentic-app/google-adk/web/package.json +29 -0
  49. package/dist/templates/agentic-app/google-adk/web/src/components/AgentChat.tsx +91 -0
  50. package/dist/templates/agentic-app/google-adk/web/src/components/AppShell.tsx +139 -0
  51. package/dist/templates/agentic-app/google-adk/web/src/components/BootstrapGate.tsx +30 -0
  52. package/dist/templates/agentic-app/google-adk/web/src/components/QrLink.tsx +25 -0
  53. package/dist/templates/agentic-app/google-adk/web/src/components/Shell.tsx +50 -0
  54. package/dist/templates/agentic-app/google-adk/web/src/config.ts +148 -0
  55. package/dist/templates/agentic-app/google-adk/web/src/lib/identity.ts +67 -0
  56. package/dist/templates/agentic-app/google-adk/web/src/lib/oidc.ts +79 -0
  57. package/dist/templates/agentic-app/google-adk/web/src/lib/status.ts +45 -0
  58. package/dist/templates/agentic-app/google-adk/web/src/lib/widget.ts +96 -0
  59. package/dist/templates/agentic-app/google-adk/web/src/main.tsx +51 -0
  60. package/dist/templates/agentic-app/google-adk/web/src/pages/Dashboard.tsx +33 -0
  61. package/dist/templates/agentic-app/google-adk/web/src/pages/Home.tsx +133 -0
  62. package/dist/templates/agentic-app/google-adk/web/src/pages/Landing.tsx +65 -0
  63. package/dist/templates/agentic-app/google-adk/web/src/pages/Login.tsx +81 -0
  64. package/dist/templates/agentic-app/google-adk/web/src/pages/Reports.tsx +9 -0
  65. package/dist/templates/agentic-app/google-adk/web/src/pages/TalkOnMobile.tsx +34 -0
  66. package/dist/templates/agentic-app/google-adk/web/src/routes.ts +7 -0
  67. package/dist/templates/agentic-app/google-adk/web/src/styles-app.css +130 -0
  68. package/dist/templates/agentic-app/google-adk/web/src/styles.css +248 -0
  69. package/dist/templates/agentic-app/google-adk/web/src/vite-env.d.ts +14 -0
  70. package/dist/templates/agentic-app/google-adk/web/tsconfig.json +18 -0
  71. package/dist/templates/agentic-app/google-adk/web/vite.config.ts +46 -0
  72. package/dist/templates/{claude-agent-sdk → agentic-app/openai-agents-sdk}/AGENTS.md +2 -2
  73. package/dist/templates/{claude-agent-sdk → agentic-app/openai-agents-sdk}/README.md +23 -7
  74. package/dist/templates/agentic-app/openai-agents-sdk/gitignore +5 -0
  75. package/dist/templates/agentic-app/openai-agents-sdk/guuey.app.json +28 -0
  76. package/dist/templates/agentic-app/openai-agents-sdk/guuey.app.schema.json +119 -0
  77. package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/package.json +6 -3
  78. package/dist/templates/agentic-app/openai-agents-sdk/scripts/bootstrap.mjs +398 -0
  79. package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/web/index.html +0 -1
  80. package/dist/templates/agentic-app/openai-agents-sdk/web/package.json +29 -0
  81. package/dist/templates/agentic-app/openai-agents-sdk/web/src/components/AgentChat.tsx +91 -0
  82. package/dist/templates/agentic-app/openai-agents-sdk/web/src/components/AppShell.tsx +139 -0
  83. package/dist/templates/agentic-app/openai-agents-sdk/web/src/components/BootstrapGate.tsx +30 -0
  84. package/dist/templates/agentic-app/openai-agents-sdk/web/src/components/QrLink.tsx +25 -0
  85. package/dist/templates/agentic-app/openai-agents-sdk/web/src/components/Shell.tsx +50 -0
  86. package/dist/templates/agentic-app/openai-agents-sdk/web/src/config.ts +148 -0
  87. package/dist/templates/agentic-app/openai-agents-sdk/web/src/lib/identity.ts +67 -0
  88. package/dist/templates/agentic-app/openai-agents-sdk/web/src/lib/oidc.ts +79 -0
  89. package/dist/templates/agentic-app/openai-agents-sdk/web/src/lib/status.ts +45 -0
  90. package/dist/templates/agentic-app/openai-agents-sdk/web/src/lib/widget.ts +96 -0
  91. package/dist/templates/agentic-app/openai-agents-sdk/web/src/main.tsx +51 -0
  92. package/dist/templates/agentic-app/openai-agents-sdk/web/src/pages/Dashboard.tsx +33 -0
  93. package/dist/templates/agentic-app/openai-agents-sdk/web/src/pages/Home.tsx +133 -0
  94. package/dist/templates/agentic-app/openai-agents-sdk/web/src/pages/Landing.tsx +65 -0
  95. package/dist/templates/agentic-app/openai-agents-sdk/web/src/pages/Login.tsx +81 -0
  96. package/dist/templates/agentic-app/openai-agents-sdk/web/src/pages/Reports.tsx +9 -0
  97. package/dist/templates/agentic-app/openai-agents-sdk/web/src/pages/TalkOnMobile.tsx +34 -0
  98. package/dist/templates/agentic-app/openai-agents-sdk/web/src/routes.ts +7 -0
  99. package/dist/templates/agentic-app/openai-agents-sdk/web/src/styles-app.css +130 -0
  100. package/dist/templates/agentic-app/openai-agents-sdk/web/src/styles.css +248 -0
  101. package/dist/templates/agentic-app/openai-agents-sdk/web/src/vite-env.d.ts +14 -0
  102. package/dist/templates/agentic-app/openai-agents-sdk/web/tsconfig.json +18 -0
  103. package/dist/templates/agentic-app/openai-agents-sdk/web/vite.config.ts +46 -0
  104. package/dist/templates/base/claude-agent-sdk/.env.example +4 -0
  105. package/dist/templates/base/claude-agent-sdk/.mcp.json +1 -0
  106. package/dist/templates/base/claude-agent-sdk/AGENTS.md +135 -0
  107. package/dist/templates/base/claude-agent-sdk/README.md +173 -0
  108. package/dist/templates/base/claude-agent-sdk/ggui/blueprints/.gitkeep +0 -0
  109. package/dist/templates/base/claude-agent-sdk/ggui/ggui.json +15 -0
  110. package/dist/templates/base/claude-agent-sdk/ggui/themes/.gitkeep +0 -0
  111. package/dist/templates/base/claude-agent-sdk/gitignore +5 -0
  112. package/dist/templates/base/claude-agent-sdk/guuey.app.json +28 -0
  113. package/dist/templates/base/claude-agent-sdk/guuey.app.schema.json +119 -0
  114. package/dist/templates/base/claude-agent-sdk/guuey.json +14 -0
  115. package/dist/templates/base/claude-agent-sdk/mcps/todo/Dockerfile +46 -0
  116. package/dist/templates/base/claude-agent-sdk/mcps/todo/package.json +22 -0
  117. package/dist/templates/base/claude-agent-sdk/mcps/todo/src/server.ts +173 -0
  118. package/dist/templates/base/claude-agent-sdk/mcps/todo/tsconfig.json +15 -0
  119. package/dist/templates/base/claude-agent-sdk/mcps/todo/tsup.config.ts +14 -0
  120. package/dist/templates/base/claude-agent-sdk/package.json +30 -0
  121. package/dist/templates/base/claude-agent-sdk/pnpm-workspace.yaml +24 -0
  122. package/dist/templates/base/claude-agent-sdk/prompts/system.md +4 -0
  123. package/dist/templates/base/claude-agent-sdk/scripts/bootstrap.mjs +398 -0
  124. package/dist/templates/base/claude-agent-sdk/scripts/dev.mjs +45 -0
  125. package/dist/templates/base/claude-agent-sdk/src/agent-config.ts +77 -0
  126. package/dist/templates/base/claude-agent-sdk/src/worker.ts +89 -0
  127. package/dist/templates/base/claude-agent-sdk/tsconfig.json +15 -0
  128. package/dist/templates/base/claude-agent-sdk/tsup.config.ts +9 -0
  129. package/dist/templates/base/claude-agent-sdk/web/index.html +12 -0
  130. package/dist/templates/{claude-agent-sdk → base/claude-agent-sdk}/web/package.json +11 -8
  131. package/dist/templates/base/claude-agent-sdk/web/src/components/AgentChat.tsx +91 -0
  132. package/dist/templates/base/claude-agent-sdk/web/src/components/BootstrapGate.tsx +30 -0
  133. package/dist/templates/base/claude-agent-sdk/web/src/components/QrLink.tsx +25 -0
  134. package/dist/templates/base/claude-agent-sdk/web/src/components/Shell.tsx +50 -0
  135. package/dist/templates/base/claude-agent-sdk/web/src/config.ts +148 -0
  136. package/dist/templates/base/claude-agent-sdk/web/src/lib/identity.ts +67 -0
  137. package/dist/templates/base/claude-agent-sdk/web/src/lib/oidc.ts +79 -0
  138. package/dist/templates/base/claude-agent-sdk/web/src/lib/status.ts +45 -0
  139. package/dist/templates/base/claude-agent-sdk/web/src/lib/widget.ts +96 -0
  140. package/dist/templates/base/claude-agent-sdk/web/src/main.tsx +52 -0
  141. package/dist/templates/base/claude-agent-sdk/web/src/pages/Chat.tsx +15 -0
  142. package/dist/templates/base/claude-agent-sdk/web/src/pages/Home.tsx +133 -0
  143. package/dist/templates/base/claude-agent-sdk/web/src/pages/Landing.tsx +65 -0
  144. package/dist/templates/base/claude-agent-sdk/web/src/pages/Login.tsx +81 -0
  145. package/dist/templates/base/claude-agent-sdk/web/src/routes.ts +7 -0
  146. package/dist/templates/base/claude-agent-sdk/web/src/styles.css +248 -0
  147. package/dist/templates/base/claude-agent-sdk/web/src/vite-env.d.ts +14 -0
  148. package/dist/templates/base/claude-agent-sdk/web/tsconfig.json +18 -0
  149. package/dist/templates/base/claude-agent-sdk/web/vite.config.ts +46 -0
  150. package/dist/templates/base/google-adk/.env.example +4 -0
  151. package/dist/templates/base/google-adk/.mcp.json +1 -0
  152. package/dist/templates/base/google-adk/AGENTS.md +135 -0
  153. package/dist/templates/base/google-adk/README.md +90 -0
  154. package/dist/templates/base/google-adk/ggui/blueprints/.gitkeep +0 -0
  155. package/dist/templates/base/google-adk/ggui/ggui.json +15 -0
  156. package/dist/templates/base/google-adk/ggui/themes/.gitkeep +0 -0
  157. package/dist/templates/base/google-adk/gitignore +5 -0
  158. package/dist/templates/base/google-adk/guuey.app.json +28 -0
  159. package/dist/templates/base/google-adk/guuey.app.schema.json +119 -0
  160. package/dist/templates/base/google-adk/guuey.json +15 -0
  161. package/dist/templates/base/google-adk/mcps/todo/Dockerfile +46 -0
  162. package/dist/templates/base/google-adk/mcps/todo/package.json +22 -0
  163. package/dist/templates/base/google-adk/mcps/todo/src/server.ts +173 -0
  164. package/dist/templates/base/google-adk/mcps/todo/tsconfig.json +15 -0
  165. package/dist/templates/base/google-adk/mcps/todo/tsup.config.ts +14 -0
  166. package/dist/templates/base/google-adk/package.json +30 -0
  167. package/dist/templates/base/google-adk/pnpm-workspace.yaml +34 -0
  168. package/dist/templates/base/google-adk/prompts/system.md +4 -0
  169. package/dist/templates/base/google-adk/scripts/bootstrap.mjs +398 -0
  170. package/dist/templates/base/google-adk/scripts/dev.mjs +45 -0
  171. package/dist/templates/base/google-adk/src/agent.ts +43 -0
  172. package/dist/templates/base/google-adk/tsconfig.json +15 -0
  173. package/dist/templates/base/google-adk/tsup.config.ts +13 -0
  174. package/dist/templates/base/google-adk/web/index.html +12 -0
  175. package/dist/templates/{google-adk → base/google-adk}/web/package.json +11 -8
  176. package/dist/templates/base/google-adk/web/src/components/AgentChat.tsx +91 -0
  177. package/dist/templates/base/google-adk/web/src/components/BootstrapGate.tsx +30 -0
  178. package/dist/templates/base/google-adk/web/src/components/QrLink.tsx +25 -0
  179. package/dist/templates/base/google-adk/web/src/components/Shell.tsx +50 -0
  180. package/dist/templates/base/google-adk/web/src/config.ts +148 -0
  181. package/dist/templates/base/google-adk/web/src/lib/identity.ts +67 -0
  182. package/dist/templates/base/google-adk/web/src/lib/oidc.ts +79 -0
  183. package/dist/templates/base/google-adk/web/src/lib/status.ts +45 -0
  184. package/dist/templates/base/google-adk/web/src/lib/widget.ts +96 -0
  185. package/dist/templates/base/google-adk/web/src/main.tsx +52 -0
  186. package/dist/templates/base/google-adk/web/src/pages/Chat.tsx +15 -0
  187. package/dist/templates/base/google-adk/web/src/pages/Home.tsx +133 -0
  188. package/dist/templates/base/google-adk/web/src/pages/Landing.tsx +65 -0
  189. package/dist/templates/base/google-adk/web/src/pages/Login.tsx +81 -0
  190. package/dist/templates/base/google-adk/web/src/routes.ts +7 -0
  191. package/dist/templates/base/google-adk/web/src/styles.css +248 -0
  192. package/dist/templates/base/google-adk/web/src/vite-env.d.ts +14 -0
  193. package/dist/templates/base/google-adk/web/tsconfig.json +18 -0
  194. package/dist/templates/base/google-adk/web/vite.config.ts +46 -0
  195. package/dist/templates/base/openai-agents-sdk/.env.example +4 -0
  196. package/dist/templates/base/openai-agents-sdk/.mcp.json +1 -0
  197. package/dist/templates/base/openai-agents-sdk/AGENTS.md +135 -0
  198. package/dist/templates/base/openai-agents-sdk/README.md +173 -0
  199. package/dist/templates/base/openai-agents-sdk/ggui/blueprints/.gitkeep +0 -0
  200. package/dist/templates/base/openai-agents-sdk/ggui/ggui.json +15 -0
  201. package/dist/templates/base/openai-agents-sdk/ggui/themes/.gitkeep +0 -0
  202. package/dist/templates/base/openai-agents-sdk/gitignore +5 -0
  203. package/dist/templates/base/openai-agents-sdk/guuey.app.json +28 -0
  204. package/dist/templates/base/openai-agents-sdk/guuey.app.schema.json +119 -0
  205. package/dist/templates/base/openai-agents-sdk/guuey.json +27 -0
  206. package/dist/templates/base/openai-agents-sdk/mcps/todo/Dockerfile +46 -0
  207. package/dist/templates/base/openai-agents-sdk/mcps/todo/package.json +22 -0
  208. package/dist/templates/base/openai-agents-sdk/mcps/todo/src/server.ts +173 -0
  209. package/dist/templates/base/openai-agents-sdk/mcps/todo/tsconfig.json +15 -0
  210. package/dist/templates/base/openai-agents-sdk/mcps/todo/tsup.config.ts +14 -0
  211. package/dist/templates/base/openai-agents-sdk/package.json +30 -0
  212. package/dist/templates/base/openai-agents-sdk/pnpm-workspace.yaml +24 -0
  213. package/dist/templates/base/openai-agents-sdk/prompts/system.md +4 -0
  214. package/dist/templates/base/openai-agents-sdk/scripts/bootstrap.mjs +398 -0
  215. package/dist/templates/base/openai-agents-sdk/scripts/dev.mjs +45 -0
  216. package/dist/templates/base/openai-agents-sdk/src/agent-config.ts +77 -0
  217. package/dist/templates/base/openai-agents-sdk/src/worker.ts +75 -0
  218. package/dist/templates/base/openai-agents-sdk/tsconfig.json +15 -0
  219. package/dist/templates/base/openai-agents-sdk/tsup.config.ts +16 -0
  220. package/dist/templates/base/openai-agents-sdk/web/index.html +12 -0
  221. package/dist/templates/{openai-agents-sdk → base/openai-agents-sdk}/web/package.json +11 -8
  222. package/dist/templates/base/openai-agents-sdk/web/src/components/AgentChat.tsx +91 -0
  223. package/dist/templates/base/openai-agents-sdk/web/src/components/BootstrapGate.tsx +30 -0
  224. package/dist/templates/base/openai-agents-sdk/web/src/components/QrLink.tsx +25 -0
  225. package/dist/templates/base/openai-agents-sdk/web/src/components/Shell.tsx +50 -0
  226. package/dist/templates/base/openai-agents-sdk/web/src/config.ts +148 -0
  227. package/dist/templates/base/openai-agents-sdk/web/src/lib/identity.ts +67 -0
  228. package/dist/templates/base/openai-agents-sdk/web/src/lib/oidc.ts +79 -0
  229. package/dist/templates/base/openai-agents-sdk/web/src/lib/status.ts +45 -0
  230. package/dist/templates/base/openai-agents-sdk/web/src/lib/widget.ts +96 -0
  231. package/dist/templates/base/openai-agents-sdk/web/src/main.tsx +52 -0
  232. package/dist/templates/base/openai-agents-sdk/web/src/pages/Chat.tsx +15 -0
  233. package/dist/templates/base/openai-agents-sdk/web/src/pages/Home.tsx +133 -0
  234. package/dist/templates/base/openai-agents-sdk/web/src/pages/Landing.tsx +65 -0
  235. package/dist/templates/base/openai-agents-sdk/web/src/pages/Login.tsx +81 -0
  236. package/dist/templates/base/openai-agents-sdk/web/src/routes.ts +7 -0
  237. package/dist/templates/base/openai-agents-sdk/web/src/styles.css +248 -0
  238. package/dist/templates/base/openai-agents-sdk/web/src/vite-env.d.ts +14 -0
  239. package/dist/templates/base/openai-agents-sdk/web/tsconfig.json +18 -0
  240. package/dist/templates/base/openai-agents-sdk/web/vite.config.ts +46 -0
  241. package/package.json +6 -3
  242. package/dist/templates/claude-agent-sdk/web/.env.example +0 -17
  243. package/dist/templates/claude-agent-sdk/web/sandbox-proxy.ts +0 -239
  244. package/dist/templates/claude-agent-sdk/web/src/App.tsx +0 -272
  245. package/dist/templates/claude-agent-sdk/web/src/main.tsx +0 -12
  246. package/dist/templates/claude-agent-sdk/web/src/useAgentChat.ts +0 -122
  247. package/dist/templates/claude-agent-sdk/web/src/vite-env.d.ts +0 -27
  248. package/dist/templates/claude-agent-sdk/web/tsconfig.json +0 -20
  249. package/dist/templates/claude-agent-sdk/web/vite.config.ts +0 -12
  250. package/dist/templates/google-adk/web/.env.example +0 -17
  251. package/dist/templates/google-adk/web/sandbox-proxy.ts +0 -239
  252. package/dist/templates/google-adk/web/src/App.tsx +0 -272
  253. package/dist/templates/google-adk/web/src/main.tsx +0 -12
  254. package/dist/templates/google-adk/web/src/useAgentChat.ts +0 -122
  255. package/dist/templates/google-adk/web/src/vite-env.d.ts +0 -27
  256. package/dist/templates/google-adk/web/tsconfig.json +0 -20
  257. package/dist/templates/google-adk/web/vite.config.ts +0 -12
  258. package/dist/templates/openai-agents-sdk/web/.env.example +0 -17
  259. package/dist/templates/openai-agents-sdk/web/sandbox-proxy.ts +0 -239
  260. package/dist/templates/openai-agents-sdk/web/src/App.tsx +0 -272
  261. package/dist/templates/openai-agents-sdk/web/src/main.tsx +0 -12
  262. package/dist/templates/openai-agents-sdk/web/src/useAgentChat.ts +0 -122
  263. package/dist/templates/openai-agents-sdk/web/src/vite-env.d.ts +0 -27
  264. package/dist/templates/openai-agents-sdk/web/tsconfig.json +0 -20
  265. package/dist/templates/openai-agents-sdk/web/vite.config.ts +0 -12
  266. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/.env.example +0 -0
  267. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/.mcp.json +0 -0
  268. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/ggui/blueprints/.gitkeep +0 -0
  269. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/ggui/ggui.json +0 -0
  270. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/ggui/themes/.gitkeep +0 -0
  271. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/guuey.json +0 -0
  272. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/mcps/todo/Dockerfile +0 -0
  273. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/mcps/todo/package.json +0 -0
  274. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/mcps/todo/src/server.ts +0 -0
  275. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/mcps/todo/tsconfig.json +0 -0
  276. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/mcps/todo/tsup.config.ts +0 -0
  277. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/pnpm-workspace.yaml +0 -0
  278. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/prompts/system.md +0 -0
  279. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/scripts/dev.mjs +0 -0
  280. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/src/agent-config.ts +0 -0
  281. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/src/worker.ts +0 -0
  282. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/tsconfig.json +0 -0
  283. /package/dist/templates/{claude-agent-sdk → agentic-app/claude-agent-sdk}/tsup.config.ts +0 -0
  284. /package/dist/templates/{google-adk → agentic-app/google-adk}/.env.example +0 -0
  285. /package/dist/templates/{google-adk → agentic-app/google-adk}/.mcp.json +0 -0
  286. /package/dist/templates/{google-adk → agentic-app/google-adk}/README.md +0 -0
  287. /package/dist/templates/{google-adk → agentic-app/google-adk}/ggui/blueprints/.gitkeep +0 -0
  288. /package/dist/templates/{google-adk → agentic-app/google-adk}/ggui/ggui.json +0 -0
  289. /package/dist/templates/{google-adk → agentic-app/google-adk}/ggui/themes/.gitkeep +0 -0
  290. /package/dist/templates/{google-adk → agentic-app/google-adk}/guuey.json +0 -0
  291. /package/dist/templates/{google-adk → agentic-app/google-adk}/mcps/todo/Dockerfile +0 -0
  292. /package/dist/templates/{google-adk → agentic-app/google-adk}/mcps/todo/package.json +0 -0
  293. /package/dist/templates/{google-adk → agentic-app/google-adk}/mcps/todo/src/server.ts +0 -0
  294. /package/dist/templates/{google-adk → agentic-app/google-adk}/mcps/todo/tsconfig.json +0 -0
  295. /package/dist/templates/{google-adk → agentic-app/google-adk}/mcps/todo/tsup.config.ts +0 -0
  296. /package/dist/templates/{google-adk → agentic-app/google-adk}/pnpm-workspace.yaml +0 -0
  297. /package/dist/templates/{google-adk → agentic-app/google-adk}/prompts/system.md +0 -0
  298. /package/dist/templates/{google-adk → agentic-app/google-adk}/scripts/dev.mjs +0 -0
  299. /package/dist/templates/{google-adk → agentic-app/google-adk}/src/agent.ts +0 -0
  300. /package/dist/templates/{google-adk → agentic-app/google-adk}/tsconfig.json +0 -0
  301. /package/dist/templates/{google-adk → agentic-app/google-adk}/tsup.config.ts +0 -0
  302. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/.env.example +0 -0
  303. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/.mcp.json +0 -0
  304. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/ggui/blueprints/.gitkeep +0 -0
  305. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/ggui/ggui.json +0 -0
  306. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/ggui/themes/.gitkeep +0 -0
  307. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/guuey.json +0 -0
  308. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/mcps/todo/Dockerfile +0 -0
  309. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/mcps/todo/package.json +0 -0
  310. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/mcps/todo/src/server.ts +0 -0
  311. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/mcps/todo/tsconfig.json +0 -0
  312. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/mcps/todo/tsup.config.ts +0 -0
  313. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/pnpm-workspace.yaml +0 -0
  314. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/prompts/system.md +0 -0
  315. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/scripts/dev.mjs +0 -0
  316. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/src/agent-config.ts +0 -0
  317. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/src/worker.ts +0 -0
  318. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/tsconfig.json +0 -0
  319. /package/dist/templates/{openai-agents-sdk → agentic-app/openai-agents-sdk}/tsup.config.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agentic-app-template/web",
3
- "version": "0.0.0",
4
3
  "private": true,
4
+ "version": "0.0.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite --port 6890",
@@ -9,17 +9,20 @@
9
9
  "typecheck": "tsc --noEmit"
10
10
  },
11
11
  "dependencies": {
12
- "@mcp-ui/client": "^7.1.1",
13
- "@silverprotocol/core": "0.5.0",
12
+ "@guuey/chat": "0.11.0",
13
+ "oidc-client-ts": "^3.1.0",
14
+ "qrcode": "^1.5.4",
14
15
  "react": "^19.0.0",
15
- "react-dom": "^19.0.0"
16
+ "react-dom": "^19.0.0",
17
+ "react-router-dom": "^7.1.0"
16
18
  },
17
19
  "devDependencies": {
18
- "@types/node": "^22.0.0",
20
+ "@types/node": "^24.0.0",
21
+ "@types/qrcode": "^1.5.5",
19
22
  "@types/react": "^19.0.0",
20
23
  "@types/react-dom": "^19.0.0",
21
- "@vitejs/plugin-react": "^4.3.0",
22
- "typescript": "^5.8.0",
23
- "vite": "^6.0.0"
24
+ "@vitejs/plugin-react": "^4.3.4",
25
+ "typescript": "^5.7.2",
26
+ "vite": "^7.0.0"
24
27
  }
25
28
  }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * The configured `<GuueyChat>` for this app — distribution way #2, the
3
+ * embedded chat SDK. One place wires endpoint, history, identity and theme;
4
+ * every chat surface (the /chat page here, the fullscreen agent canvas in
5
+ * the agentic-app template) renders this.
6
+ *
7
+ * Identity rule: ONE mode per surface. When OIDC is configured AND a
8
+ * session exists, the bearer wins; otherwise the client-minted guest
9
+ * secret. Never both.
10
+ */
11
+ import { useEffect, useState, type CSSProperties } from "react";
12
+ import { GuueyChat } from "@guuey/chat/react";
13
+ import type { PlanViewSummary, ViewRefItem } from "@guuey/chat";
14
+ import { agentEndpointUrl, appConfig, historyBaseUrl } from "../config";
15
+ import { currentIdentityMode, ensureGuestSecret } from "../lib/identity";
16
+ import { getBearerToken, currentUser, oidcConfigured } from "../lib/oidc";
17
+
18
+ /**
19
+ * The chat-rail bridge (agentic-app shell): with `viewsBridge` set, the
20
+ * chat runs the kit's CHIPS presentation — generative views collapse to
21
+ * compact chips in the rail, the full renders belong to the host's main
22
+ * canvas (fed by `onViewsChange`), and chip clicks re-select
23
+ * (`onViewRef` → `promotedViewKey`, the browser-history mechanic).
24
+ */
25
+ export interface ViewsBridge {
26
+ promotedViewKey?: string | undefined;
27
+ onViewRef: (item: ViewRefItem) => void;
28
+ onViewsChange: (views: PlanViewSummary[]) => void;
29
+ }
30
+
31
+ // Module scope on purpose: props want STABLE identities. An inline
32
+ // `policy={{ … }}` literal (or per-render arrow getters) re-mints every
33
+ // render; the kit stabilizes structurally since 0.11.0, but the template
34
+ // models the correct shape — one identity for the app's whole life.
35
+ const RAIL_POLICY = { view: { timeoutMs: 8000, presentation: "chips" as const } };
36
+
37
+ export function AgentChat({
38
+ className,
39
+ style,
40
+ viewsBridge,
41
+ }: {
42
+ className?: string;
43
+ style?: CSSProperties;
44
+ viewsBridge?: ViewsBridge;
45
+ }) {
46
+ // The user's CHOSEN mode wins: an explicit "Continue as guest" must never
47
+ // be shadowed by a cached OIDC session. Only when no choice is recorded
48
+ // does a live session imply oidc.
49
+ const chosen = currentIdentityMode();
50
+ const [identity, setIdentity] = useState<"resolving" | "guest" | "oidc">(
51
+ chosen === "guest" || !oidcConfigured() ? "guest" : chosen === "oidc" ? "oidc" : "resolving",
52
+ );
53
+
54
+ useEffect(() => {
55
+ if (identity !== "resolving") return;
56
+ let cancelled = false;
57
+ void currentUser().then((user) => {
58
+ if (!cancelled) setIdentity(user ? "oidc" : "guest");
59
+ });
60
+ return () => {
61
+ cancelled = true;
62
+ };
63
+ }, [identity]);
64
+
65
+ if (identity === "resolving") return null;
66
+
67
+ const shared = {
68
+ endpointUrl: agentEndpointUrl(),
69
+ appId: appConfig.link?.appId ?? "local",
70
+ apiBaseUrl: historyBaseUrl(),
71
+ mode: appConfig.theme.mode,
72
+ className,
73
+ style,
74
+ ...(viewsBridge !== undefined
75
+ ? {
76
+ policy: RAIL_POLICY,
77
+ promotedViewKey: viewsBridge.promotedViewKey,
78
+ onViewRef: viewsBridge.onViewRef,
79
+ onViewsChange: viewsBridge.onViewsChange,
80
+ }
81
+ : {}),
82
+ };
83
+
84
+ // The lib functions ARE the stable getters — no wrapping arrows (a fresh
85
+ // closure per render is the identity churn RAIL_POLICY exists to avoid).
86
+ return identity === "oidc" ? (
87
+ <GuueyChat {...shared} getAccessToken={getBearerToken} />
88
+ ) : (
89
+ <GuueyChat {...shared} getGuestSecret={ensureGuestSecret} />
90
+ );
91
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Dev-time gate: until `pnpm bootstrap` has run, every page renders this
3
+ * setup screen instead of a half-configured app. Production builds are
4
+ * gated harder — vite.config.ts fails the build outright.
5
+ */
6
+ import type { ReactNode } from "react";
7
+ import { appConfig } from "../config";
8
+
9
+ export function BootstrapGate({ children }: { children: ReactNode }) {
10
+ if (appConfig.bootstrapped) return <>{children}</>;
11
+ return (
12
+ <main className="gate">
13
+ <div className="gate-card">
14
+ <h1>Run bootstrap first</h1>
15
+ <p>
16
+ This project has not been configured yet. From the project root:
17
+ </p>
18
+ <pre>
19
+ <code>pnpm bootstrap</code>
20
+ </pre>
21
+ <p>
22
+ That writes <code>guuey.app.json</code> (brand, theme, copy) and
23
+ regenerates <code>AGENTS.md</code>. Then start the local stack with{" "}
24
+ <code>pnpm dev</code>. When you are ready to bind a deployed guuey
25
+ app: <code>pnpm bootstrap -- --link</code>.
26
+ </p>
27
+ </div>
28
+ </main>
29
+ );
30
+ }
@@ -0,0 +1,25 @@
1
+ /** A QR code for a URL, with the plain link beneath — mobile hand-off. */
2
+ import { useEffect, useRef, useState } from "react";
3
+ import QRCode from "qrcode";
4
+
5
+ export function QrLink({ url, size = 200 }: { url: string; size?: number }) {
6
+ const canvasRef = useRef<HTMLCanvasElement | null>(null);
7
+ const [error, setError] = useState<string | null>(null);
8
+
9
+ useEffect(() => {
10
+ if (!canvasRef.current) return;
11
+ QRCode.toCanvas(canvasRef.current, url, { width: size, margin: 1 }).catch((err: unknown) => {
12
+ setError(err instanceof Error ? err.message : String(err));
13
+ });
14
+ }, [url, size]);
15
+
16
+ return (
17
+ <span className="qr-link">
18
+ <canvas ref={canvasRef} className="qr" />
19
+ <a href={url} target="_blank" rel="noreferrer">
20
+ {url}
21
+ </a>
22
+ {error ? <span className="error">QR render failed: {error}</span> : null}
23
+ </span>
24
+ );
25
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Base-template chrome: brand header + nav + auth affordance. Pages render
3
+ * inside via the router outlet.
4
+ */
5
+ import { Link, NavLink, Outlet, useLocation, useNavigate } from "react-router-dom";
6
+ import { appConfig } from "../config";
7
+ import { CHAT_PATH, HOME_PATH } from "../routes";
8
+ import { currentIdentityMode, logOut } from "../lib/identity";
9
+ import { oidcConfigured, signOutOidc } from "../lib/oidc";
10
+
11
+ export function Shell() {
12
+ const navigate = useNavigate();
13
+ // Subscribing to the location re-renders this chrome on every navigation,
14
+ // so the render-time read below stays fresh after login/logout. (A
15
+ // `storage` listener would NOT work — that event only fires in OTHER
16
+ // tabs, never the one that wrote the change.)
17
+ useLocation();
18
+ const mode = currentIdentityMode();
19
+
20
+ async function handleLogOut() {
21
+ if (mode === "oidc" && oidcConfigured()) await signOutOidc();
22
+ logOut();
23
+ navigate("/");
24
+ }
25
+
26
+ return (
27
+ <div className="shell">
28
+ <header className="topbar">
29
+ <Link to="/" className="brand">
30
+ <span className="brand-mark">{appConfig.brand.logoText}</span>
31
+ <span>{appConfig.brand.name}</span>
32
+ </Link>
33
+ <nav>
34
+ <NavLink to={CHAT_PATH}>Chat</NavLink>
35
+ <NavLink to={HOME_PATH}>Home</NavLink>
36
+ {mode === null ? (
37
+ <NavLink to="/login" className="btn btn-accent">
38
+ Sign in
39
+ </NavLink>
40
+ ) : (
41
+ <button type="button" className="btn" onClick={() => void handleLogOut()}>
42
+ Log out{mode === "guest" ? " (guest)" : ""}
43
+ </button>
44
+ )}
45
+ </nav>
46
+ </header>
47
+ <Outlet />
48
+ </div>
49
+ );
50
+ }
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Typed access to `guuey.app.json` — the ONE file `pnpm bootstrap` writes.
3
+ *
4
+ * The JSON is validated structurally here (not just cast) so a hand-edited
5
+ * config fails with a named path instead of an undefined-deep-in-React
6
+ * crash. The schema is documented in `../guuey.app.schema.json`.
7
+ */
8
+ import rawConfig from "../../guuey.app.json";
9
+
10
+ export interface OidcConfig {
11
+ /** OIDC issuer URL (https). Discovery via /.well-known/openid-configuration. */
12
+ issuer: string;
13
+ clientId: string;
14
+ }
15
+
16
+ export interface AppLink {
17
+ appId: string;
18
+ env: "dev" | "staging" | "release";
19
+ /** Public API base ending in /v1 — history + persisted-card reads. */
20
+ apiBaseUrl: string;
21
+ /** The agent pod's public origin — live chat + health probe. */
22
+ endpointUrl: string;
23
+ /** Widget host origin serving /v1.js for this environment. */
24
+ widgetOrigin: string;
25
+ /** Portal web origin (the "talk on mobile" target). */
26
+ portalUrl: string;
27
+ slug: string | null;
28
+ /** The agent's own hosted page (https://<slug>.agents...), when slugged. */
29
+ pageUrl: string | null;
30
+ }
31
+
32
+ export interface AppConfig {
33
+ schema: number;
34
+ bootstrapped: boolean;
35
+ brand: { name: string; tagline: string; logoText: string };
36
+ theme: { accent: string; mode: "light" | "dark" };
37
+ copy: {
38
+ landing: { headline: string; sub: string };
39
+ login: { guestHint: string };
40
+ };
41
+ auth: { oidc: OidcConfig | null };
42
+ link: AppLink | null;
43
+ demoMode: boolean;
44
+ }
45
+
46
+ class ConfigError extends Error {
47
+ constructor(path: string, expected: string) {
48
+ super(`guuey.app.json: ${path} — expected ${expected}. Re-run \`pnpm bootstrap\` or fix the file by hand (schema: guuey.app.schema.json).`);
49
+ }
50
+ }
51
+
52
+ function str(v: unknown, path: string): string {
53
+ if (typeof v !== "string" || v.length === 0) throw new ConfigError(path, "a non-empty string");
54
+ return v;
55
+ }
56
+
57
+ function bool(v: unknown, path: string): boolean {
58
+ if (typeof v !== "boolean") throw new ConfigError(path, "a boolean");
59
+ return v;
60
+ }
61
+
62
+ function obj(v: unknown, path: string): Record<string, unknown> {
63
+ if (typeof v !== "object" || v === null || Array.isArray(v)) throw new ConfigError(path, "an object");
64
+ return v as Record<string, unknown>;
65
+ }
66
+
67
+ function validate(raw: unknown): AppConfig {
68
+ const root = obj(raw, "$");
69
+ if (root.schema !== 1) throw new ConfigError("schema", "the literal 1");
70
+
71
+ const brand = obj(root.brand, "brand");
72
+ const theme = obj(root.theme, "theme");
73
+ const mode = theme.mode;
74
+ if (mode !== "light" && mode !== "dark") throw new ConfigError("theme.mode", '"light" | "dark"');
75
+ const copy = obj(root.copy, "copy");
76
+ const landing = obj(copy.landing, "copy.landing");
77
+ const login = obj(copy.login, "copy.login");
78
+ const auth = obj(root.auth, "auth");
79
+
80
+ let oidc: OidcConfig | null = null;
81
+ if (auth.oidc !== null && auth.oidc !== undefined) {
82
+ const o = obj(auth.oidc, "auth.oidc");
83
+ oidc = { issuer: str(o.issuer, "auth.oidc.issuer"), clientId: str(o.clientId, "auth.oidc.clientId") };
84
+ }
85
+
86
+ let link: AppLink | null = null;
87
+ if (root.link !== null && root.link !== undefined) {
88
+ const l = obj(root.link, "link");
89
+ const env = l.env;
90
+ if (env !== "dev" && env !== "staging" && env !== "release") {
91
+ throw new ConfigError("link.env", '"dev" | "staging" | "release"');
92
+ }
93
+ link = {
94
+ appId: str(l.appId, "link.appId"),
95
+ env,
96
+ apiBaseUrl: str(l.apiBaseUrl, "link.apiBaseUrl"),
97
+ // Normalize to the ORIGIN whatever shape was stored: the platform's
98
+ // deployment records carry the full `…/agent/invoke` URL, while this
99
+ // contract (and the probe) wants the base. The chat kit accepts
100
+ // either, so normalizing here makes both consumers correct.
101
+ endpointUrl: str(l.endpointUrl, "link.endpointUrl").replace(/\/agent\/invoke\/?$/, ""),
102
+ widgetOrigin: str(l.widgetOrigin, "link.widgetOrigin"),
103
+ portalUrl: str(l.portalUrl, "link.portalUrl"),
104
+ slug: typeof l.slug === "string" ? l.slug : null,
105
+ pageUrl: typeof l.pageUrl === "string" ? l.pageUrl : null,
106
+ };
107
+ }
108
+
109
+ return {
110
+ schema: 1,
111
+ bootstrapped: bool(root.bootstrapped, "bootstrapped"),
112
+ brand: {
113
+ name: str(brand.name, "brand.name"),
114
+ tagline: str(brand.tagline, "brand.tagline"),
115
+ logoText: str(brand.logoText, "brand.logoText"),
116
+ },
117
+ theme: { accent: str(theme.accent, "theme.accent"), mode },
118
+ copy: {
119
+ landing: { headline: str(landing.headline, "copy.landing.headline"), sub: str(landing.sub, "copy.landing.sub") },
120
+ login: { guestHint: str(login.guestHint, "copy.login.guestHint") },
121
+ },
122
+ auth: { oidc },
123
+ link,
124
+ demoMode: bool(root.demoMode ?? false, "demoMode"),
125
+ };
126
+ }
127
+
128
+ export const appConfig: AppConfig = validate(rawConfig);
129
+
130
+ /** The local `guuey dev --serve` router (scripts/dev.mjs boots it). */
131
+ export const DEV_AGENT_URL = "http://localhost:6790";
132
+
133
+ export const isLinked: boolean = appConfig.link !== null;
134
+
135
+ /** Live-chat base: the bound pod when linked, the local dev router otherwise. */
136
+ export function agentEndpointUrl(): string {
137
+ return appConfig.link?.endpointUrl ?? DEV_AGENT_URL;
138
+ }
139
+
140
+ /**
141
+ * History/read-plane base. When linked this is the public API (`…/v1`);
142
+ * in local dev, `guuey dev --serve` exposes the same read-plane route
143
+ * shape (`/threads/:id/messages`) on its own origin, so history and
144
+ * rehydration work locally too.
145
+ */
146
+ export function historyBaseUrl(): string {
147
+ return appConfig.link?.apiBaseUrl ?? DEV_AGENT_URL;
148
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * End-user identity for this app's chat surfaces.
3
+ *
4
+ * ONE mode per surface — never both resolvers at once (a bearer + a guest
5
+ * secret on the same request is a silent-downgrade hazard the platform
6
+ * refuses to guess about):
7
+ *
8
+ * - **Guest** (always available): a client-minted 64-hex secret stored at
9
+ * `localStorage["guuey:guest-secret:<appId>"]` and sent as the
10
+ * `x-guuey-guest` header. Per-browser and persistent, so the agent
11
+ * remembers the visitor across reloads. This is the same mechanic the
12
+ * guuey widget uses. "Log out" deletes the secret — a fresh one next
13
+ * visit is a fresh person as far as the agent is concerned.
14
+ * - **Signed in** (when `auth.oidc` is configured in guuey.app.json): an
15
+ * OIDC ID token from your IdP (see ./oidc.ts), sent as a Bearer. The
16
+ * bound guuey app must be in BYO auth mode for the same issuer
17
+ * (`guuey apps update <appId> --auth-mode byo --issuer-url … --audience <clientId>`).
18
+ */
19
+ import { appConfig } from "../config";
20
+
21
+ export type IdentityMode = "guest" | "oidc";
22
+
23
+ const scope = appConfig.link?.appId ?? "local";
24
+ const GUEST_KEY = `guuey:guest-secret:${scope}`;
25
+ const MODE_KEY = `guuey:identity-mode:${scope}`;
26
+
27
+ function mintSecret(): string {
28
+ const bytes = new Uint8Array(32);
29
+ crypto.getRandomValues(bytes);
30
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
31
+ }
32
+
33
+ /** The stored guest secret, minting one on first use. */
34
+ export function ensureGuestSecret(): string {
35
+ const existing = localStorage.getItem(GUEST_KEY);
36
+ if (existing && /^[0-9a-f]{64}$/.test(existing)) return existing;
37
+ const fresh = mintSecret();
38
+ localStorage.setItem(GUEST_KEY, fresh);
39
+ return fresh;
40
+ }
41
+
42
+ export function getStoredGuestSecret(): string | null {
43
+ const v = localStorage.getItem(GUEST_KEY);
44
+ return v && /^[0-9a-f]{64}$/.test(v) ? v : null;
45
+ }
46
+
47
+ export function currentIdentityMode(): IdentityMode | null {
48
+ const v = localStorage.getItem(MODE_KEY);
49
+ return v === "guest" || v === "oidc" ? v : null;
50
+ }
51
+
52
+ export function setIdentityMode(mode: IdentityMode | null): void {
53
+ if (mode === null) localStorage.removeItem(MODE_KEY);
54
+ else localStorage.setItem(MODE_KEY, mode);
55
+ }
56
+
57
+ /** "Continue as guest": ensure a secret exists and select guest mode. */
58
+ export function continueAsGuest(): void {
59
+ ensureGuestSecret();
60
+ setIdentityMode("guest");
61
+ }
62
+
63
+ /** Log out of whichever mode is active. Guest logout forgets the secret. */
64
+ export function logOut(): void {
65
+ if (currentIdentityMode() === "guest") localStorage.removeItem(GUEST_KEY);
66
+ setIdentityMode(null);
67
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * BYO-OIDC sign-in seam (only active when `auth.oidc` is configured in
3
+ * guuey.app.json).
4
+ *
5
+ * Standard authorization-code + PKCE via oidc-client-ts. The ID TOKEN is
6
+ * what the guuey pod verifies in BYO auth mode (audience = your client id),
7
+ * so `getAccessToken` below returns `user.id_token` — forwarding the OAuth
8
+ * access token instead is the classic mistake (wrong audience → 401).
9
+ *
10
+ * Works with any spec-compliant IdP that can host a "Sign in with Google"
11
+ * (Auth0, AWS Cognito, Okta, Keycloak, …). Configure the IdP's allowed
12
+ * callback URL to `<your site origin>/login`.
13
+ */
14
+ import { UserManager, WebStorageStateStore, type User } from "oidc-client-ts";
15
+ import { appConfig, type OidcConfig } from "../config";
16
+
17
+ let manager: UserManager | null = null;
18
+
19
+ export function oidcConfigured(): boolean {
20
+ return appConfig.auth.oidc !== null;
21
+ }
22
+
23
+ function requireManager(oidc: OidcConfig): UserManager {
24
+ if (manager) return manager;
25
+ manager = new UserManager({
26
+ authority: oidc.issuer,
27
+ client_id: oidc.clientId,
28
+ redirect_uri: `${window.location.origin}/login`,
29
+ response_type: "code",
30
+ scope: "openid profile email",
31
+ userStore: new WebStorageStateStore({ store: window.localStorage }),
32
+ });
33
+ return manager;
34
+ }
35
+
36
+ /** Kick off the redirect sign-in flow. */
37
+ export async function signIn(): Promise<void> {
38
+ const oidc = appConfig.auth.oidc;
39
+ if (!oidc) throw new Error("auth.oidc is not configured in guuey.app.json");
40
+ await requireManager(oidc).signinRedirect();
41
+ }
42
+
43
+ /** Complete the flow when the IdP redirected back to /login?code=… */
44
+ export async function completeSignIn(): Promise<User> {
45
+ const oidc = appConfig.auth.oidc;
46
+ if (!oidc) throw new Error("auth.oidc is not configured in guuey.app.json");
47
+ return requireManager(oidc).signinCallback() as Promise<User>;
48
+ }
49
+
50
+ export function isSigninCallback(): boolean {
51
+ const q = new URLSearchParams(window.location.search);
52
+ return q.has("code") && q.has("state");
53
+ }
54
+
55
+ export async function currentUser(): Promise<User | null> {
56
+ const oidc = appConfig.auth.oidc;
57
+ if (!oidc) return null;
58
+ const user = await requireManager(oidc).getUser();
59
+ return user && !user.expired ? user : null;
60
+ }
61
+
62
+ /**
63
+ * `getAccessToken` for `<GuueyChat>`: the current stored ID token, or null
64
+ * when signed out / expired (the chat surfaces it as needs-sign-in; they
65
+ * never silently fall back to guest — one identity mode per surface).
66
+ * There is NO silent renew here — when the session expires the user signs
67
+ * in again via /login. Wiring `automaticSilentRenew` (plus a silent
68
+ * redirect page) is the documented upgrade if your IdP supports it.
69
+ */
70
+ export async function getBearerToken(): Promise<string | null> {
71
+ const user = await currentUser();
72
+ return user?.id_token ?? null;
73
+ }
74
+
75
+ export async function signOutOidc(): Promise<void> {
76
+ const oidc = appConfig.auth.oidc;
77
+ if (!oidc || !manager) return;
78
+ await manager.removeUser();
79
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Live-ness probe for the Home page.
3
+ *
4
+ * Probes the agent's invoke route with a CORS preflight-shaped OPTIONS —
5
+ * the ONE route both servers answer cross-origin: the pod's CORS covers
6
+ * `/agent/invoke` for the app's allowed domains, and `guuey dev --serve`
7
+ * answers OPTIONS 204 on it too. (A bare `/healthz` GET carries no CORS
8
+ * headers on either server, so it is useless from a browser.) The
9
+ * platform's richer status API is credentialed and guuey-origin-CORS'd, so
10
+ * the CLI is the tool for detail: `pnpm status` runs `guuey apps get` +
11
+ * `guuey agent status`.
12
+ */
13
+ import { agentEndpointUrl, isLinked } from "../config";
14
+
15
+ export type AgentProbe =
16
+ | { state: "checking" }
17
+ | { state: "reachable" }
18
+ | {
19
+ /**
20
+ * Calm, honest failure: a fresh clone before `bootstrap --link` (or a
21
+ * dev session without `pnpm dev` running) is ALWAYS in this state —
22
+ * it is a setup stage, not an error.
23
+ */
24
+ state: "unreachable";
25
+ hint: string;
26
+ };
27
+
28
+ export async function probeAgent(): Promise<AgentProbe> {
29
+ const base = agentEndpointUrl().replace(/\/+$/, "");
30
+ try {
31
+ const res = await fetch(`${base}/agent/invoke`, {
32
+ method: "OPTIONS",
33
+ signal: AbortSignal.timeout(5000),
34
+ });
35
+ if (res.ok) return { state: "reachable" };
36
+ return { state: "unreachable", hint: `agent answered ${res.status}` };
37
+ } catch {
38
+ return {
39
+ state: "unreachable",
40
+ hint: isLinked
41
+ ? "agent unreachable from this origin — check the app's Allowed Domains include this site, and that a deployment is live (pnpm status)"
42
+ : "local dev router not running — start it with `pnpm dev` (or bind a deployed app with `pnpm bootstrap -- --link`)",
43
+ };
44
+ }
45
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Host-page loader for the guuey widget (distribution way #1).
3
+ *
4
+ * The queue shim + single-init + idempotent script tag pattern — safe under
5
+ * React strict-mode double effects and route remounts. The widget only
6
+ * works against a DEPLOYED app (it loads from the environment's widget
7
+ * origin and frames the app's hosted chat), so callers gate on
8
+ * `appConfig.link`.
9
+ */
10
+ import { appConfig } from "../config";
11
+
12
+ interface GuueyGlobal {
13
+ (...args: unknown[]): void;
14
+ q?: unknown[][];
15
+ loaded?: boolean;
16
+ }
17
+
18
+ declare global {
19
+ interface Window {
20
+ guuey?: GuueyGlobal;
21
+ }
22
+ }
23
+
24
+ const SCRIPT_ID = "guuey-widget-v1";
25
+ let initDispatched = false;
26
+
27
+ function ensureGlobal(): GuueyGlobal {
28
+ if (!window.guuey) {
29
+ const shim: GuueyGlobal = function (...args: unknown[]) {
30
+ (shim.q = shim.q ?? []).push(args);
31
+ };
32
+ window.guuey = shim;
33
+ }
34
+ return window.guuey;
35
+ }
36
+
37
+ export type WidgetOutcome = "live" | "offline";
38
+
39
+ /**
40
+ * Mount the widget launcher once: dispatches `guuey("init", …)` on first
41
+ * call and injects `<widget origin>/v1.js` if it is not already on the
42
+ * page. Subsequent calls are no-ops. Returns false when the app is not
43
+ * linked yet (nothing to embed).
44
+ */
45
+ export function mountWidget(onOutcome?: (o: WidgetOutcome) => void): boolean {
46
+ const link = appConfig.link;
47
+ if (!link) return false;
48
+
49
+ const guuey = ensureGlobal();
50
+ if (!initDispatched) {
51
+ initDispatched = true;
52
+ guuey("init", {
53
+ app: link.appId,
54
+ launcher: `Ask ${appConfig.brand.name}`,
55
+ color: appConfig.theme.accent,
56
+ theme: appConfig.theme.mode,
57
+ });
58
+ }
59
+
60
+ if (!document.getElementById(SCRIPT_ID)) {
61
+ const script = document.createElement("script");
62
+ script.id = SCRIPT_ID;
63
+ script.src = `${link.widgetOrigin}/v1.js`;
64
+ script.async = true;
65
+ script.addEventListener("load", () => onOutcome?.("live"));
66
+ script.addEventListener("error", () => onOutcome?.("offline"));
67
+ document.head.appendChild(script);
68
+ } else {
69
+ onOutcome?.("live");
70
+ }
71
+ return true;
72
+ }
73
+
74
+ /**
75
+ * A value embedded inside an inline <script> on the customer's page: JSON
76
+ * string escaping, plus a `<` rewrite so a pathological brand name cannot
77
+ * smuggle `</script>` and terminate the element (the same rule the widget's
78
+ * own snippet generator applies).
79
+ */
80
+ function jsString(value: string): string {
81
+ return JSON.stringify(value).replaceAll("<", "\\u003c");
82
+ }
83
+
84
+ /** The copy-paste embed snippet with this app's real values, for the Home guide. */
85
+ export function widgetSnippet(): string | null {
86
+ const link = appConfig.link;
87
+ if (!link) return null;
88
+ return [
89
+ "<!-- guuey widget. Add this site to the app's allowed domains or the embed is refused. -->",
90
+ "<script>",
91
+ " window.guuey = window.guuey || function(){(guuey.q=guuey.q||[]).push(arguments)};",
92
+ ` guuey("init", { app: ${jsString(link.appId)}, launcher: ${jsString(`Ask ${appConfig.brand.name}`)} });`,
93
+ "</script>",
94
+ `<script src="${link.widgetOrigin}/v1.js" async></script>`,
95
+ ].join("\n");
96
+ }