luca 2.0.0 → 3.0.2

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 (532) hide show
  1. package/.github/workflows/release.yaml +170 -0
  2. package/AGENTS.md +99 -0
  3. package/CLAUDE.md +123 -0
  4. package/CNAME +1 -0
  5. package/README.md +275 -9
  6. package/RUNME.md +56 -0
  7. package/assistants/codingAssistant/ABOUT.md +5 -0
  8. package/assistants/codingAssistant/CORE.md +33 -0
  9. package/assistants/codingAssistant/hooks.ts +21 -0
  10. package/assistants/codingAssistant/tools.ts +12 -0
  11. package/assistants/inkbot/ABOUT.md +16 -0
  12. package/assistants/inkbot/CORE.md +330 -0
  13. package/assistants/inkbot/hooks.ts +6 -0
  14. package/assistants/inkbot/tools.ts +53 -0
  15. package/assistants/researcher/ABOUT.md +5 -0
  16. package/assistants/researcher/CORE.md +46 -0
  17. package/assistants/researcher/hooks.ts +16 -0
  18. package/assistants/researcher/tools.ts +237 -0
  19. package/bun.lock +2667 -0
  20. package/bunfig.toml +3 -0
  21. package/commands/audit-docs.ts +740 -0
  22. package/commands/build-bootstrap.ts +117 -0
  23. package/commands/build-python-bridge.ts +42 -0
  24. package/commands/build-scaffolds.ts +175 -0
  25. package/commands/bundle-consumer-project.ts +521 -0
  26. package/commands/generate-api-docs.ts +114 -0
  27. package/commands/inkbot.ts +874 -0
  28. package/commands/release.ts +80 -0
  29. package/commands/try-all-challenges.ts +543 -0
  30. package/commands/try-challenge.ts +100 -0
  31. package/dist/agi/container.server.d.ts +63 -0
  32. package/dist/agi/container.server.d.ts.map +1 -0
  33. package/dist/agi/endpoints/ask.d.ts +20 -0
  34. package/dist/agi/endpoints/ask.d.ts.map +1 -0
  35. package/dist/agi/endpoints/conversations/[id].d.ts +27 -0
  36. package/dist/agi/endpoints/conversations/[id].d.ts.map +1 -0
  37. package/dist/agi/endpoints/conversations.d.ts +18 -0
  38. package/dist/agi/endpoints/conversations.d.ts.map +1 -0
  39. package/dist/agi/endpoints/experts.d.ts +8 -0
  40. package/dist/agi/endpoints/experts.d.ts.map +1 -0
  41. package/dist/agi/feature.d.ts +9 -0
  42. package/dist/agi/feature.d.ts.map +1 -0
  43. package/dist/agi/features/assistant.d.ts +509 -0
  44. package/dist/agi/features/assistant.d.ts.map +1 -0
  45. package/dist/agi/features/assistants-manager.d.ts +236 -0
  46. package/dist/agi/features/assistants-manager.d.ts.map +1 -0
  47. package/dist/agi/features/autonomous-assistant.d.ts +281 -0
  48. package/dist/agi/features/autonomous-assistant.d.ts.map +1 -0
  49. package/dist/agi/features/browser-use.d.ts +479 -0
  50. package/dist/agi/features/browser-use.d.ts.map +1 -0
  51. package/dist/agi/features/claude-code.d.ts +824 -0
  52. package/dist/agi/features/claude-code.d.ts.map +1 -0
  53. package/dist/agi/features/conversation-history.d.ts +245 -0
  54. package/dist/agi/features/conversation-history.d.ts.map +1 -0
  55. package/dist/agi/features/conversation.d.ts +464 -0
  56. package/dist/agi/features/conversation.d.ts.map +1 -0
  57. package/dist/agi/features/docs-reader.d.ts +72 -0
  58. package/dist/agi/features/docs-reader.d.ts.map +1 -0
  59. package/dist/agi/features/file-tools.d.ts +110 -0
  60. package/dist/agi/features/file-tools.d.ts.map +1 -0
  61. package/dist/agi/features/luca-coder.d.ts +323 -0
  62. package/dist/agi/features/luca-coder.d.ts.map +1 -0
  63. package/dist/agi/features/openai-codex.d.ts +381 -0
  64. package/dist/agi/features/openai-codex.d.ts.map +1 -0
  65. package/dist/agi/features/openapi.d.ts +200 -0
  66. package/dist/agi/features/openapi.d.ts.map +1 -0
  67. package/dist/agi/features/skills-library.d.ts +167 -0
  68. package/dist/agi/features/skills-library.d.ts.map +1 -0
  69. package/dist/agi/index.d.ts +5 -0
  70. package/dist/agi/index.d.ts.map +1 -0
  71. package/dist/agi/lib/interceptor-chain.d.ts +44 -0
  72. package/dist/agi/lib/interceptor-chain.d.ts.map +1 -0
  73. package/dist/agi/lib/token-counter.d.ts +13 -0
  74. package/dist/agi/lib/token-counter.d.ts.map +1 -0
  75. package/dist/bootstrap/generated.d.ts +5 -0
  76. package/dist/bootstrap/generated.d.ts.map +1 -0
  77. package/dist/browser.d.ts +12 -0
  78. package/dist/browser.d.ts.map +1 -0
  79. package/dist/bus.d.ts +29 -0
  80. package/dist/bus.d.ts.map +1 -0
  81. package/dist/cli/build-info.d.ts +4 -0
  82. package/dist/cli/build-info.d.ts.map +1 -0
  83. package/dist/cli/cli.d.ts +3 -12
  84. package/dist/cli/cli.d.ts.map +1 -0
  85. package/dist/client.d.ts +60 -0
  86. package/dist/client.d.ts.map +1 -0
  87. package/dist/clients/civitai/index.d.ts +472 -0
  88. package/dist/clients/civitai/index.d.ts.map +1 -0
  89. package/dist/clients/client-template.d.ts +30 -0
  90. package/dist/clients/client-template.d.ts.map +1 -0
  91. package/dist/clients/comfyui/index.d.ts +281 -0
  92. package/dist/clients/comfyui/index.d.ts.map +1 -0
  93. package/dist/clients/elevenlabs/index.d.ts +197 -0
  94. package/dist/clients/elevenlabs/index.d.ts.map +1 -0
  95. package/dist/clients/graph.d.ts +64 -0
  96. package/dist/clients/graph.d.ts.map +1 -0
  97. package/dist/clients/openai/index.d.ts +247 -0
  98. package/dist/clients/openai/index.d.ts.map +1 -0
  99. package/dist/clients/rest.d.ts +92 -0
  100. package/dist/clients/rest.d.ts.map +1 -0
  101. package/dist/clients/supabase/index.d.ts +176 -0
  102. package/dist/clients/supabase/index.d.ts.map +1 -0
  103. package/dist/clients/websocket.d.ts +127 -0
  104. package/dist/clients/websocket.d.ts.map +1 -0
  105. package/dist/command.d.ts +163 -0
  106. package/dist/command.d.ts.map +1 -0
  107. package/dist/commands/bootstrap.d.ts +20 -0
  108. package/dist/commands/bootstrap.d.ts.map +1 -0
  109. package/dist/commands/chat.d.ts +37 -0
  110. package/dist/commands/chat.d.ts.map +1 -0
  111. package/dist/commands/code.d.ts +28 -0
  112. package/dist/commands/code.d.ts.map +1 -0
  113. package/dist/commands/console.d.ts +22 -0
  114. package/dist/commands/console.d.ts.map +1 -0
  115. package/dist/commands/describe.d.ts +50 -0
  116. package/dist/commands/describe.d.ts.map +1 -0
  117. package/dist/commands/eval.d.ts +23 -0
  118. package/dist/commands/eval.d.ts.map +1 -0
  119. package/dist/commands/help.d.ts +25 -0
  120. package/dist/commands/help.d.ts.map +1 -0
  121. package/dist/commands/index.d.ts +18 -0
  122. package/dist/commands/index.d.ts.map +1 -0
  123. package/dist/commands/introspect.d.ts +24 -0
  124. package/dist/commands/introspect.d.ts.map +1 -0
  125. package/dist/commands/mcp.d.ts +35 -0
  126. package/dist/commands/mcp.d.ts.map +1 -0
  127. package/dist/commands/prompt.d.ts +38 -0
  128. package/dist/commands/prompt.d.ts.map +1 -0
  129. package/dist/commands/run.d.ts +24 -0
  130. package/dist/commands/run.d.ts.map +1 -0
  131. package/dist/commands/sandbox-mcp.d.ts +34 -0
  132. package/dist/commands/sandbox-mcp.d.ts.map +1 -0
  133. package/dist/commands/save-api-docs.d.ts +21 -0
  134. package/dist/commands/save-api-docs.d.ts.map +1 -0
  135. package/dist/commands/scaffold.d.ts +24 -0
  136. package/dist/commands/scaffold.d.ts.map +1 -0
  137. package/dist/commands/select.d.ts +22 -0
  138. package/dist/commands/select.d.ts.map +1 -0
  139. package/dist/commands/serve.d.ts +29 -0
  140. package/dist/commands/serve.d.ts.map +1 -0
  141. package/dist/container-describer.d.ts +144 -0
  142. package/dist/container-describer.d.ts.map +1 -0
  143. package/dist/container.d.ts +451 -0
  144. package/dist/container.d.ts.map +1 -0
  145. package/dist/endpoint.d.ts +113 -0
  146. package/dist/endpoint.d.ts.map +1 -0
  147. package/dist/feature.d.ts +47 -0
  148. package/dist/feature.d.ts.map +1 -0
  149. package/dist/graft.d.ts +29 -0
  150. package/dist/graft.d.ts.map +1 -0
  151. package/dist/hash-object.d.ts +8 -0
  152. package/dist/hash-object.d.ts.map +1 -0
  153. package/dist/helper.d.ts +209 -0
  154. package/dist/helper.d.ts.map +1 -0
  155. package/dist/introspection/generated.node.d.ts +44623 -0
  156. package/dist/introspection/generated.node.d.ts.map +1 -0
  157. package/dist/introspection/generated.web.d.ts +1412 -0
  158. package/dist/introspection/generated.web.d.ts.map +1 -0
  159. package/dist/introspection/index.d.ts +156 -0
  160. package/dist/introspection/index.d.ts.map +1 -0
  161. package/dist/introspection/scan.d.ts +147 -0
  162. package/dist/introspection/scan.d.ts.map +1 -0
  163. package/dist/node/container.d.ts +256 -0
  164. package/dist/node/container.d.ts.map +1 -0
  165. package/dist/node/feature.d.ts +9 -0
  166. package/dist/node/feature.d.ts.map +1 -0
  167. package/dist/node/features/container-link.d.ts +213 -0
  168. package/dist/node/features/container-link.d.ts.map +1 -0
  169. package/dist/node/features/content-db.d.ts +354 -0
  170. package/dist/node/features/content-db.d.ts.map +1 -0
  171. package/dist/node/features/disk-cache.d.ts +236 -0
  172. package/dist/node/features/disk-cache.d.ts.map +1 -0
  173. package/dist/node/features/dns.d.ts +511 -0
  174. package/dist/node/features/dns.d.ts.map +1 -0
  175. package/dist/node/features/docker.d.ts +485 -0
  176. package/dist/node/features/docker.d.ts.map +1 -0
  177. package/dist/node/features/downloader.d.ts +73 -0
  178. package/dist/node/features/downloader.d.ts.map +1 -0
  179. package/dist/node/features/figlet-fonts.d.ts +4 -0
  180. package/dist/node/features/figlet-fonts.d.ts.map +1 -0
  181. package/dist/node/features/file-manager.d.ts +177 -0
  182. package/dist/node/features/file-manager.d.ts.map +1 -0
  183. package/dist/node/features/fs.d.ts +635 -0
  184. package/dist/node/features/fs.d.ts.map +1 -0
  185. package/dist/node/features/git.d.ts +329 -0
  186. package/dist/node/features/git.d.ts.map +1 -0
  187. package/dist/node/features/google-auth.d.ts +200 -0
  188. package/dist/node/features/google-auth.d.ts.map +1 -0
  189. package/dist/node/features/google-calendar.d.ts +194 -0
  190. package/dist/node/features/google-calendar.d.ts.map +1 -0
  191. package/dist/node/features/google-docs.d.ts +138 -0
  192. package/dist/node/features/google-docs.d.ts.map +1 -0
  193. package/dist/node/features/google-drive.d.ts +202 -0
  194. package/dist/node/features/google-drive.d.ts.map +1 -0
  195. package/dist/node/features/google-mail.d.ts +221 -0
  196. package/dist/node/features/google-mail.d.ts.map +1 -0
  197. package/dist/node/features/google-sheets.d.ts +157 -0
  198. package/dist/node/features/google-sheets.d.ts.map +1 -0
  199. package/dist/node/features/grep.d.ts +207 -0
  200. package/dist/node/features/grep.d.ts.map +1 -0
  201. package/dist/node/features/helpers.d.ts +236 -0
  202. package/dist/node/features/helpers.d.ts.map +1 -0
  203. package/dist/node/features/ink.d.ts +332 -0
  204. package/dist/node/features/ink.d.ts.map +1 -0
  205. package/dist/node/features/ipc-socket.d.ts +298 -0
  206. package/dist/node/features/ipc-socket.d.ts.map +1 -0
  207. package/dist/node/features/json-tree.d.ts +140 -0
  208. package/dist/node/features/json-tree.d.ts.map +1 -0
  209. package/dist/node/features/networking.d.ts +373 -0
  210. package/dist/node/features/networking.d.ts.map +1 -0
  211. package/dist/node/features/nlp.d.ts +125 -0
  212. package/dist/node/features/nlp.d.ts.map +1 -0
  213. package/dist/node/features/opener.d.ts +93 -0
  214. package/dist/node/features/opener.d.ts.map +1 -0
  215. package/dist/node/features/os.d.ts +168 -0
  216. package/dist/node/features/os.d.ts.map +1 -0
  217. package/dist/node/features/package-finder.d.ts +419 -0
  218. package/dist/node/features/package-finder.d.ts.map +1 -0
  219. package/dist/node/features/postgres.d.ts +173 -0
  220. package/dist/node/features/postgres.d.ts.map +1 -0
  221. package/dist/node/features/proc.d.ts +285 -0
  222. package/dist/node/features/proc.d.ts.map +1 -0
  223. package/dist/node/features/process-manager.d.ts +427 -0
  224. package/dist/node/features/process-manager.d.ts.map +1 -0
  225. package/dist/node/features/python.d.ts +477 -0
  226. package/dist/node/features/python.d.ts.map +1 -0
  227. package/dist/node/features/redis.d.ts +247 -0
  228. package/dist/node/features/redis.d.ts.map +1 -0
  229. package/dist/node/features/repl.d.ts +84 -0
  230. package/dist/node/features/repl.d.ts.map +1 -0
  231. package/dist/node/features/runpod.d.ts +527 -0
  232. package/dist/node/features/runpod.d.ts.map +1 -0
  233. package/dist/node/features/secure-shell.d.ts +145 -0
  234. package/dist/node/features/secure-shell.d.ts.map +1 -0
  235. package/dist/node/features/semantic-search.d.ts +207 -0
  236. package/dist/node/features/semantic-search.d.ts.map +1 -0
  237. package/dist/node/features/sqlite.d.ts +180 -0
  238. package/dist/node/features/sqlite.d.ts.map +1 -0
  239. package/dist/node/features/telegram.d.ts +173 -0
  240. package/dist/node/features/telegram.d.ts.map +1 -0
  241. package/dist/node/features/transpiler.d.ts +51 -0
  242. package/dist/node/features/transpiler.d.ts.map +1 -0
  243. package/dist/node/features/tts.d.ts +108 -0
  244. package/dist/node/features/tts.d.ts.map +1 -0
  245. package/dist/node/features/ui.d.ts +562 -0
  246. package/dist/node/features/ui.d.ts.map +1 -0
  247. package/dist/node/features/vault.d.ts +90 -0
  248. package/dist/node/features/vault.d.ts.map +1 -0
  249. package/dist/node/features/vm.d.ts +285 -0
  250. package/dist/node/features/vm.d.ts.map +1 -0
  251. package/dist/node/features/yaml-tree.d.ts +118 -0
  252. package/dist/node/features/yaml-tree.d.ts.map +1 -0
  253. package/dist/node/features/yaml.d.ts +127 -0
  254. package/dist/node/features/yaml.d.ts.map +1 -0
  255. package/dist/node.d.ts +67 -0
  256. package/dist/node.d.ts.map +1 -0
  257. package/dist/python/generated.d.ts +2 -0
  258. package/dist/python/generated.d.ts.map +1 -0
  259. package/dist/react/index.d.ts +36 -0
  260. package/dist/react/index.d.ts.map +1 -0
  261. package/dist/registry.d.ts +97 -0
  262. package/dist/registry.d.ts.map +1 -0
  263. package/dist/scaffolds/generated.d.ts +13 -0
  264. package/dist/scaffolds/generated.d.ts.map +1 -0
  265. package/dist/scaffolds/template.d.ts +11 -0
  266. package/dist/scaffolds/template.d.ts.map +1 -0
  267. package/dist/schemas/base.d.ts +254 -0
  268. package/dist/schemas/base.d.ts.map +1 -0
  269. package/dist/selector.d.ts +130 -0
  270. package/dist/selector.d.ts.map +1 -0
  271. package/dist/server.d.ts +89 -0
  272. package/dist/server.d.ts.map +1 -0
  273. package/dist/servers/express.d.ts +104 -0
  274. package/dist/servers/express.d.ts.map +1 -0
  275. package/dist/servers/mcp.d.ts +201 -0
  276. package/dist/servers/mcp.d.ts.map +1 -0
  277. package/dist/servers/socket.d.ts +121 -0
  278. package/dist/servers/socket.d.ts.map +1 -0
  279. package/dist/state.d.ts +24 -0
  280. package/dist/state.d.ts.map +1 -0
  281. package/dist/web/clients/socket.d.ts +37 -0
  282. package/dist/web/clients/socket.d.ts.map +1 -0
  283. package/dist/web/container.d.ts +55 -0
  284. package/dist/web/container.d.ts.map +1 -0
  285. package/dist/web/extension.d.ts +4 -0
  286. package/dist/web/extension.d.ts.map +1 -0
  287. package/dist/web/feature.d.ts +8 -0
  288. package/dist/web/feature.d.ts.map +1 -0
  289. package/dist/web/features/asset-loader.d.ts +35 -0
  290. package/dist/web/features/asset-loader.d.ts.map +1 -0
  291. package/dist/web/features/container-link.d.ts +167 -0
  292. package/dist/web/features/container-link.d.ts.map +1 -0
  293. package/dist/web/features/esbuild.d.ts +51 -0
  294. package/dist/web/features/esbuild.d.ts.map +1 -0
  295. package/dist/web/features/helpers.d.ts +140 -0
  296. package/dist/web/features/helpers.d.ts.map +1 -0
  297. package/dist/web/features/network.d.ts +69 -0
  298. package/dist/web/features/network.d.ts.map +1 -0
  299. package/dist/web/features/speech.d.ts +71 -0
  300. package/dist/web/features/speech.d.ts.map +1 -0
  301. package/dist/web/features/vault.d.ts +62 -0
  302. package/dist/web/features/vault.d.ts.map +1 -0
  303. package/dist/web/features/vm.d.ts +48 -0
  304. package/dist/web/features/vm.d.ts.map +1 -0
  305. package/dist/web/features/voice-recognition.d.ts +96 -0
  306. package/dist/web/features/voice-recognition.d.ts.map +1 -0
  307. package/dist/web/shims/isomorphic-vm.d.ts +22 -0
  308. package/dist/web/shims/isomorphic-vm.d.ts.map +1 -0
  309. package/index.html +1457 -0
  310. package/index.ts +1 -0
  311. package/install.sh +84 -0
  312. package/luca.cli.ts +16 -0
  313. package/luca.console.ts +9 -0
  314. package/main.py +6 -0
  315. package/package.json +219 -58
  316. package/public/index.html +1457 -0
  317. package/public/slides-ai-native.html +902 -0
  318. package/public/slides-intro.html +974 -0
  319. package/pyproject.toml +7 -0
  320. package/scripts/build-web.ts +28 -0
  321. package/scripts/examples/ask-luca-expert.ts +42 -0
  322. package/scripts/examples/assistant-questions.ts +12 -0
  323. package/scripts/examples/excalidraw-expert.ts +75 -0
  324. package/scripts/examples/expert-chat.ts +0 -0
  325. package/scripts/examples/file-manager.ts +14 -0
  326. package/scripts/examples/ideas.ts +12 -0
  327. package/scripts/examples/interactive-chat.ts +20 -0
  328. package/scripts/examples/openai-tool-calls.ts +113 -0
  329. package/scripts/examples/opening-a-web-browser.ts +5 -0
  330. package/scripts/examples/telegram-bot.ts +79 -0
  331. package/scripts/examples/using-assistant-with-mcp.ts +555 -0
  332. package/scripts/examples/using-claude-code.ts +10 -0
  333. package/scripts/examples/using-contentdb.ts +35 -0
  334. package/scripts/examples/using-conversations.ts +35 -0
  335. package/scripts/examples/using-disk-cache.ts +10 -0
  336. package/scripts/examples/using-docker-shell.ts +75 -0
  337. package/scripts/examples/using-elevenlabs.ts +25 -0
  338. package/scripts/examples/using-google-calendar.ts +57 -0
  339. package/scripts/examples/using-google-docs.ts +74 -0
  340. package/scripts/examples/using-google-drive.ts +74 -0
  341. package/scripts/examples/using-google-sheets.ts +89 -0
  342. package/scripts/examples/using-nlp.ts +55 -0
  343. package/scripts/examples/using-ollama.ts +11 -0
  344. package/scripts/examples/using-postgres.ts +55 -0
  345. package/scripts/examples/using-runpod.ts +32 -0
  346. package/scripts/examples/using-tts.ts +40 -0
  347. package/scripts/scaffold.ts +391 -0
  348. package/scripts/scratch.ts +15 -0
  349. package/scripts/stamp-build.sh +12 -0
  350. package/scripts/test-assistant-hooks.ts +13 -0
  351. package/scripts/test-docs-reader.ts +10 -0
  352. package/scripts/test-linux-binary.sh +80 -0
  353. package/scripts/update-introspection-data.ts +58 -0
  354. package/src/agi/README.md +14 -0
  355. package/src/agi/container.server.ts +156 -0
  356. package/src/agi/feature.ts +13 -0
  357. package/src/agi/features/agent-memory.ts +694 -0
  358. package/src/agi/features/assistant.ts +1653 -0
  359. package/src/agi/features/assistants-manager.ts +534 -0
  360. package/src/agi/features/autonomous-assistant.ts +431 -0
  361. package/src/agi/features/browser-use.ts +672 -0
  362. package/src/agi/features/claude-code.ts +1584 -0
  363. package/src/agi/features/coding-tools.ts +175 -0
  364. package/src/agi/features/conversation-history.ts +672 -0
  365. package/src/agi/features/conversation.ts +1494 -0
  366. package/src/agi/features/docs-reader.ts +167 -0
  367. package/src/agi/features/file-tools.ts +340 -0
  368. package/src/agi/features/luca-coder.ts +641 -0
  369. package/src/agi/features/mcp-bridge.ts +532 -0
  370. package/src/agi/features/openai-codex.ts +651 -0
  371. package/src/agi/features/openapi.ts +445 -0
  372. package/src/agi/features/skills-library.ts +557 -0
  373. package/src/agi/index.ts +6 -0
  374. package/src/agi/lib/interceptor-chain.ts +89 -0
  375. package/src/agi/lib/token-counter.ts +202 -0
  376. package/src/bootstrap/generated.ts +9791 -0
  377. package/src/browser.ts +25 -0
  378. package/src/bus.ts +122 -0
  379. package/src/cli/build-info.ts +4 -0
  380. package/src/cli/cli.ts +355 -0
  381. package/src/client.ts +170 -0
  382. package/src/clients/civitai/index.ts +537 -0
  383. package/src/clients/client-template.ts +41 -0
  384. package/src/clients/comfyui/index.ts +604 -0
  385. package/src/clients/elevenlabs/index.ts +317 -0
  386. package/src/clients/graph.ts +87 -0
  387. package/src/clients/openai/index.ts +456 -0
  388. package/src/clients/rest.ts +207 -0
  389. package/src/clients/supabase/index.ts +357 -0
  390. package/src/clients/voicebox/index.ts +300 -0
  391. package/src/clients/websocket.ts +251 -0
  392. package/src/command.ts +506 -0
  393. package/src/commands/bootstrap.ts +244 -0
  394. package/src/commands/chat.ts +309 -0
  395. package/src/commands/code.ts +371 -0
  396. package/src/commands/console.ts +189 -0
  397. package/src/commands/describe.ts +243 -0
  398. package/src/commands/eval.ts +67 -0
  399. package/src/commands/help.ts +240 -0
  400. package/src/commands/index.ts +19 -0
  401. package/src/commands/introspect.ts +218 -0
  402. package/src/commands/mcp.ts +64 -0
  403. package/src/commands/prompt.ts +1014 -0
  404. package/src/commands/run.ts +278 -0
  405. package/src/commands/sandbox-mcp.ts +343 -0
  406. package/src/commands/save-api-docs.ts +51 -0
  407. package/src/commands/scaffold.ts +225 -0
  408. package/src/commands/select.ts +99 -0
  409. package/src/commands/serve.ts +208 -0
  410. package/src/container-describer.ts +1091 -0
  411. package/src/container.ts +1199 -0
  412. package/src/endpoint.ts +365 -0
  413. package/src/entity.ts +173 -0
  414. package/src/feature.ts +118 -0
  415. package/src/graft.ts +181 -0
  416. package/src/hash-object.ts +97 -0
  417. package/src/helper.ts +849 -0
  418. package/src/introspection/generated.agi.ts +41200 -0
  419. package/src/introspection/generated.node.ts +28773 -0
  420. package/src/introspection/generated.web.ts +2272 -0
  421. package/src/introspection/index.ts +296 -0
  422. package/src/introspection/scan.ts +1136 -0
  423. package/src/node/container.ts +409 -0
  424. package/src/node/feature.ts +13 -0
  425. package/src/node/features/container-link.ts +559 -0
  426. package/src/node/features/content-db.ts +849 -0
  427. package/src/node/features/disk-cache.ts +388 -0
  428. package/src/node/features/display-result.ts +57 -0
  429. package/src/node/features/dns.ts +669 -0
  430. package/src/node/features/docker.ts +921 -0
  431. package/src/node/features/downloader.ts +79 -0
  432. package/src/node/features/figlet-fonts.ts +600 -0
  433. package/src/node/features/file-manager.ts +535 -0
  434. package/src/node/features/fs.ts +1050 -0
  435. package/src/node/features/git.ts +592 -0
  436. package/src/node/features/google-auth.ts +504 -0
  437. package/src/node/features/google-calendar.ts +306 -0
  438. package/src/node/features/google-docs.ts +412 -0
  439. package/src/node/features/google-drive.ts +346 -0
  440. package/src/node/features/google-mail.ts +540 -0
  441. package/src/node/features/google-sheets.ts +286 -0
  442. package/src/node/features/grep.ts +427 -0
  443. package/src/node/features/helpers.ts +762 -0
  444. package/src/node/features/ink.ts +490 -0
  445. package/src/node/features/ipc-socket.ts +649 -0
  446. package/src/node/features/json-tree.ts +170 -0
  447. package/src/node/features/networking.ts +961 -0
  448. package/src/node/features/nlp.ts +212 -0
  449. package/src/node/features/opener.ts +180 -0
  450. package/src/node/features/os.ts +403 -0
  451. package/src/node/features/package-finder.ts +540 -0
  452. package/src/node/features/postgres.ts +289 -0
  453. package/src/node/features/proc.ts +503 -0
  454. package/src/node/features/process-manager.ts +844 -0
  455. package/src/node/features/python.ts +912 -0
  456. package/src/node/features/redis.ts +446 -0
  457. package/src/node/features/repl.ts +212 -0
  458. package/src/node/features/runpod.ts +811 -0
  459. package/src/node/features/secure-shell.ts +261 -0
  460. package/src/node/features/semantic-search.ts +935 -0
  461. package/src/node/features/sqlite.ts +289 -0
  462. package/src/node/features/telegram.ts +343 -0
  463. package/src/node/features/transpiler.ts +160 -0
  464. package/src/node/features/tts.ts +185 -0
  465. package/src/node/features/ui.ts +791 -0
  466. package/src/node/features/vault.ts +153 -0
  467. package/src/node/features/vm.ts +462 -0
  468. package/src/node/features/yaml-tree.ts +148 -0
  469. package/src/node/features/yaml.ts +133 -0
  470. package/src/node.ts +76 -0
  471. package/src/python/bridge.py +220 -0
  472. package/src/python/generated.ts +226 -0
  473. package/src/react/index.ts +175 -0
  474. package/src/registry.ts +210 -0
  475. package/src/scaffolds/generated.ts +1814 -0
  476. package/src/scaffolds/template.ts +46 -0
  477. package/src/schemas/base.ts +296 -0
  478. package/src/selector.ts +352 -0
  479. package/src/server.ts +229 -0
  480. package/src/servers/express.ts +283 -0
  481. package/src/servers/mcp.ts +802 -0
  482. package/src/servers/socket.ts +258 -0
  483. package/src/state.ts +101 -0
  484. package/src/web/clients/socket.ts +99 -0
  485. package/src/web/container.ts +75 -0
  486. package/src/web/extension.ts +30 -0
  487. package/src/web/feature.ts +12 -0
  488. package/src/web/features/asset-loader.ts +72 -0
  489. package/src/web/features/container-link.ts +382 -0
  490. package/src/web/features/esbuild.ts +93 -0
  491. package/src/web/features/helpers.ts +291 -0
  492. package/src/web/features/network.ts +85 -0
  493. package/src/web/features/speech.ts +104 -0
  494. package/src/web/features/vault.ts +207 -0
  495. package/src/web/features/vm.ts +85 -0
  496. package/src/web/features/voice-recognition.ts +161 -0
  497. package/src/web/shims/isomorphic-vm.ts +149 -0
  498. package/tsconfig.build.json +12 -0
  499. package/tsconfig.json +58 -0
  500. package/uv.lock +8 -0
  501. package/LICENSE +0 -21
  502. package/dist/cli/cli.js +0 -48
  503. package/dist/cli/common.d.ts +0 -2
  504. package/dist/cli/common.js +0 -6
  505. package/dist/cli/index.d.ts +0 -2
  506. package/dist/cli/index.js +0 -5
  507. package/dist/cli/run.d.ts +0 -1
  508. package/dist/cli/run.js +0 -38
  509. package/dist/core/index.d.ts +0 -4
  510. package/dist/core/index.js +0 -32
  511. package/dist/core/read.d.ts +0 -2
  512. package/dist/core/read.js +0 -29
  513. package/dist/core/request.d.ts +0 -1
  514. package/dist/core/request.js +0 -2
  515. package/dist/core/write.d.ts +0 -2
  516. package/dist/core/write.js +0 -21
  517. package/dist/index.d.ts +0 -1
  518. package/dist/index.js +0 -5
  519. package/dist/utils/common.d.ts +0 -9
  520. package/dist/utils/common.js +0 -57
  521. package/dist/utils/consts.d.ts +0 -3
  522. package/dist/utils/consts.js +0 -11
  523. package/dist/utils/dict.d.ts +0 -1
  524. package/dist/utils/dict.js +0 -7
  525. package/dist/utils/index.d.ts +0 -5
  526. package/dist/utils/index.js +0 -21
  527. package/dist/utils/log.d.ts +0 -1
  528. package/dist/utils/log.js +0 -5
  529. package/dist/utils/types.d.ts +0 -1
  530. package/dist/utils/types.js +0 -2
  531. package/dist/utils/utils.test.d.ts +0 -1
  532. package/dist/utils/utils.test.js +0 -7
