nitrojs / nitro-cloudflare-dev

Enable access to the Cloudflare runtime bindings in development server of Nitro and Nuxt
MIT License
79 stars 4 forks source link

Authentication #26

Open RihanArfan opened 4 months ago

RihanArfan commented 4 months ago

When using AI bindings, wrangler requires logging in to run the AI models on Cloudflare even during local development. However, no link is shown to authenticate in the Nuxt console.

I'm not sure whether wrangler via getPlatformProxy even exposes a way to get the link to authenticate. If you can pass wrangler's console through to the Nuxt one it should suffice.

The current workaround is to use C3 to create Workers template, add the AI binding and launch it directly through Wrangler to authenticate wrangler system wide to your Cloudflare account.

Potentially blocks https://github.com/nuxt-hub/core/pull/173

 ERROR  [nuxt] [request error] [unhandled] [500] Error: Not logged in.
    at requireLoggedIn (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/cfetch/internal.ts:133:9)
    at performApiFetch (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/cfetch/internal.ts:29:2)
    at fetchInternal (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/cfetch/internal.ts:69:19)
    at fetchPagedListResult (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/cfetch/index.ts:120:16)
    at getAccountChoices (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/user/choose-account.tsx:19:21)
    at getAccountId (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/user/user.ts:1130:19)
    at AIFetcher (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/ai/fetcher.ts:17:20)
    at Miniflare2.#handleLoopbackCustomService (/workspaces/nuxt-hub-core/node_modules/.pnpm/miniflare@3.20240610.0/node_modules/miniflare/src/index.ts:819:21)
    at Server.#handleLoopback (/workspaces/nuxt-hub-core/node_modules/.pnpm/miniflare@3.20240610.0/node_modules/miniflare/src/index.ts:878:16)
  at requireLoggedIn (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/cfetch/internal.ts:133:9)  
  at performApiFetch (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/cfetch/internal.ts:29:2)  
  at fetchInternal (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/cfetch/internal.ts:69:19)  
  at fetchPagedListResult (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/cfetch/index.ts:120:16)  
  at getAccountChoices (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/user/choose-account.tsx:19:21)  
  at getAccountId (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/user/user.ts:1130:19)  
  at AIFetcher (/workspaces/nuxt-hub-core/node_modules/.pnpm/wrangler@3.60.3_@cloudflare+workers-types@4.20240614.0/node_modules/wrangler/src/ai/fetcher.ts:17:20)  
  at Miniflare2.#handleLoopbackCustomService (/workspaces/nuxt-hub-core/node_modules/.pnpm/miniflare@3.20240610.0/node_modules/miniflare/src/index.ts:819:21)  
  at Server.#handleLoopback (/workspaces/nuxt-hub-core/node_modules/.pnpm/miniflare@3.20240610.0/node_modules/miniflare/src/index.ts:878:16)  
  at process.processTicksAndRejections (node:internal/process/task_queues:95:5)  
  at Object.handler (./server/api/ai.ts:3:1)  
  at async /workspaces/nuxt-hub-core/node_modules/.pnpm/h3@1.11.1/node_modules/h3/dist/index.mjs:1962:19  
  at async Object.callAsync (/workspaces/nuxt-hub-core/node_modules/.pnpm/unctx@2.3.1/node_modules/unctx/dist/index.mjs:72:16)  
  at async Server.toNodeHandle (/workspaces/nuxt-hub-core/node_modules/.pnpm/h3@1.11.1/node_modules/h3/dist/index.mjs:2249:7)
pi0 commented 4 months ago

Intresting issue. /cc @dario-piotrowicz do you have some ideas?

RihanArfan commented 4 months ago

When starting an application with AI bindings, it notifies about billing but doesn't prompt to authenticate until the first call to AI.run(). It seems like it does the same thing as npx wrangler login, so an idea if their SDK exposes login is to programatically do that upon Error: Not logged in exceptions.

image

Upon authenticating with the link, wrangler has an interactive CLI to choose an account.

image
dario-piotrowicz commented 4 months ago

Hey @pi0 and @RihanArfan πŸ‘‹

The Ai authentication with getPlatformProxy has been on my radar for a while and it is something that we need to document better and as @RihanArfan put it, something that could actually hopefully be improved

I suspect that getting getPlatformProxy to inherit the wrangler login behavior should be possible, but on the top of my head I am not sure how complex implementing that will be

If it works for you I will look into that in the following few days and let you know what the situation is and eventually a possible ETA for that πŸ™‚

pi0 commented 4 months ago

Thanks! Let me know if i could help on anything.

(Btw just some idea, if tty access is the issue for prompt, maybe getPlatformProxy can accept an option like prompt like onAuth to let the integration add it somehow? )

dario-piotrowicz commented 4 months ago

Thanks! Let me know if i could help on anything.

Sure, I'll let you know if I'll need help, thanks πŸ˜„

(Btw just some idea, if tty access is the issue for prompt, maybe getPlatformProxy can accept an option like prompt like onAuth to let the integration add it somehow? )

That's a possible idea, but as I mentioned what I have in mind is to see if and how much we can just reuse from wrangler itself, ideally I'd love it if we could just write in the parent process' stdout and read from its stdin and just simply use the same exact flow that wrangler has... WDYT? that shouldn't be problematic for users of getPlatformProxy right? the nitro-cloudflare-dev module does not suppress any stdin/stdout related to getPlatformProxy right?

dario-piotrowicz commented 4 months ago

@pi0 I've looked into this and in a standard node.js program the above works as expected. If you run getPlatformProxy and try to use AI in the terminal you'll see the various links and interactive prompts.

So I am thinking that this is an issue in regards on how nitro/nuxt calls getPlatformProxy, I am guessing that whatever way you're running the function doesn't allow it to access the stdin/stdout of the terminal and/or doesn't make it look like the terminal is interactive.

This issue could be fixed by making getPlatformProxy able to interact with the terminal as it should, but I am guessing that that could be not possible due to the nitro's dev isolation strategy? what do you think?

if the above is not possible then I can only think, as you mentioned, of us defining some sort of API in getPlatformProxy that would make it possible to programmatically get the links and prompts, etc... but I can see it not being 100% straightforward and me getting pushbacks from the team since this API is only needed/requested by nitro/nuxt πŸ€”

pi0 commented 4 months ago

Thanks for investigating. Yes indeed it is specific to Nitro because we use Node.js Worker Threads and while they have access to studio, they don't have an interactive TTY and proxy needs custom hooks.

Let me think more about it also next steps when directly using miniflare/workerd (on positive side, miniflare is initialized on main thread so i guess that won't have this limit)