@@ -0,0 +1,504 @@
1
+ import { z } from 'zod'
2
+ import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
3
+ import { Feature } from '../feature.js'
4
+ import { google } from 'googleapis'
5
+ import type { OAuth2Client } from 'google-auth-library'
6
+
7
+ export const GoogleAuthStateSchema = FeatureStateSchema.extend({
8
+ authMode: z.enum(['oauth2', 'service-account', 'none']).default('none')
9
+ .describe('Current authentication mode'),
10
+ isAuthenticated: z.boolean().default(false)
11
+ .describe('Whether valid credentials are currently available'),
12
+ email: z.string().optional()
13
+ .describe('Authenticated user or service account email'),
14
+ scopes: z.array(z.string()).default([])
15
+ .describe('OAuth2 scopes that have been authorized'),
16
+ tokenExpiry: z.string().optional()
17
+ .describe('ISO timestamp when the current access token expires'),
18
+ lastError: z.string().optional()
19
+ .describe('Last authentication error message'),
20
+ })
21
+ export type GoogleAuthState = z.infer<typeof GoogleAuthStateSchema>
22
+
23
+ export const GoogleAuthOptionsSchema = FeatureOptionsSchema.extend({
24
+ mode: z.enum(['oauth2', 'service-account']).optional()
25
+ .describe('Authentication mode. Auto-detected if serviceAccountKeyPath is set'),
26
+ clientId: z.string().optional()
27
+ .describe('OAuth2 client ID (falls back to GOOGLE_CLIENT_ID env var)'),
28
+ clientSecret: z.string().optional()
29
+ .describe('OAuth2 client secret (falls back to GOOGLE_CLIENT_SECRET env var)'),
30
+ serviceAccountKeyPath: z.string().optional()
31
+ .describe('Path to service account JSON key file (falls back to GOOGLE_SERVICE_ACCOUNT_KEY env var)'),
32
+ serviceAccountKey: z.record(z.string(), z.any()).optional()
33
+ .describe('Service account key as a parsed JSON object (alternative to file path)'),
34
+ scopes: z.array(z.string()).optional()
35
+ .describe('OAuth2 scopes to request'),
36
+ redirectPort: z.number().optional()
37
+ .describe('Port for OAuth2 callback server (falls back to GOOGLE_OAUTH_REDIRECT_PORT env var, then 3000)'),
38
+ tokenCacheKey: z.string().optional()
39
+ .describe('DiskCache key for storing OAuth2 refresh token'),
40
+ })
41
+ export type GoogleAuthOptions = z.infer<typeof GoogleAuthOptionsSchema>
42
+
43
+ export const GoogleAuthEventsSchema = FeatureEventsSchema.extend({
44
+ authenticated: z.tuple([z.object({
45
+ mode: z.string().describe('Auth mode used'),
46
+ email: z.string().optional().describe('User or service account email'),
47
+ })]).describe('Authentication successful'),
48
+ tokenRefreshed: z.tuple([]).describe('Access token was refreshed'),
49
+ authorizationRequired: z.tuple([z.string().describe('Authorization URL to visit')])
50
+ .describe('User must visit this URL to authorize'),
51
+ error: z.tuple([z.any().describe('The error')]).describe('Authentication error occurred'),
52
+ })
53
+
54
+ /**
55
+ * Google authentication feature supporting OAuth2 browser flow and service account auth.
56
+ *
57
+ * Handles the complete OAuth2 lifecycle: authorization URL generation, local callback server,
58
+ * token exchange, refresh token storage (via diskCache), and automatic token refresh.
59
+ * Also supports non-interactive service account authentication via JSON key files.
60
+ *
61
+ * Other Google features (drive, sheets, calendar, docs) depend on this feature
62
+ * and access it lazily via `container.feature('googleAuth')`.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * // OAuth2 flow — opens browser for consent
67
+ * const auth = container.feature('googleAuth', {
68
+ * clientId: 'your-client-id.apps.googleusercontent.com',
69
+ * clientSecret: 'your-secret',
70
+ * scopes: ['https://www.googleapis.com/auth/drive.readonly'],
71
+ * })
72
+ * await auth.authorize()
73
+ *
74
+ * // Service account flow — no browser needed
75
+ * const auth = container.feature('googleAuth', {
76
+ * serviceAccountKeyPath: '/path/to/key.json',
77
+ * scopes: ['https://www.googleapis.com/auth/spreadsheets.readonly'],
78
+ * })
79
+ * await auth.authenticateServiceAccount()
80
+ * ```
81
+ */
82
+ export class GoogleAuth extends Feature<GoogleAuthState, GoogleAuthOptions> {
83
+ static override shortcut = 'features.googleAuth' as const
84
+ static override envVars = [
85
+ 'GOOGLE_CLIENT_ID',
86
+ 'GOOGLE_CLIENT_SECRET',
87
+ 'GOOGLE_SERVICE_ACCOUNT_KEY',
88
+ 'GOOGLE_OAUTH_REDIRECT_PORT',
89
+ ]
90
+ static override stateSchema = GoogleAuthStateSchema
91
+ static override optionsSchema = GoogleAuthOptionsSchema
92
+ static override eventsSchema = GoogleAuthEventsSchema
93
+ static { Feature.register(this, 'googleAuth') }
94
+
95
+ private _oauth2Client?: OAuth2Client
96
+ private _redirectUri?: string
97
+
98
+ override get initialState(): GoogleAuthState {
99
+ return {
100
+ ...super.initialState,
101
+ authMode: 'none',
102
+ isAuthenticated: false,
103
+ scopes: [],
104
+ }
105
+ }
106
+
107
+ /** OAuth2 client ID from options or GOOGLE_CLIENT_ID env var. */
108
+ get clientId(): string {
109
+ const id = this.options.clientId || process.env.GOOGLE_CLIENT_ID
110
+ if (!id) throw new Error('Google client ID required. Set options.clientId or GOOGLE_CLIENT_ID env var.')
111
+ return id
112
+ }
113
+
114
+ /** OAuth2 client secret from options or GOOGLE_CLIENT_SECRET env var. */
115
+ get clientSecret(): string {
116
+ const secret = this.options.clientSecret || process.env.GOOGLE_CLIENT_SECRET
117
+ if (!secret) throw new Error('Google client secret required. Set options.clientSecret or GOOGLE_CLIENT_SECRET env var.')
118
+ return secret
119
+ }
120
+
121
+ /** Resolved authentication mode based on options. */
122
+ get authMode(): 'oauth2' | 'service-account' {
123
+ if (this.options.mode) return this.options.mode
124
+ if (this.options.serviceAccountKeyPath || this.options.serviceAccountKey || process.env.GOOGLE_SERVICE_ACCOUNT_KEY) {
125
+ return 'service-account'
126
+ }
127
+ return 'oauth2'
128
+ }
129
+
130
+ /** Whether valid credentials are currently available. */
131
+ get isAuthenticated(): boolean {
132
+ return this.state.get('isAuthenticated') || false
133
+ }
134
+
135
+ /** Default scopes covering Drive, Sheets, Calendar, and Docs read access. */
136
+ get defaultScopes(): string[] {
137
+ return [
138
+ 'https://www.googleapis.com/auth/drive.readonly',
139
+ 'https://www.googleapis.com/auth/spreadsheets.readonly',
140
+ 'https://www.googleapis.com/auth/calendar.readonly',
141
+ 'https://www.googleapis.com/auth/documents.readonly',
142
+ 'https://www.googleapis.com/auth/gmail.readonly',
143
+ ]
144
+ }
145
+
146
+ /** Resolved redirect port from options, GOOGLE_OAUTH_REDIRECT_PORT env var, or default 3000. */
147
+ get redirectPort(): number {
148
+ return this.options.redirectPort
149
+ || (process.env.GOOGLE_OAUTH_REDIRECT_PORT ? parseInt(process.env.GOOGLE_OAUTH_REDIRECT_PORT, 10) : undefined)
150
+ || 3000
151
+ }
152
+
153
+ /** DiskCache key used for storing the refresh token. */
154
+ get tokenCacheKey(): string {
155
+ return this.options.tokenCacheKey || `google-auth:refresh:${this.clientId}`
156
+ }
157
+
158
+ /**
159
+ * Get the OAuth2Client instance, creating it lazily.
160
+ * After authentication, this client has valid credentials set.
161
+ *
162
+ * @returns The OAuth2Client instance
163
+ */
164
+ getOAuth2Client(): OAuth2Client {
165
+ if (this._oauth2Client) return this._oauth2Client
166
+
167
+ const redirectUri = this._redirectUri || `http://localhost:${this.redirectPort}/oauth2callback`
168
+ this._oauth2Client = new google.auth.OAuth2(this.clientId, this.clientSecret, redirectUri)
169
+ return this._oauth2Client
170
+ }
171
+
172
+ /**
173
+ * Get the authenticated auth client for passing to googleapis service constructors.
174
+ * Handles token refresh automatically for OAuth2. For service accounts, returns
175
+ * the JWT auth client.
176
+ *
177
+ * @returns An auth client suitable for `google.drive({ version: 'v3', auth })`
178
+ */
179
+ async getAuthClient(): Promise<OAuth2Client | ReturnType<typeof google.auth.fromJSON>> {
180
+ if (!this.isAuthenticated) {
181
+ // Try restoring from cache first
182
+ const restored = await this.tryRestoreTokens()
183
+ if (!restored) {
184
+ throw new Error('Not authenticated. Call authorize() or authenticateServiceAccount() first.')
185
+ }
186
+ }
187
+
188
+ if (this.state.get('authMode') === 'service-account') {
189
+ const key = this.getServiceAccountKey()
190
+ const auth = google.auth.fromJSON(key) as any
191
+ auth.scopes = this.options.scopes || this.defaultScopes
192
+ return auth
193
+ }
194
+
195
+ const client = this.getOAuth2Client()
196
+
197
+ // Check if token needs refresh
198
+ const expiry = this.state.get('tokenExpiry')
199
+ if (expiry && new Date(expiry).getTime() < Date.now() + 60_000) {
200
+ try {
201
+ const { credentials } = await client.refreshAccessToken()
202
+ client.setCredentials(credentials)
203
+ if (credentials.expiry_date) {
204
+ this.setState({ tokenExpiry: new Date(credentials.expiry_date).toISOString() })
205
+ }
206
+ this.emit('tokenRefreshed')
207
+ } catch (err: any) {
208
+ this.setState({ lastError: err.message, isAuthenticated: false })
209
+ this.emit('error', err)
210
+ throw err
211
+ }
212
+ }
213
+
214
+ return client
215
+ }
216
+
217
+ /**
218
+ * Start the OAuth2 authorization flow.
219
+ *
220
+ * 1. Spins up a temporary Express callback server on a free port
221
+ * 2. Generates the Google authorization URL
222
+ * 3. Opens the browser to the consent page
223
+ * 4. Waits for the callback with the authorization code
224
+ * 5. Exchanges the code for access + refresh tokens
225
+ * 6. Stores the refresh token in diskCache
226
+ * 7. Shuts down the callback server
227
+ *
228
+ * @param scopes - OAuth2 scopes to request (defaults to options.scopes or defaultScopes)
229
+ */
230
+ async authorize(scopes?: string[]): Promise<this> {
231
+ const requestedScopes = scopes || this.options.scopes || this.defaultScopes
232
+ const port = this.redirectPort
233
+ const redirectUri = `http://localhost:${port}/oauth2callback`
234
+ this._redirectUri = redirectUri
235
+
236
+ const oauth2Client = new google.auth.OAuth2(this.clientId, this.clientSecret, redirectUri)
237
+ this._oauth2Client = oauth2Client
238
+
239
+ const authUrl = oauth2Client.generateAuthUrl({
240
+ access_type: 'offline',
241
+ scope: requestedScopes,
242
+ prompt: 'consent',
243
+ })
244
+
245
+ this.emit('authorizationRequired', authUrl)
246
+
247
+ // Create a promise that resolves when the callback is received
248
+ const codePromise = new Promise<string>((resolve, reject) => {
249
+ const server = Bun.serve({
250
+ port,
251
+ fetch(req) {
252
+ const url = new URL(req.url)
253
+ if (url.pathname === '/oauth2callback') {
254
+ const code = url.searchParams.get('code')
255
+ const error = url.searchParams.get('error')
256
+
257
+ if (error) {
258
+ reject(new Error(`OAuth2 authorization denied: ${error}`))
259
+ return new Response(
260
+ '<html><body><h2>Authorization denied.</h2><p>You can close this window.</p></body></html>',
261
+ { headers: { 'Content-Type': 'text/html' } }
262
+ )
263
+ }
264
+
265
+ if (code) {
266
+ resolve(code)
267
+ return new Response(
268
+ '<html><body><h2>Authorization successful!</h2><p>You can close this window.</p></body></html>',
269
+ { headers: { 'Content-Type': 'text/html' } }
270
+ )
271
+ }
272
+
273
+ reject(new Error('No authorization code received'))
274
+ return new Response('Missing code', { status: 400 })
275
+ }
276
+ return new Response('Not found', { status: 404 })
277
+ },
278
+ })
279
+
280
+ // Store server reference for cleanup
281
+ ;(this as any)._callbackServer = server
282
+
283
+ // Timeout after 5 minutes
284
+ setTimeout(() => {
285
+ reject(new Error('OAuth2 authorization timed out (5 minutes)'))
286
+ }, 5 * 60 * 1000)
287
+ })
288
+
289
+ // Open the browser
290
+ try {
291
+ const opener = this.container.feature('opener')
292
+ await opener.open(authUrl)
293
+ } catch {
294
+ // If opener fails, log the URL for manual opening
295
+ console.log(`\nOpen this URL in your browser to authorize:\n${authUrl}\n`)
296
+ }
297
+
298
+ try {
299
+ const code = await codePromise
300
+ const { tokens } = await oauth2Client.getToken(code)
301
+ oauth2Client.setCredentials(tokens)
302
+
303
+ // Store refresh token
304
+ if (tokens.refresh_token) {
305
+ await this.storeRefreshToken(tokens.refresh_token)
306
+ }
307
+
308
+ // Fetch user info
309
+ let email: string | undefined
310
+ try {
311
+ const oauth2 = google.oauth2({ version: 'v2', auth: oauth2Client })
312
+ const userInfo = await oauth2.userinfo.get()
313
+ email = userInfo.data.email || undefined
314
+ } catch {
315
+ // Non-critical — email is optional
316
+ }
317
+
318
+ this.setState({
319
+ authMode: 'oauth2',
320
+ isAuthenticated: true,
321
+ email,
322
+ scopes: requestedScopes,
323
+ tokenExpiry: tokens.expiry_date ? new Date(tokens.expiry_date).toISOString() : undefined,
324
+ lastError: undefined,
325
+ })
326
+
327
+ this.emit('authenticated', { mode: 'oauth2', email })
328
+ } catch (err: any) {
329
+ this.setState({ lastError: err.message })
330
+ this.emit('error', err)
331
+ throw err
332
+ } finally {
333
+ // Shut down callback server
334
+ const server = (this as any)._callbackServer
335
+ if (server) {
336
+ server.stop()
337
+ delete (this as any)._callbackServer
338
+ }
339
+ }
340
+
341
+ return this
342
+ }
343
+
344
+ /**
345
+ * Authenticate using a service account JSON key file.
346
+ * Reads the key from options.serviceAccountKeyPath, options.serviceAccountKey,
347
+ * or the GOOGLE_SERVICE_ACCOUNT_KEY env var.
348
+ *
349
+ * @returns This feature instance for chaining
350
+ */
351
+ async authenticateServiceAccount(): Promise<this> {
352
+ try {
353
+ const key = this.getServiceAccountKey()
354
+ const scopes = this.options.scopes || this.defaultScopes
355
+ const auth = google.auth.fromJSON(key) as any
356
+ auth.scopes = scopes
357
+
358
+ // Test the auth by getting an access token
359
+ const token = await auth.getAccessToken()
360
+ if (!token) {
361
+ throw new Error('Failed to obtain access token from service account')
362
+ }
363
+
364
+ this.setState({
365
+ authMode: 'service-account',
366
+ isAuthenticated: true,
367
+ email: key.client_email,
368
+ scopes,
369
+ lastError: undefined,
370
+ })
371
+
372
+ this.emit('authenticated', { mode: 'service-account', email: key.client_email })
373
+ } catch (err: any) {
374
+ this.setState({ lastError: err.message })
375
+ this.emit('error', err)
376
+ throw err
377
+ }
378
+
379
+ return this
380
+ }
381
+
382
+ /**
383
+ * Attempt to restore authentication from a cached refresh token.
384
+ * Called automatically by getAuthClient() if not yet authenticated.
385
+ *
386
+ * @returns true if tokens were restored successfully
387
+ */
388
+ async tryRestoreTokens(): Promise<boolean> {
389
+ if (this.authMode === 'service-account') {
390
+ try {
391
+ await this.authenticateServiceAccount()
392
+ return true
393
+ } catch {
394
+ return false
395
+ }
396
+ }
397
+
398
+ try {
399
+ const refreshToken = await this.loadRefreshToken()
400
+ if (!refreshToken) return false
401
+
402
+ const oauth2Client = this.getOAuth2Client()
403
+ oauth2Client.setCredentials({ refresh_token: refreshToken })
404
+
405
+ const { credentials } = await oauth2Client.refreshAccessToken()
406
+ oauth2Client.setCredentials(credentials)
407
+
408
+ let email: string | undefined
409
+ try {
410
+ const oauth2 = google.oauth2({ version: 'v2', auth: oauth2Client })
411
+ const userInfo = await oauth2.userinfo.get()
412
+ email = userInfo.data.email || undefined
413
+ } catch {
414
+ // Non-critical
415
+ }
416
+
417
+ this.setState({
418
+ authMode: 'oauth2',
419
+ isAuthenticated: true,
420
+ email,
421
+ tokenExpiry: credentials.expiry_date ? new Date(credentials.expiry_date).toISOString() : undefined,
422
+ lastError: undefined,
423
+ })
424
+
425
+ this.emit('authenticated', { mode: 'oauth2', email })
426
+ return true
427
+ } catch {
428
+ return false
429
+ }
430
+ }
431
+
432
+ /**
433
+ * Revoke the current credentials and clear cached tokens.
434
+ *
435
+ * @returns This feature instance for chaining
436
+ */
437
+ async revoke(): Promise<this> {
438
+ try {
439
+ if (this.state.get('authMode') === 'oauth2' && this._oauth2Client) {
440
+ await this._oauth2Client.revokeCredentials()
441
+ }
442
+ } catch {
443
+ // Best effort revocation
444
+ }
445
+
446
+ // Clear cached refresh token
447
+ try {
448
+ const cache = this.container.feature('diskCache')
449
+ await cache.rm(this.tokenCacheKey)
450
+ } catch {
451
+ // Cache may not exist
452
+ }
453
+
454
+ this._oauth2Client = undefined
455
+ this.setState({
456
+ authMode: 'none',
457
+ isAuthenticated: false,
458
+ email: undefined,
459
+ scopes: [],
460
+ tokenExpiry: undefined,
461
+ })
462
+
463
+ return this
464
+ }
465
+
466
+ /** Store a refresh token in diskCache. */
467
+ private async storeRefreshToken(token: string): Promise<void> {
468
+ const cache = this.container.feature('diskCache')
469
+ await cache.set(this.tokenCacheKey, token)
470
+ }
471
+
472
+ /** Load a refresh token from diskCache. */
473
+ private async loadRefreshToken(): Promise<string | null> {
474
+ try {
475
+ const cache = this.container.feature('diskCache')
476
+ const exists = await cache.has(this.tokenCacheKey)
477
+ if (!exists) return null
478
+ return await cache.get(this.tokenCacheKey)
479
+ } catch {
480
+ return null
481
+ }
482
+ }
483
+
484
+ /** Resolve the service account key from options or env var. */
485
+ private getServiceAccountKey(): any {
486
+ if (this.options.serviceAccountKey) return this.options.serviceAccountKey
487
+
488
+ const keyPath = this.options.serviceAccountKeyPath || process.env.GOOGLE_SERVICE_ACCOUNT_KEY
489
+ if (!keyPath) {
490
+ throw new Error('Service account key required. Set options.serviceAccountKeyPath, options.serviceAccountKey, or GOOGLE_SERVICE_ACCOUNT_KEY env var.')
491
+ }
492
+
493
+ const resolved = this.container.paths.resolve(keyPath)
494
+ return this.container.fs.readJson(resolved)
495
+ }
496
+ }
497
+
498
+ declare module '../../feature' {
499
+ interface AvailableFeatures {
500
+ googleAuth: typeof GoogleAuth
501
+ }
502
+ }
503
+
504
+ export default GoogleAuth