neon-init 0.13.1 → 0.15.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 (117) hide show
  1. package/dist/cli.js +368 -33
  2. package/dist/cli.js.map +1 -1
  3. package/dist/index.d.ts +15 -3
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +220 -41
  6. package/dist/index.js.map +1 -1
  7. package/dist/interactive.d.ts +12 -0
  8. package/dist/interactive.d.ts.map +1 -0
  9. package/dist/interactive.js +495 -0
  10. package/dist/interactive.js.map +1 -0
  11. package/dist/lib/agents.d.ts +23 -0
  12. package/dist/lib/agents.d.ts.map +1 -0
  13. package/dist/lib/agents.js +148 -0
  14. package/dist/lib/agents.js.map +1 -0
  15. package/dist/lib/auth.d.ts +10 -3
  16. package/dist/lib/auth.d.ts.map +1 -1
  17. package/dist/lib/auth.js +20 -13
  18. package/dist/lib/auth.js.map +1 -1
  19. package/dist/lib/bootstrap.d.ts +30 -0
  20. package/dist/lib/bootstrap.d.ts.map +1 -0
  21. package/dist/lib/bootstrap.js +61 -0
  22. package/dist/lib/bootstrap.js.map +1 -0
  23. package/dist/lib/build-config.d.ts +5 -0
  24. package/dist/lib/build-config.d.ts.map +1 -0
  25. package/dist/lib/build-config.js +6 -0
  26. package/dist/lib/build-config.js.map +1 -0
  27. package/dist/lib/detect-agent.d.ts +22 -0
  28. package/dist/lib/detect-agent.d.ts.map +1 -0
  29. package/dist/lib/detect-agent.js +65 -0
  30. package/dist/lib/detect-agent.js.map +1 -0
  31. package/dist/lib/editors.d.ts.map +1 -1
  32. package/dist/lib/editors.js +1 -2
  33. package/dist/lib/editors.js.map +1 -1
  34. package/dist/lib/extension.d.ts +11 -3
  35. package/dist/lib/extension.d.ts.map +1 -1
  36. package/dist/lib/extension.js +29 -9
  37. package/dist/lib/extension.js.map +1 -1
  38. package/dist/lib/inspect.d.ts +28 -0
  39. package/dist/lib/inspect.d.ts.map +1 -0
  40. package/dist/lib/inspect.js +190 -0
  41. package/dist/lib/inspect.js.map +1 -0
  42. package/dist/lib/install.d.ts +10 -4
  43. package/dist/lib/install.d.ts.map +1 -1
  44. package/dist/lib/install.js +74 -71
  45. package/dist/lib/install.js.map +1 -1
  46. package/dist/lib/neonctl.d.ts +32 -0
  47. package/dist/lib/neonctl.d.ts.map +1 -0
  48. package/dist/lib/neonctl.js +149 -0
  49. package/dist/lib/neonctl.js.map +1 -0
  50. package/dist/lib/phases/auth.d.ts +12 -0
  51. package/dist/lib/phases/auth.d.ts.map +1 -0
  52. package/dist/lib/phases/auth.js +188 -0
  53. package/dist/lib/phases/auth.js.map +1 -0
  54. package/dist/lib/phases/cleanup.d.ts +12 -0
  55. package/dist/lib/phases/cleanup.d.ts.map +1 -0
  56. package/dist/lib/phases/cleanup.js +29 -0
  57. package/dist/lib/phases/cleanup.js.map +1 -0
  58. package/dist/lib/phases/db.d.ts +17 -0
  59. package/dist/lib/phases/db.d.ts.map +1 -0
  60. package/dist/lib/phases/db.js +258 -0
  61. package/dist/lib/phases/db.js.map +1 -0
  62. package/dist/lib/phases/getting-started.d.ts +26 -0
  63. package/dist/lib/phases/getting-started.d.ts.map +1 -0
  64. package/dist/lib/phases/getting-started.js +195 -0
  65. package/dist/lib/phases/getting-started.js.map +1 -0
  66. package/dist/lib/phases/mcp.d.ts +15 -0
  67. package/dist/lib/phases/mcp.d.ts.map +1 -0
  68. package/dist/lib/phases/mcp.js +179 -0
  69. package/dist/lib/phases/mcp.js.map +1 -0
  70. package/dist/lib/phases/migrations.d.ts +14 -0
  71. package/dist/lib/phases/migrations.d.ts.map +1 -0
  72. package/dist/lib/phases/migrations.js +239 -0
  73. package/dist/lib/phases/migrations.js.map +1 -0
  74. package/dist/lib/phases/neon-auth.d.ts +13 -0
  75. package/dist/lib/phases/neon-auth.d.ts.map +1 -0
  76. package/dist/lib/phases/neon-auth.js +117 -0
  77. package/dist/lib/phases/neon-auth.js.map +1 -0
  78. package/dist/lib/phases/setup.d.ts +41 -0
  79. package/dist/lib/phases/setup.d.ts.map +1 -0
  80. package/dist/lib/phases/setup.js +689 -0
  81. package/dist/lib/phases/setup.js.map +1 -0
  82. package/dist/lib/phases/skills.d.ts +14 -0
  83. package/dist/lib/phases/skills.d.ts.map +1 -0
  84. package/dist/lib/phases/skills.js +80 -0
  85. package/dist/lib/phases/skills.js.map +1 -0
  86. package/dist/lib/phases/status.d.ts +10 -0
  87. package/dist/lib/phases/status.d.ts.map +1 -0
  88. package/dist/lib/phases/status.js +65 -0
  89. package/dist/lib/phases/status.js.map +1 -0
  90. package/dist/lib/resolve-context.d.ts +19 -0
  91. package/dist/lib/resolve-context.d.ts.map +1 -0
  92. package/dist/lib/resolve-context.js +112 -0
  93. package/dist/lib/resolve-context.js.map +1 -0
  94. package/dist/lib/route-command.d.ts +8 -0
  95. package/dist/lib/route-command.d.ts.map +1 -0
  96. package/dist/lib/route-command.js +195 -0
  97. package/dist/lib/route-command.js.map +1 -0
  98. package/dist/lib/skills.d.ts +21 -4
  99. package/dist/lib/skills.d.ts.map +1 -1
  100. package/dist/lib/skills.js +129 -22
  101. package/dist/lib/skills.js.map +1 -1
  102. package/dist/lib/types.d.ts +146 -13
  103. package/dist/lib/types.d.ts.map +1 -1
  104. package/dist/lib/types.js +1 -1
  105. package/dist/lib/vsix.d.ts +15 -0
  106. package/dist/lib/vsix.d.ts.map +1 -0
  107. package/dist/lib/vsix.js +91 -0
  108. package/dist/lib/vsix.js.map +1 -0
  109. package/dist/v2.d.ts +31 -0
  110. package/dist/v2.d.ts.map +1 -0
  111. package/dist/v2.js +147 -0
  112. package/dist/v2.js.map +1 -0
  113. package/package.json +9 -4
  114. package/dist/lib/mcp-config.d.ts +0 -24
  115. package/dist/lib/mcp-config.d.ts.map +0 -1
  116. package/dist/lib/mcp-config.js +0 -51
  117. package/dist/lib/mcp-config.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","names":[],"sources":["../../src/lib/install.ts"],"sourcesContent":["import { confirm, isCancel, log, spinner } from \"@clack/prompts\";\nimport { createApiKeyFromNeonctl, ensureNeonctlAuth } from \"./auth.js\";\nimport {\n\tconfigureExtension,\n\tinstallExtension,\n\tusesExtension,\n\twaitForExtensionInstalled,\n} from \"./extension.js\";\nimport { getMCPConfig, writeMCPConfig } from \"./mcp-config.js\";\nimport type { Editor, InstallStatus } from \"./types.js\";\n\n/**\n * Checks if an editor needs MCP configuration\n * Returns true if configuration is needed, false otherwise\n */\nasync function shouldConfigureMCP(\n\thomeDir: string,\n\tworkspaceDir: string,\n\teditor: Editor,\n): Promise<boolean> {\n\tconst { config } = getMCPConfig(homeDir, workspaceDir, editor);\n\n\t// Check if already configured\n\tconst serverKey = editor === \"VS Code\" ? config.servers : config.mcpServers;\n\tconst alreadyConfigured = Boolean(serverKey?.Neon);\n\n\tif (alreadyConfigured) {\n\t\tconst response = await confirm({\n\t\t\tmessage: `Neon MCP Server is already configured for ${editor}. Would you like to reconfigure it? (Y/n)`,\n\t\t\tinitialValue: true,\n\t\t});\n\n\t\tif (isCancel(response)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst shouldReconfigure = response as boolean;\n\n\t\tif (!shouldReconfigure) {\n\t\t\tlog.info(\n\t\t\t\t`Keeping existing MCP server configuration for ${editor}.`,\n\t\t\t);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Installs Neon's MCP Server for specific editors\n */\nasync function installMCPServerForEditor(\n\thomeDir: string,\n\tworkspaceDir: string,\n\teditor: Editor,\n\tapiKey: string,\n): Promise<InstallStatus> {\n\tconst { config, configPath } = getMCPConfig(homeDir, workspaceDir, editor);\n\n\t// Configure Neon MCP Server\n\t// Using remote MCP server with API key authentication\n\t// Ref: https://neon.com/docs/ai/neon-mcp-server#api-key-based-authentication\n\tconst neonServerConfig = {\n\t\ttype: \"http\",\n\t\turl: \"https://mcp.neon.tech/mcp\",\n\t\theaders: {\n\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t},\n\t};\n\n\t// Claude CLI uses \"mcpServers\" key\n\tif (!config.mcpServers) {\n\t\tconfig.mcpServers = {};\n\t}\n\tconfig.mcpServers.Neon = neonServerConfig;\n\n\t// Write configuration\n\ttry {\n\t\twriteMCPConfig(configPath, config);\n\t\treturn \"success\";\n\t} catch (error) {\n\t\tlog.error(\n\t\t\t`Failed to write configuration for ${editor}: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t);\n\t\treturn \"failed\";\n\t}\n}\n\n/**\n * Installs Neon's Local Connect extension or MCP Server for specific editors\n */\nexport async function installNeon(\n\thomeDir: string,\n\tworkspaceDir: string,\n\tselectedEditors: Editor[],\n): Promise<Map<Editor, InstallStatus>> {\n\tconst results = new Map<Editor, InstallStatus>();\n\n\tconst extensionEditors = selectedEditors.filter(usesExtension);\n\tconst mcpEditors = selectedEditors.filter((e) => !usesExtension(e));\n\n\t// Check which MCP editors need configuration\n\tconst mcpEditorsToConfigureMap = new Map<Editor, boolean>();\n\tfor (const editor of mcpEditors) {\n\t\tconst needsConfig = await shouldConfigureMCP(\n\t\t\thomeDir,\n\t\t\tworkspaceDir,\n\t\t\teditor,\n\t\t);\n\t\tmcpEditorsToConfigureMap.set(editor, needsConfig);\n\n\t\tif (!needsConfig) {\n\t\t\tresults.set(editor, \"success\");\n\t\t}\n\t}\n\n\tconst mcpToConfigure = mcpEditors.filter(\n\t\t(editor) => mcpEditorsToConfigureMap.get(editor) === true,\n\t);\n\n\t// Extension editors always get processed (silent installation)\n\tconst extensionsToConfigure = extensionEditors;\n\n\t// If nothing needs configuration, return early\n\tif (extensionsToConfigure.length === 0 && mcpToConfigure.length === 0) {\n\t\treturn results;\n\t}\n\n\tconst authSpinner = spinner();\n\tauthSpinner.start(\"Authenticating...\");\n\n\tconst authSuccess = await ensureNeonctlAuth();\n\n\tif (!authSuccess) {\n\t\tauthSpinner.stop(\"Authentication failed\");\n\t\t// Mark all editors that need configuration as failed\n\t\tfor (const editor of [...extensionsToConfigure, ...mcpToConfigure]) {\n\t\t\tresults.set(editor, \"failed\");\n\t\t}\n\t\treturn results;\n\t}\n\n\tauthSpinner.stop(\"Authentication successful ✓\");\n\n\t// Create API key using the OAuth token\n\tconst apiKey = await createApiKeyFromNeonctl();\n\n\tif (!apiKey) {\n\t\tlog.error(\"Could not create API key after authentication.\");\n\t\tlog.info(\n\t\t\t\"You can manually create one at: https://console.neon.tech/app/settings/api-keys\",\n\t\t);\n\t\t// Mark all editors that need configuration as failed\n\t\tfor (const editor of [...extensionsToConfigure, ...mcpToConfigure]) {\n\t\t\tresults.set(editor, \"failed\");\n\t\t}\n\t\treturn results;\n\t}\n\n\t// Install and configure extension for Cursor/VS Code (silently)\n\tfor (const editor of extensionsToConfigure) {\n\t\tconst installSuccess = await installExtension(editor);\n\n\t\tif (!installSuccess) {\n\t\t\tresults.set(editor, \"failed\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst isReady = await waitForExtensionInstalled(editor);\n\t\tif (!isReady) {\n\t\t\t// Extension install command succeeded but extension didn't appear in list\n\t\t\tresults.set(editor, \"failed\");\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Configure the extension with the API key\n\t\tconst configSuccess = await configureExtension(editor, apiKey);\n\n\t\tif (configSuccess) {\n\t\t\tresults.set(editor, \"success\");\n\t\t} else {\n\t\t\t// Extension installed but auth failed but user can manually configure later\n\t\t\tresults.set(editor, \"success\");\n\t\t}\n\t}\n\n\tfor (const editor of mcpToConfigure) {\n\t\tconst status = await installMCPServerForEditor(\n\t\t\thomeDir,\n\t\t\tworkspaceDir,\n\t\t\teditor,\n\t\t\tapiKey,\n\t\t);\n\t\tresults.set(editor, status);\n\t}\n\n\treturn results;\n}\n"],"mappings":";;;;;;;;;;AAeA,eAAe,mBACd,SACA,cACA,QACmB;CACnB,MAAM,EAAE,WAAW,aAAa,SAAS,cAAc,OAAO;CAG9D,MAAM,YAAY,WAAW,YAAY,OAAO,UAAU,OAAO;AAGjE,KAF0B,QAAQ,WAAW,KAAK,EAE3B;EACtB,MAAM,WAAW,MAAM,QAAQ;GAC9B,SAAS,6CAA6C,OAAO;GAC7D,cAAc;GACd,CAAC;AAEF,MAAI,SAAS,SAAS,CACrB,QAAO;AAKR,MAAI,CAFsB,UAEF;AACvB,OAAI,KACH,iDAAiD,OAAO,GACxD;AACD,UAAO;;;AAIT,QAAO;;;;;AAMR,eAAe,0BACd,SACA,cACA,QACA,QACyB;CACzB,MAAM,EAAE,QAAQ,eAAe,aAAa,SAAS,cAAc,OAAO;CAK1E,MAAM,mBAAmB;EACxB,MAAM;EACN,KAAK;EACL,SAAS,EACR,eAAe,UAAU,UACzB;EACD;AAGD,KAAI,CAAC,OAAO,WACX,QAAO,aAAa,EAAE;AAEvB,QAAO,WAAW,OAAO;AAGzB,KAAI;AACH,iBAAe,YAAY,OAAO;AAClC,SAAO;UACC,OAAO;AACf,MAAI,MACH,qCAAqC,OAAO,IAAI,iBAAiB,QAAQ,MAAM,UAAU,kBACzF;AACD,SAAO;;;;;;AAOT,eAAsB,YACrB,SACA,cACA,iBACsC;CACtC,MAAM,0BAAU,IAAI,KAA4B;CAEhD,MAAM,mBAAmB,gBAAgB,OAAO,cAAc;CAC9D,MAAM,aAAa,gBAAgB,QAAQ,MAAM,CAAC,cAAc,EAAE,CAAC;CAGnE,MAAM,2CAA2B,IAAI,KAAsB;AAC3D,MAAK,MAAM,UAAU,YAAY;EAChC,MAAM,cAAc,MAAM,mBACzB,SACA,cACA,OACA;AACD,2BAAyB,IAAI,QAAQ,YAAY;AAEjD,MAAI,CAAC,YACJ,SAAQ,IAAI,QAAQ,UAAU;;CAIhC,MAAM,iBAAiB,WAAW,QAChC,WAAW,yBAAyB,IAAI,OAAO,KAAK,KACrD;CAGD,MAAM,wBAAwB;AAG9B,KAAI,sBAAsB,WAAW,KAAK,eAAe,WAAW,EACnE,QAAO;CAGR,MAAM,cAAc,SAAS;AAC7B,aAAY,MAAM,oBAAoB;AAItC,KAAI,CAFgB,MAAM,mBAAmB,EAE3B;AACjB,cAAY,KAAK,wBAAwB;AAEzC,OAAK,MAAM,UAAU,CAAC,GAAG,uBAAuB,GAAG,eAAe,CACjE,SAAQ,IAAI,QAAQ,SAAS;AAE9B,SAAO;;AAGR,aAAY,KAAK,8BAA8B;CAG/C,MAAM,SAAS,MAAM,yBAAyB;AAE9C,KAAI,CAAC,QAAQ;AACZ,MAAI,MAAM,iDAAiD;AAC3D,MAAI,KACH,kFACA;AAED,OAAK,MAAM,UAAU,CAAC,GAAG,uBAAuB,GAAG,eAAe,CACjE,SAAQ,IAAI,QAAQ,SAAS;AAE9B,SAAO;;AAIR,MAAK,MAAM,UAAU,uBAAuB;AAG3C,MAAI,CAFmB,MAAM,iBAAiB,OAAO,EAEhC;AACpB,WAAQ,IAAI,QAAQ,SAAS;AAC7B;;AAID,MAAI,CADY,MAAM,0BAA0B,OAAO,EACzC;AAEb,WAAQ,IAAI,QAAQ,SAAS;AAC7B;;AAMD,MAFsB,MAAM,mBAAmB,QAAQ,OAAO,CAG7D,SAAQ,IAAI,QAAQ,UAAU;MAG9B,SAAQ,IAAI,QAAQ,UAAU;;AAIhC,MAAK,MAAM,UAAU,gBAAgB;EACpC,MAAM,SAAS,MAAM,0BACpB,SACA,cACA,QACA,OACA;AACD,UAAQ,IAAI,QAAQ,OAAO;;AAG5B,QAAO"}
1
+ {"version":3,"file":"install.js","names":[],"sources":["../../src/lib/install.ts"],"sourcesContent":["import { log, spinner } from \"@clack/prompts\";\nimport { execa } from \"execa\";\nimport { getAddMcpAgentId } from \"./agents.js\";\nimport {\n\ttype AuthOptions,\n\tcreateApiKeyFromNeonctl,\n\tensureNeonctlAuth,\n} from \"./auth.js\";\nimport {\n\tconfigureExtension,\n\tinstallExtension,\n\tusesExtension,\n\twaitForExtensionInstalled,\n} from \"./extension.js\";\nimport type { Editor, InstallStatus } from \"./types.js\";\n\nconst NEON_MCP_SERVER_URL = \"https://mcp.neon.tech/mcp\";\n\n/**\n * Installs Neon MCP Server for a single editor via the add-mcp CLI.\n * Uses API key authentication via the Authorization header.\n */\nasync function installMCPServerViaAddMcp(\n\teditor: Editor,\n\tapiKey: string,\n): Promise<void> {\n\tconst agentId = getAddMcpAgentId(editor);\n\n\tawait execa(\n\t\t\"npx\",\n\t\t[\n\t\t\t\"-y\",\n\t\t\t\"add-mcp\",\n\t\t\tNEON_MCP_SERVER_URL,\n\t\t\t\"--header\",\n\t\t\t`Authorization: Bearer ${apiKey}`,\n\t\t\t\"-g\",\n\t\t\t\"-n\",\n\t\t\t\"Neon\",\n\t\t\t\"-y\",\n\t\t\t\"-a\",\n\t\t\tagentId,\n\t\t],\n\t\t{\n\t\t\tstdio: \"pipe\",\n\t\t\ttimeout: 60000,\n\t\t},\n\t);\n}\n\nexport interface InstallNeonOptions {\n\tjson?: boolean;\n}\n\n/**\n * Installs Neon's Local Connect extension or MCP Server for specific editors.\n * Returns a map of editor → install status and whether auth succeeded.\n */\nexport async function installNeon(\n\tselectedEditors: Editor[],\n\toptions?: InstallNeonOptions,\n): Promise<{ results: Map<Editor, InstallStatus>; authSuccess: boolean }> {\n\tconst quiet = options?.json === true;\n\tconst authOptions: AuthOptions = { json: quiet };\n\tconst results = new Map<Editor, InstallStatus>();\n\n\tconst extensionEditors = selectedEditors.filter(usesExtension);\n\tconst mcpEditors = selectedEditors.filter((e) => !usesExtension(e));\n\n\tif (extensionEditors.length === 0 && mcpEditors.length === 0) {\n\t\treturn { results, authSuccess: false };\n\t}\n\n\tconst authSpinner = quiet ? null : spinner();\n\tauthSpinner?.start(\"Authenticating...\");\n\n\tconst authSuccess = await ensureNeonctlAuth(authOptions);\n\n\tif (!authSuccess) {\n\t\tauthSpinner?.stop(\"Authentication failed\");\n\t\tfor (const editor of selectedEditors) {\n\t\t\tresults.set(editor, \"failed\");\n\t\t}\n\t\treturn { results, authSuccess: false };\n\t}\n\n\tauthSpinner?.stop(\"Authentication successful ✓\");\n\n\tconst apiKey = await createApiKeyFromNeonctl(authOptions);\n\n\tif (!apiKey) {\n\t\tif (!quiet) {\n\t\t\tlog.error(\"Could not create API key after authentication.\");\n\t\t\tlog.info(\n\t\t\t\t\"You can manually create one at: https://console.neon.tech/app/settings/api-keys\",\n\t\t\t);\n\t\t}\n\t\tfor (const editor of selectedEditors) {\n\t\t\tresults.set(editor, \"failed\");\n\t\t}\n\t\treturn { results, authSuccess: true };\n\t}\n\n\tfor (const editor of extensionEditors) {\n\t\tconst installSuccess = await installExtension(editor);\n\n\t\tif (!installSuccess) {\n\t\t\tresults.set(editor, \"failed\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst isReady = await waitForExtensionInstalled(editor);\n\t\tif (!isReady) {\n\t\t\tresults.set(editor, \"failed\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst configSuccess = await configureExtension(editor, apiKey);\n\n\t\tif (configSuccess) {\n\t\t\tresults.set(editor, \"success\");\n\t\t} else {\n\t\t\tresults.set(editor, \"failed\");\n\t\t}\n\t}\n\n\tif (mcpEditors.length > 0) {\n\t\tconst mcpSpinner = quiet ? null : spinner();\n\t\tmcpSpinner?.start(\"Installing and configuring Neon MCP Server...\");\n\n\t\tlet mcpSuccessCount = 0;\n\t\tfor (const editor of mcpEditors) {\n\t\t\ttry {\n\t\t\t\tawait installMCPServerViaAddMcp(editor, apiKey);\n\t\t\t\tresults.set(editor, \"success\");\n\t\t\t\tmcpSuccessCount++;\n\t\t\t} catch (err) {\n\t\t\t\tresults.set(editor, \"failed\");\n\t\t\t\tif (\n\t\t\t\t\t!quiet &&\n\t\t\t\t\terr &&\n\t\t\t\t\ttypeof err === \"object\" &&\n\t\t\t\t\t\"stderr\" in err &&\n\t\t\t\t\terr.stderr\n\t\t\t\t) {\n\t\t\t\t\tlog.error(\n\t\t\t\t\t\tString(err.stderr).trim() ||\n\t\t\t\t\t\t\t\"failed to install MCP server via add-mcp\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tmcpSpinner?.stop(\n\t\t\tmcpSuccessCount > 0\n\t\t\t\t? \"Neon MCP Server configuration complete ✓\"\n\t\t\t\t: \"Failed to configure Neon MCP Server\",\n\t\t);\n\t}\n\n\treturn { results, authSuccess: true };\n}\n"],"mappings":";;;;;;AAgBA,MAAM,sBAAsB;;;;;AAM5B,eAAe,0BACd,QACA,QACgB;CAChB,MAAM,UAAU,iBAAiB,MAAM;CAEvC,MAAM,MACL,OACA;EACC;EACA;EACA;EACA;EACA,yBAAyB;EACzB;EACA;EACA;EACA;EACA;EACA;CACD,GACA;EACC,OAAO;EACP,SAAS;CACV,CACD;AACD;;;;;AAUA,eAAsB,YACrB,iBACA,SACyE;CACzE,MAAM,QAAQ,SAAS,SAAS;CAChC,MAAM,cAA2B,EAAE,MAAM,MAAM;CAC/C,MAAM,0BAAU,IAAI,IAA2B;CAE/C,MAAM,mBAAmB,gBAAgB,OAAO,aAAa;CAC7D,MAAM,aAAa,gBAAgB,QAAQ,MAAM,CAAC,cAAc,CAAC,CAAC;CAElE,IAAI,iBAAiB,WAAW,KAAK,WAAW,WAAW,GAC1D,OAAO;EAAE;EAAS,aAAa;CAAM;CAGtC,MAAM,cAAc,QAAQ,OAAO,QAAQ;CAC3C,aAAa,MAAM,mBAAmB;CAItC,IAAI,CAAC,MAFqB,kBAAkB,WAAW,GAErC;EACjB,aAAa,KAAK,uBAAuB;EACzC,KAAK,MAAM,UAAU,iBACpB,QAAQ,IAAI,QAAQ,QAAQ;EAE7B,OAAO;GAAE;GAAS,aAAa;EAAM;CACtC;CAEA,aAAa,KAAK,6BAA6B;CAE/C,MAAM,SAAS,MAAM,wBAAwB,WAAW;CAExD,IAAI,CAAC,QAAQ;EACZ,IAAI,CAAC,OAAO;GACX,IAAI,MAAM,gDAAgD;GAC1D,IAAI,KACH,iFACD;EACD;EACA,KAAK,MAAM,UAAU,iBACpB,QAAQ,IAAI,QAAQ,QAAQ;EAE7B,OAAO;GAAE;GAAS,aAAa;EAAK;CACrC;CAEA,KAAK,MAAM,UAAU,kBAAkB;EAGtC,IAAI,CAAC,MAFwB,iBAAiB,MAAM,GAE/B;GACpB,QAAQ,IAAI,QAAQ,QAAQ;GAC5B;EACD;EAGA,IAAI,CAAC,MADiB,0BAA0B,MAAM,GACxC;GACb,QAAQ,IAAI,QAAQ,QAAQ;GAC5B;EACD;EAIA,IAAI,MAFwB,mBAAmB,QAAQ,MAAM,GAG5D,QAAQ,IAAI,QAAQ,SAAS;OAE7B,QAAQ,IAAI,QAAQ,QAAQ;CAE9B;CAEA,IAAI,WAAW,SAAS,GAAG;EAC1B,MAAM,aAAa,QAAQ,OAAO,QAAQ;EAC1C,YAAY,MAAM,+CAA+C;EAEjE,IAAI,kBAAkB;EACtB,KAAK,MAAM,UAAU,YACpB,IAAI;GACH,MAAM,0BAA0B,QAAQ,MAAM;GAC9C,QAAQ,IAAI,QAAQ,SAAS;GAC7B;EACD,SAAS,KAAK;GACb,QAAQ,IAAI,QAAQ,QAAQ;GAC5B,IACC,CAAC,SACD,OACA,OAAO,QAAQ,YACf,YAAY,OACZ,IAAI,QAEJ,IAAI,MACH,OAAO,IAAI,MAAM,CAAC,CAAC,KAAK,KACvB,0CACF;EAEF;EAGD,YAAY,KACX,kBAAkB,IACf,6CACA,qCACJ;CACD;CAEA,OAAO;EAAE;EAAS,aAAa;CAAK;AACrC"}
@@ -0,0 +1,32 @@
1
+ //#region src/lib/neonctl.d.ts
2
+ /**
3
+ * Detects which package manager was used to invoke the current process.
4
+ * Reads the `npm_config_user_agent` env var set by npm/pnpm/yarn/bun when
5
+ * they spawn child processes (including via `npx`, `pnpx`, `bunx`, etc.).
6
+ *
7
+ * Falls back to "npm" if detection fails.
8
+ */
9
+ declare function detectPackageManager(): "npm" | "pnpm" | "yarn" | "bun";
10
+ interface NeonctlStatus {
11
+ installed: boolean;
12
+ currentVersion: string | null;
13
+ latestVersion: string | null;
14
+ needsUpdate: boolean;
15
+ }
16
+ /**
17
+ * Checks whether the neonctl CLI is globally installed and whether it's up to date.
18
+ */
19
+ declare function checkNeonctl(): Promise<NeonctlStatus>;
20
+ interface EnsureNeonctlResult {
21
+ status: "already_current" | "installed" | "updated" | "failed";
22
+ version?: string;
23
+ error?: string;
24
+ }
25
+ /**
26
+ * Ensures neonctl is globally installed and up to date.
27
+ * Uses the same package manager that invoked the init command.
28
+ */
29
+ declare function ensureNeonctl(): Promise<EnsureNeonctlResult>;
30
+ //#endregion
31
+ export { EnsureNeonctlResult, checkNeonctl, detectPackageManager, ensureNeonctl };
32
+ //# sourceMappingURL=neonctl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"neonctl.d.ts","names":[],"sources":["../../src/lib/neonctl.ts"],"mappings":";;AASA;AAQC;AAkDD;;;;AAA6C,iBA1D7B,oBAAA,CAAA,CA0D6B,EAAA,KAAA,GAAA,MAAA,GAAA,MAAA,GAAA,KAAA;AAiD7C,UA9EU,aAAA,CA8EO;EAUK,SAAA,EAAA,OAAa;EAAA,cAAA,EAAA,MAAA,GAAA,IAAA;eAAY,EAAA,MAAA,GAAA,IAAA;aAAR,EAAA,OAAA;AAAO;;;;iBA3DxB,YAAA,CAAA,GAAgB,QAAQ;UAiD7B,mBAAA;;;;;;;;;iBAUK,aAAA,CAAA,GAAiB,QAAQ"}
@@ -0,0 +1,149 @@
1
+ import { execa } from "execa";
2
+ //#region src/lib/neonctl.ts
3
+ /**
4
+ * Detects which package manager was used to invoke the current process.
5
+ * Reads the `npm_config_user_agent` env var set by npm/pnpm/yarn/bun when
6
+ * they spawn child processes (including via `npx`, `pnpx`, `bunx`, etc.).
7
+ *
8
+ * Falls back to "npm" if detection fails.
9
+ */
10
+ function detectPackageManager() {
11
+ const ua = process.env.npm_config_user_agent;
12
+ if (ua) {
13
+ if (ua.startsWith("pnpm/")) return "pnpm";
14
+ if (ua.startsWith("yarn/")) return "yarn";
15
+ if (ua.startsWith("bun/")) return "bun";
16
+ }
17
+ return "npm";
18
+ }
19
+ /**
20
+ * Returns the global install command for a given package manager.
21
+ */
22
+ function globalInstallArgs(pm, pkg) {
23
+ switch (pm) {
24
+ case "pnpm": return {
25
+ command: "pnpm",
26
+ args: [
27
+ "add",
28
+ "-g",
29
+ pkg
30
+ ]
31
+ };
32
+ case "yarn": return {
33
+ command: "yarn",
34
+ args: [
35
+ "global",
36
+ "add",
37
+ pkg
38
+ ]
39
+ };
40
+ case "bun": return {
41
+ command: "bun",
42
+ args: [
43
+ "add",
44
+ "-g",
45
+ pkg
46
+ ]
47
+ };
48
+ default: return {
49
+ command: "npm",
50
+ args: [
51
+ "install",
52
+ "-g",
53
+ pkg
54
+ ]
55
+ };
56
+ }
57
+ }
58
+ /**
59
+ * Gets the currently available neonctl version.
60
+ * Tries the global binary first, then falls back to npx.
61
+ */
62
+ async function getNeonctlVersion() {
63
+ try {
64
+ const match = (await execa("neonctl", ["--version"], {
65
+ stdio: "pipe",
66
+ timeout: 5e3
67
+ })).stdout.trim().match(/(\d+\.\d+\.\d+)/);
68
+ if (match) return match[1];
69
+ } catch {}
70
+ return null;
71
+ }
72
+ /**
73
+ * Checks whether the neonctl CLI is globally installed and whether it's up to date.
74
+ */
75
+ async function checkNeonctl() {
76
+ const currentVersion = await getNeonctlVersion();
77
+ if (!currentVersion) return {
78
+ installed: false,
79
+ currentVersion: null,
80
+ latestVersion: null,
81
+ needsUpdate: true
82
+ };
83
+ let latestVersion = null;
84
+ try {
85
+ latestVersion = (await execa("npm", [
86
+ "view",
87
+ "neonctl",
88
+ "version"
89
+ ], {
90
+ stdio: "pipe",
91
+ timeout: 1e4
92
+ })).stdout.trim();
93
+ } catch {
94
+ return {
95
+ installed: true,
96
+ currentVersion,
97
+ latestVersion: null,
98
+ needsUpdate: false
99
+ };
100
+ }
101
+ const needsUpdate = currentVersion !== null && latestVersion !== null && currentVersion !== latestVersion && isOlderVersion(currentVersion, latestVersion);
102
+ return {
103
+ installed: true,
104
+ currentVersion,
105
+ latestVersion,
106
+ needsUpdate
107
+ };
108
+ }
109
+ function isOlderVersion(current, latest) {
110
+ const c = current.split(".").map(Number);
111
+ const l = latest.split(".").map(Number);
112
+ for (let i = 0; i < 3; i++) {
113
+ if ((c[i] ?? 0) < (l[i] ?? 0)) return true;
114
+ if ((c[i] ?? 0) > (l[i] ?? 0)) return false;
115
+ }
116
+ return false;
117
+ }
118
+ /**
119
+ * Ensures neonctl is globally installed and up to date.
120
+ * Uses the same package manager that invoked the init command.
121
+ */
122
+ async function ensureNeonctl() {
123
+ const check = await checkNeonctl();
124
+ if (check.installed && !check.needsUpdate) return {
125
+ status: "already_current",
126
+ version: check.currentVersion ?? void 0
127
+ };
128
+ const { command, args } = globalInstallArgs(detectPackageManager(), "neonctl");
129
+ try {
130
+ await execa(command, args, {
131
+ stdio: "pipe",
132
+ timeout: 6e4
133
+ });
134
+ const version = await getNeonctlVersion();
135
+ return {
136
+ status: check.installed ? "updated" : "installed",
137
+ version: version ?? void 0
138
+ };
139
+ } catch (err) {
140
+ return {
141
+ status: "failed",
142
+ error: err instanceof Error ? err.message : "Unknown error"
143
+ };
144
+ }
145
+ }
146
+ //#endregion
147
+ export { checkNeonctl, detectPackageManager, ensureNeonctl };
148
+
149
+ //# sourceMappingURL=neonctl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"neonctl.js","names":[],"sources":["../../src/lib/neonctl.ts"],"sourcesContent":["import { execa } from \"execa\";\n\n/**\n * Detects which package manager was used to invoke the current process.\n * Reads the `npm_config_user_agent` env var set by npm/pnpm/yarn/bun when\n * they spawn child processes (including via `npx`, `pnpx`, `bunx`, etc.).\n *\n * Falls back to \"npm\" if detection fails.\n */\nexport function detectPackageManager(): \"npm\" | \"pnpm\" | \"yarn\" | \"bun\" {\n\tconst ua = process.env.npm_config_user_agent;\n\tif (ua) {\n\t\tif (ua.startsWith(\"pnpm/\")) return \"pnpm\";\n\t\tif (ua.startsWith(\"yarn/\")) return \"yarn\";\n\t\tif (ua.startsWith(\"bun/\")) return \"bun\";\n\t}\n\treturn \"npm\";\n}\n\n/**\n * Returns the global install command for a given package manager.\n */\nfunction globalInstallArgs(\n\tpm: \"npm\" | \"pnpm\" | \"yarn\" | \"bun\",\n\tpkg: string,\n): { command: string; args: string[] } {\n\tswitch (pm) {\n\t\tcase \"pnpm\":\n\t\t\treturn { command: \"pnpm\", args: [\"add\", \"-g\", pkg] };\n\t\tcase \"yarn\":\n\t\t\treturn { command: \"yarn\", args: [\"global\", \"add\", pkg] };\n\t\tcase \"bun\":\n\t\t\treturn { command: \"bun\", args: [\"add\", \"-g\", pkg] };\n\t\tdefault:\n\t\t\treturn { command: \"npm\", args: [\"install\", \"-g\", pkg] };\n\t}\n}\n\ninterface NeonctlStatus {\n\tinstalled: boolean;\n\tcurrentVersion: string | null;\n\tlatestVersion: string | null;\n\tneedsUpdate: boolean;\n}\n\n/**\n * Gets the currently available neonctl version.\n * Tries the global binary first, then falls back to npx.\n */\nasync function getNeonctlVersion(): Promise<string | null> {\n\t// Try global binary first (fast path)\n\ttry {\n\t\tconst result = await execa(\"neonctl\", [\"--version\"], {\n\t\t\tstdio: \"pipe\",\n\t\t\ttimeout: 5000,\n\t\t});\n\t\tconst match = result.stdout.trim().match(/(\\d+\\.\\d+\\.\\d+)/);\n\t\tif (match) return match[1];\n\t} catch {\n\t\t// Not globally installed — that's fine\n\t}\n\treturn null;\n}\n\n/**\n * Checks whether the neonctl CLI is globally installed and whether it's up to date.\n */\nexport async function checkNeonctl(): Promise<NeonctlStatus> {\n\tconst currentVersion = await getNeonctlVersion();\n\n\tif (!currentVersion) {\n\t\treturn {\n\t\t\tinstalled: false,\n\t\t\tcurrentVersion: null,\n\t\t\tlatestVersion: null,\n\t\t\tneedsUpdate: true,\n\t\t};\n\t}\n\n\t// Check latest version from npm registry\n\tlet latestVersion: string | null = null;\n\ttry {\n\t\tconst result = await execa(\"npm\", [\"view\", \"neonctl\", \"version\"], {\n\t\t\tstdio: \"pipe\",\n\t\t\ttimeout: 10000,\n\t\t});\n\t\tlatestVersion = result.stdout.trim();\n\t} catch {\n\t\t// Can't determine latest — assume current is fine\n\t\treturn {\n\t\t\tinstalled: true,\n\t\t\tcurrentVersion,\n\t\t\tlatestVersion: null,\n\t\t\tneedsUpdate: false,\n\t\t};\n\t}\n\n\tconst needsUpdate =\n\t\tcurrentVersion !== null &&\n\t\tlatestVersion !== null &&\n\t\tcurrentVersion !== latestVersion &&\n\t\tisOlderVersion(currentVersion, latestVersion);\n\n\treturn { installed: true, currentVersion, latestVersion, needsUpdate };\n}\n\nfunction isOlderVersion(current: string, latest: string): boolean {\n\tconst c = current.split(\".\").map(Number);\n\tconst l = latest.split(\".\").map(Number);\n\tfor (let i = 0; i < 3; i++) {\n\t\tif ((c[i] ?? 0) < (l[i] ?? 0)) return true;\n\t\tif ((c[i] ?? 0) > (l[i] ?? 0)) return false;\n\t}\n\treturn false;\n}\n\nexport interface EnsureNeonctlResult {\n\tstatus: \"already_current\" | \"installed\" | \"updated\" | \"failed\";\n\tversion?: string;\n\terror?: string;\n}\n\n/**\n * Ensures neonctl is globally installed and up to date.\n * Uses the same package manager that invoked the init command.\n */\nexport async function ensureNeonctl(): Promise<EnsureNeonctlResult> {\n\tconst check = await checkNeonctl();\n\n\tif (check.installed && !check.needsUpdate) {\n\t\treturn {\n\t\t\tstatus: \"already_current\",\n\t\t\tversion: check.currentVersion ?? undefined,\n\t\t};\n\t}\n\n\tconst pm = detectPackageManager();\n\tconst { command, args } = globalInstallArgs(pm, \"neonctl\");\n\n\ttry {\n\t\tawait execa(command, args, { stdio: \"pipe\", timeout: 60000 });\n\n\t\t// Verify installation\n\t\tconst version = await getNeonctlVersion();\n\t\treturn {\n\t\t\tstatus: check.installed ? \"updated\" : \"installed\",\n\t\t\tversion: version ?? undefined,\n\t\t};\n\t} catch (err) {\n\t\treturn {\n\t\t\tstatus: \"failed\",\n\t\t\terror: err instanceof Error ? err.message : \"Unknown error\",\n\t\t};\n\t}\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,uBAAwD;CACvE,MAAM,KAAK,QAAQ,IAAI;CACvB,IAAI,IAAI;EACP,IAAI,GAAG,WAAW,OAAO,GAAG,OAAO;EACnC,IAAI,GAAG,WAAW,OAAO,GAAG,OAAO;EACnC,IAAI,GAAG,WAAW,MAAM,GAAG,OAAO;CACnC;CACA,OAAO;AACR;;;;AAKA,SAAS,kBACR,IACA,KACsC;CACtC,QAAQ,IAAR;EACC,KAAK,QACJ,OAAO;GAAE,SAAS;GAAQ,MAAM;IAAC;IAAO;IAAM;GAAG;EAAE;EACpD,KAAK,QACJ,OAAO;GAAE,SAAS;GAAQ,MAAM;IAAC;IAAU;IAAO;GAAG;EAAE;EACxD,KAAK,OACJ,OAAO;GAAE,SAAS;GAAO,MAAM;IAAC;IAAO;IAAM;GAAG;EAAE;EACnD,SACC,OAAO;GAAE,SAAS;GAAO,MAAM;IAAC;IAAW;IAAM;GAAG;EAAE;CACxD;AACD;;;;;AAaA,eAAe,oBAA4C;CAE1D,IAAI;EAKH,MAAM,SAAQ,MAJO,MAAM,WAAW,CAAC,WAAW,GAAG;GACpD,OAAO;GACP,SAAS;EACV,CAAC,EAAA,CACoB,OAAO,KAAK,CAAC,CAAC,MAAM,iBAAiB;EAC1D,IAAI,OAAO,OAAO,MAAM;CACzB,QAAQ,CAER;CACA,OAAO;AACR;;;;AAKA,eAAsB,eAAuC;CAC5D,MAAM,iBAAiB,MAAM,kBAAkB;CAE/C,IAAI,CAAC,gBACJ,OAAO;EACN,WAAW;EACX,gBAAgB;EAChB,eAAe;EACf,aAAa;CACd;CAID,IAAI,gBAA+B;CACnC,IAAI;EAKH,iBAAgB,MAJK,MAAM,OAAO;GAAC;GAAQ;GAAW;EAAS,GAAG;GACjE,OAAO;GACP,SAAS;EACV,CAAC,EAAA,CACsB,OAAO,KAAK;CACpC,QAAQ;EAEP,OAAO;GACN,WAAW;GACX;GACA,eAAe;GACf,aAAa;EACd;CACD;CAEA,MAAM,cACL,mBAAmB,QACnB,kBAAkB,QAClB,mBAAmB,iBACnB,eAAe,gBAAgB,aAAa;CAE7C,OAAO;EAAE,WAAW;EAAM;EAAgB;EAAe;CAAY;AACtE;AAEA,SAAS,eAAe,SAAiB,QAAyB;CACjE,MAAM,IAAI,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM;CACvC,MAAM,IAAI,OAAO,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM;CACtC,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC3B,KAAK,EAAE,MAAM,MAAM,EAAE,MAAM,IAAI,OAAO;EACtC,KAAK,EAAE,MAAM,MAAM,EAAE,MAAM,IAAI,OAAO;CACvC;CACA,OAAO;AACR;;;;;AAYA,eAAsB,gBAA8C;CACnE,MAAM,QAAQ,MAAM,aAAa;CAEjC,IAAI,MAAM,aAAa,CAAC,MAAM,aAC7B,OAAO;EACN,QAAQ;EACR,SAAS,MAAM,kBAAkB,KAAA;CAClC;CAID,MAAM,EAAE,SAAS,SAAS,kBADf,qBACkC,GAAG,SAAS;CAEzD,IAAI;EACH,MAAM,MAAM,SAAS,MAAM;GAAE,OAAO;GAAQ,SAAS;EAAM,CAAC;EAG5D,MAAM,UAAU,MAAM,kBAAkB;EACxC,OAAO;GACN,QAAQ,MAAM,YAAY,YAAY;GACtC,SAAS,WAAW,KAAA;EACrB;CACD,SAAS,KAAK;EACb,OAAO;GACN,QAAQ;GACR,OAAO,eAAe,QAAQ,IAAI,UAAU;EAC7C;CACD;AACD"}
@@ -0,0 +1,12 @@
1
+ import { PhaseResponse } from "../types.js";
2
+
3
+ //#region src/lib/phases/auth.d.ts
4
+ interface AuthPhaseOptions {
5
+ agent?: string;
6
+ method?: "existing" | "new";
7
+ verify?: boolean;
8
+ }
9
+ declare function handleAuthPhase(options: AuthPhaseOptions): Promise<PhaseResponse>;
10
+ //#endregion
11
+ export { AuthPhaseOptions, handleAuthPhase };
12
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","names":[],"sources":["../../../src/lib/phases/auth.ts"],"mappings":";;;UASiB,gBAAA;;EAAA,MAAA,CAAA,EAAA,UAAgB,GAAA,KAAA;EAMX,MAAA,CAAA,EAAA,OAAA;;AACZ,iBADY,eAAA,CACZ,OAAA,EAAA,gBAAA,CAAA,EACP,OADO,CACC,aADD,CAAA"}
@@ -0,0 +1,188 @@
1
+ import { isAuthenticated } from "../auth.js";
2
+ //#region src/lib/phases/auth.ts
3
+ const SIGNUP_COMMANDS = {
4
+ darwin: "open https://console.neon.tech/signup",
5
+ linux: "xdg-open https://console.neon.tech/signup",
6
+ win32: "start https://console.neon.tech/signup"
7
+ };
8
+ async function handleAuthPhase(options) {
9
+ const agentArgs = options.agent ? [
10
+ "--agent",
11
+ options.agent,
12
+ "--json"
13
+ ] : ["--json"];
14
+ if (options.verify) {
15
+ if (await isAuthenticated()) return {
16
+ phase: "auth",
17
+ status: "verified",
18
+ nextAction: {
19
+ type: "run_neon_init",
20
+ args: agentArgs
21
+ }
22
+ };
23
+ return {
24
+ phase: "auth",
25
+ status: "not_authenticated",
26
+ nextAction: {
27
+ type: "run_neon_init",
28
+ args: ["auth", "--json"]
29
+ }
30
+ };
31
+ }
32
+ if (await isAuthenticated()) return {
33
+ phase: "auth",
34
+ status: "verified",
35
+ nextAction: {
36
+ type: "run_neon_init",
37
+ args: agentArgs
38
+ }
39
+ };
40
+ if (options.method === "new") return {
41
+ phase: "auth",
42
+ status: "in_progress",
43
+ nextAction: {
44
+ type: "agent_action",
45
+ steps: [{
46
+ id: "open_signup",
47
+ description: "Open the Neon sign-up page in the user's browser",
48
+ command: SIGNUP_COMMANDS[process.platform] ?? SIGNUP_COMMANDS.linux
49
+ }, {
50
+ id: "wait_for_signup",
51
+ description: "Tell the user: 'I've opened the Neon sign-up page. Create your account and verify your email, then let me know when you're ready.'"
52
+ }],
53
+ onComplete: {
54
+ type: "run_neon_init",
55
+ args: [
56
+ "auth",
57
+ "--json",
58
+ "--method",
59
+ "existing"
60
+ ]
61
+ }
62
+ }
63
+ };
64
+ if (options.method === "existing") return {
65
+ phase: "auth",
66
+ status: "in_progress",
67
+ nextAction: {
68
+ type: "run_command",
69
+ command: "CI= npx -y neonctl auth",
70
+ description: "This will open your browser for Neon OAuth sign-in.",
71
+ timeout: 12e4,
72
+ onSuccess: {
73
+ type: "run_neon_init",
74
+ args: [
75
+ "auth",
76
+ "--json",
77
+ "--verify"
78
+ ]
79
+ },
80
+ onFailure: {
81
+ "2": {
82
+ type: "ask_user",
83
+ question: "The sign-in timed out. Did you complete the sign-in in your browser?",
84
+ options: ["yes_retry", "need_help"],
85
+ responseMapping: {
86
+ yes_retry: { args: [
87
+ "auth",
88
+ "--json",
89
+ "--method",
90
+ "existing"
91
+ ] },
92
+ need_help: { args: [
93
+ "auth",
94
+ "--json",
95
+ "--method",
96
+ "new"
97
+ ] }
98
+ }
99
+ },
100
+ other: {
101
+ type: "run_neon_init",
102
+ args: ["auth", "--json"]
103
+ }
104
+ }
105
+ }
106
+ };
107
+ return {
108
+ phase: "auth",
109
+ status: "required",
110
+ nextAction: {
111
+ type: "ask_user",
112
+ question: "Do you have an existing Neon account, or do you need to create one?",
113
+ options: [{
114
+ value: "existing_account",
115
+ label: "I have an existing Neon account"
116
+ }, {
117
+ value: "new_account",
118
+ label: "I need to create a new account"
119
+ }],
120
+ context: "Neon is a serverless Postgres provider. A free account is required to continue.",
121
+ responseMapping: {
122
+ existing_account: { action: {
123
+ type: "run_command",
124
+ command: "CI= npx -y neonctl auth",
125
+ description: "This will open your browser for Neon OAuth sign-in.",
126
+ timeout: 12e4,
127
+ onSuccess: {
128
+ type: "run_neon_init",
129
+ args: [
130
+ "auth",
131
+ "--json",
132
+ "--verify"
133
+ ]
134
+ },
135
+ onFailure: {
136
+ "2": {
137
+ type: "ask_user",
138
+ question: "The sign-in timed out. Did you complete the sign-in in your browser?",
139
+ options: ["yes_retry", "need_help"],
140
+ responseMapping: {
141
+ yes_retry: { args: [
142
+ "auth",
143
+ "--json",
144
+ "--method",
145
+ "existing"
146
+ ] },
147
+ need_help: { args: [
148
+ "auth",
149
+ "--json",
150
+ "--method",
151
+ "new"
152
+ ] }
153
+ }
154
+ },
155
+ other: {
156
+ type: "run_neon_init",
157
+ args: ["auth", "--json"]
158
+ }
159
+ }
160
+ } },
161
+ new_account: { action: {
162
+ type: "agent_action",
163
+ steps: [{
164
+ id: "open_signup",
165
+ description: "Open the Neon sign-up page in the user's browser",
166
+ command: SIGNUP_COMMANDS[process.platform] ?? SIGNUP_COMMANDS.linux
167
+ }, {
168
+ id: "wait_for_signup",
169
+ description: "Tell the user: 'I've opened the Neon sign-up page. Create your account and verify your email, then let me know when you're ready.'"
170
+ }],
171
+ onComplete: {
172
+ type: "run_neon_init",
173
+ args: [
174
+ "auth",
175
+ "--json",
176
+ "--method",
177
+ "existing"
178
+ ]
179
+ }
180
+ } }
181
+ }
182
+ }
183
+ };
184
+ }
185
+ //#endregion
186
+ export { handleAuthPhase };
187
+
188
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","names":[],"sources":["../../../src/lib/phases/auth.ts"],"sourcesContent":["import { isAuthenticated } from \"../auth.js\";\nimport type { PhaseResponse } from \"../types.js\";\n\nconst SIGNUP_COMMANDS: Record<string, string> = {\n\tdarwin: \"open https://console.neon.tech/signup\",\n\tlinux: \"xdg-open https://console.neon.tech/signup\",\n\twin32: \"start https://console.neon.tech/signup\",\n};\n\nexport interface AuthPhaseOptions {\n\tagent?: string;\n\tmethod?: \"existing\" | \"new\";\n\tverify?: boolean;\n}\n\nexport async function handleAuthPhase(\n\toptions: AuthPhaseOptions,\n): Promise<PhaseResponse> {\n\tconst agentArgs = options.agent\n\t\t? [\"--agent\", options.agent, \"--json\"]\n\t\t: [\"--json\"];\n\n\t// --verify: just check if credentials exist\n\tif (options.verify) {\n\t\tconst authed = await isAuthenticated();\n\t\tif (authed) {\n\t\t\t// Continue the flow immediately — don't use \"complete\" which\n\t\t\t// causes agents to stop and get distracted by neonctl output.\n\t\t\treturn {\n\t\t\t\tphase: \"auth\",\n\t\t\t\tstatus: \"verified\",\n\t\t\t\tnextAction: {\n\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\targs: agentArgs,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tphase: \"auth\",\n\t\t\tstatus: \"not_authenticated\",\n\t\t\tnextAction: {\n\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\targs: [\"auth\", \"--json\"],\n\t\t\t},\n\t\t};\n\t}\n\n\t// Check if already authenticated\n\tconst authed = await isAuthenticated();\n\tif (authed) {\n\t\treturn {\n\t\t\tphase: \"auth\",\n\t\t\tstatus: \"verified\",\n\t\t\tnextAction: {\n\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\targs: agentArgs,\n\t\t\t},\n\t\t};\n\t}\n\n\t// --method new: guide through signup\n\tif (options.method === \"new\") {\n\t\tconst openCmd =\n\t\t\tSIGNUP_COMMANDS[process.platform] ?? SIGNUP_COMMANDS.linux;\n\t\treturn {\n\t\t\tphase: \"auth\",\n\t\t\tstatus: \"in_progress\",\n\t\t\tnextAction: {\n\t\t\t\ttype: \"agent_action\",\n\t\t\t\tsteps: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"open_signup\",\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"Open the Neon sign-up page in the user's browser\",\n\t\t\t\t\t\tcommand: openCmd,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"wait_for_signup\",\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"Tell the user: 'I've opened the Neon sign-up page. Create your account and verify your email, then let me know when you're ready.'\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tonComplete: {\n\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\targs: [\"auth\", \"--json\", \"--method\", \"existing\"],\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\t// --method existing: run OAuth flow\n\tif (options.method === \"existing\") {\n\t\treturn {\n\t\t\tphase: \"auth\",\n\t\t\tstatus: \"in_progress\",\n\t\t\tnextAction: {\n\t\t\t\ttype: \"run_command\",\n\t\t\t\tcommand: \"CI= npx -y neonctl auth\",\n\t\t\t\tdescription:\n\t\t\t\t\t\"This will open your browser for Neon OAuth sign-in.\",\n\t\t\t\ttimeout: 120000,\n\t\t\t\tonSuccess: {\n\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\targs: [\"auth\", \"--json\", \"--verify\"],\n\t\t\t\t},\n\t\t\t\tonFailure: {\n\t\t\t\t\t\"2\": {\n\t\t\t\t\t\ttype: \"ask_user\",\n\t\t\t\t\t\tquestion:\n\t\t\t\t\t\t\t\"The sign-in timed out. Did you complete the sign-in in your browser?\",\n\t\t\t\t\t\toptions: [\"yes_retry\", \"need_help\"],\n\t\t\t\t\t\tresponseMapping: {\n\t\t\t\t\t\t\tyes_retry: {\n\t\t\t\t\t\t\t\targs: [\n\t\t\t\t\t\t\t\t\t\"auth\",\n\t\t\t\t\t\t\t\t\t\"--json\",\n\t\t\t\t\t\t\t\t\t\"--method\",\n\t\t\t\t\t\t\t\t\t\"existing\",\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tneed_help: {\n\t\t\t\t\t\t\t\targs: [\"auth\", \"--json\", \"--method\", \"new\"],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tother: {\n\t\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\t\targs: [\"auth\", \"--json\"],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\t// No method specified: ask the user, then launch OAuth directly for\n\t// \"existing account\" without an intermediate CLI round-trip.\n\tconst openCmd = SIGNUP_COMMANDS[process.platform] ?? SIGNUP_COMMANDS.linux;\n\treturn {\n\t\tphase: \"auth\",\n\t\tstatus: \"required\",\n\t\tnextAction: {\n\t\t\ttype: \"ask_user\",\n\t\t\tquestion:\n\t\t\t\t\"Do you have an existing Neon account, or do you need to create one?\",\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tvalue: \"existing_account\",\n\t\t\t\t\tlabel: \"I have an existing Neon account\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tvalue: \"new_account\",\n\t\t\t\t\tlabel: \"I need to create a new account\",\n\t\t\t\t},\n\t\t\t],\n\t\t\tcontext:\n\t\t\t\t\"Neon is a serverless Postgres provider. A free account is required to continue.\",\n\t\t\tresponseMapping: {\n\t\t\t\texisting_account: {\n\t\t\t\t\taction: {\n\t\t\t\t\t\ttype: \"run_command\",\n\t\t\t\t\t\tcommand: \"CI= npx -y neonctl auth\",\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"This will open your browser for Neon OAuth sign-in.\",\n\t\t\t\t\t\ttimeout: 120000,\n\t\t\t\t\t\tonSuccess: {\n\t\t\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\t\t\targs: [\"auth\", \"--json\", \"--verify\"],\n\t\t\t\t\t\t},\n\t\t\t\t\t\tonFailure: {\n\t\t\t\t\t\t\t\"2\": {\n\t\t\t\t\t\t\t\ttype: \"ask_user\",\n\t\t\t\t\t\t\t\tquestion:\n\t\t\t\t\t\t\t\t\t\"The sign-in timed out. Did you complete the sign-in in your browser?\",\n\t\t\t\t\t\t\t\toptions: [\"yes_retry\", \"need_help\"],\n\t\t\t\t\t\t\t\tresponseMapping: {\n\t\t\t\t\t\t\t\t\tyes_retry: {\n\t\t\t\t\t\t\t\t\t\targs: [\n\t\t\t\t\t\t\t\t\t\t\t\"auth\",\n\t\t\t\t\t\t\t\t\t\t\t\"--json\",\n\t\t\t\t\t\t\t\t\t\t\t\"--method\",\n\t\t\t\t\t\t\t\t\t\t\t\"existing\",\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tneed_help: {\n\t\t\t\t\t\t\t\t\t\targs: [\n\t\t\t\t\t\t\t\t\t\t\t\"auth\",\n\t\t\t\t\t\t\t\t\t\t\t\"--json\",\n\t\t\t\t\t\t\t\t\t\t\t\"--method\",\n\t\t\t\t\t\t\t\t\t\t\t\"new\",\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tother: {\n\t\t\t\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\t\t\t\targs: [\"auth\", \"--json\"],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tnew_account: {\n\t\t\t\t\taction: {\n\t\t\t\t\t\ttype: \"agent_action\",\n\t\t\t\t\t\tsteps: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tid: \"open_signup\",\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\"Open the Neon sign-up page in the user's browser\",\n\t\t\t\t\t\t\t\tcommand: openCmd,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tid: \"wait_for_signup\",\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\"Tell the user: 'I've opened the Neon sign-up page. Create your account and verify your email, then let me know when you're ready.'\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tonComplete: {\n\t\t\t\t\t\t\ttype: \"run_neon_init\",\n\t\t\t\t\t\t\targs: [\"auth\", \"--json\", \"--method\", \"existing\"],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t};\n}\n"],"mappings":";;AAGA,MAAM,kBAA0C;CAC/C,QAAQ;CACR,OAAO;CACP,OAAO;AACR;AAQA,eAAsB,gBACrB,SACyB;CACzB,MAAM,YAAY,QAAQ,QACvB;EAAC;EAAW,QAAQ;EAAO;CAAQ,IACnC,CAAC,QAAQ;CAGZ,IAAI,QAAQ,QAAQ;EAEnB,IAAI,MADiB,gBAAgB,GAIpC,OAAO;GACN,OAAO;GACP,QAAQ;GACR,YAAY;IACX,MAAM;IACN,MAAM;GACP;EACD;EAED,OAAO;GACN,OAAO;GACP,QAAQ;GACR,YAAY;IACX,MAAM;IACN,MAAM,CAAC,QAAQ,QAAQ;GACxB;EACD;CACD;CAIA,IAAI,MADiB,gBAAgB,GAEpC,OAAO;EACN,OAAO;EACP,QAAQ;EACR,YAAY;GACX,MAAM;GACN,MAAM;EACP;CACD;CAID,IAAI,QAAQ,WAAW,OAGtB,OAAO;EACN,OAAO;EACP,QAAQ;EACR,YAAY;GACX,MAAM;GACN,OAAO,CACN;IACC,IAAI;IACJ,aACC;IACD,SAXH,gBAAgB,QAAQ,aAAa,gBAAgB;GAYnD,GACA;IACC,IAAI;IACJ,aACC;GACF,CACD;GACA,YAAY;IACX,MAAM;IACN,MAAM;KAAC;KAAQ;KAAU;KAAY;IAAU;GAChD;EACD;CACD;CAID,IAAI,QAAQ,WAAW,YACtB,OAAO;EACN,OAAO;EACP,QAAQ;EACR,YAAY;GACX,MAAM;GACN,SAAS;GACT,aACC;GACD,SAAS;GACT,WAAW;IACV,MAAM;IACN,MAAM;KAAC;KAAQ;KAAU;IAAU;GACpC;GACA,WAAW;IACV,KAAK;KACJ,MAAM;KACN,UACC;KACD,SAAS,CAAC,aAAa,WAAW;KAClC,iBAAiB;MAChB,WAAW,EACV,MAAM;OACL;OACA;OACA;OACA;MACD,EACD;MACA,WAAW,EACV,MAAM;OAAC;OAAQ;OAAU;OAAY;MAAK,EAC3C;KACD;IACD;IACA,OAAO;KACN,MAAM;KACN,MAAM,CAAC,QAAQ,QAAQ;IACxB;GACD;EACD;CACD;CAMD,OAAO;EACN,OAAO;EACP,QAAQ;EACR,YAAY;GACX,MAAM;GACN,UACC;GACD,SAAS,CACR;IACC,OAAO;IACP,OAAO;GACR,GACA;IACC,OAAO;IACP,OAAO;GACR,CACD;GACA,SACC;GACD,iBAAiB;IAChB,kBAAkB,EACjB,QAAQ;KACP,MAAM;KACN,SAAS;KACT,aACC;KACD,SAAS;KACT,WAAW;MACV,MAAM;MACN,MAAM;OAAC;OAAQ;OAAU;MAAU;KACpC;KACA,WAAW;MACV,KAAK;OACJ,MAAM;OACN,UACC;OACD,SAAS,CAAC,aAAa,WAAW;OAClC,iBAAiB;QAChB,WAAW,EACV,MAAM;SACL;SACA;SACA;SACA;QACD,EACD;QACA,WAAW,EACV,MAAM;SACL;SACA;SACA;SACA;QACD,EACD;OACD;MACD;MACA,OAAO;OACN,MAAM;OACN,MAAM,CAAC,QAAQ,QAAQ;MACxB;KACD;IACD,EACD;IACA,aAAa,EACZ,QAAQ;KACP,MAAM;KACN,OAAO,CACN;MACC,IAAI;MACJ,aACC;MACD,SAxES,gBAAgB,QAAQ,aAAa,gBAAgB;KAyE/D,GACA;MACC,IAAI;MACJ,aACC;KACF,CACD;KACA,YAAY;MACX,MAAM;MACN,MAAM;OAAC;OAAQ;OAAU;OAAY;MAAU;KAChD;IACD,EACD;GACD;EACD;CACD;AACD"}
@@ -0,0 +1,12 @@
1
+ import { PhaseResponse } from "../types.js";
2
+
3
+ //#region src/lib/phases/cleanup.d.ts
4
+
5
+ /**
6
+ * Terminal phase: cleans up ephemeral _init state from .neon and
7
+ * returns a complete message. All feature chains should end here.
8
+ */
9
+ declare function handleCleanup(): PhaseResponse;
10
+ //#endregion
11
+ export { handleCleanup };
12
+ //# sourceMappingURL=cleanup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.d.ts","names":[],"sources":["../../../src/lib/phases/cleanup.ts"],"mappings":";;;;;;AAQA;;iBAAgB,aAAA,CAAA,GAAiB"}
@@ -0,0 +1,29 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ //#region src/lib/phases/cleanup.ts
4
+ /**
5
+ * Terminal phase: cleans up ephemeral _init state from .neon and
6
+ * returns a complete message. All feature chains should end here.
7
+ */
8
+ function handleCleanup() {
9
+ const neonContextPath = resolve(process.cwd(), ".neon");
10
+ if (existsSync(neonContextPath)) try {
11
+ const context = JSON.parse(readFileSync(neonContextPath, "utf-8"));
12
+ if (context._init !== void 0) {
13
+ delete context._init;
14
+ writeFileSync(neonContextPath, `${JSON.stringify(context, null, 2)}\n`);
15
+ }
16
+ } catch {}
17
+ return {
18
+ phase: "setup",
19
+ status: "complete",
20
+ nextAction: {
21
+ type: "complete",
22
+ message: "Neon setup is complete! Your database is connected and your agent has the Neon MCP server and skills available."
23
+ }
24
+ };
25
+ }
26
+ //#endregion
27
+ export { handleCleanup };
28
+
29
+ //# sourceMappingURL=cleanup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cleanup.js","names":[],"sources":["../../../src/lib/phases/cleanup.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { PhaseResponse } from \"../types.js\";\n\n/**\n * Terminal phase: cleans up ephemeral _init state from .neon and\n * returns a complete message. All feature chains should end here.\n */\nexport function handleCleanup(): PhaseResponse {\n\tconst neonContextPath = resolve(process.cwd(), \".neon\");\n\tif (existsSync(neonContextPath)) {\n\t\ttry {\n\t\t\tconst context = JSON.parse(readFileSync(neonContextPath, \"utf-8\"));\n\t\t\tif (context._init !== undefined) {\n\t\t\t\tdelete context._init;\n\t\t\t\twriteFileSync(\n\t\t\t\t\tneonContextPath,\n\t\t\t\t\t`${JSON.stringify(context, null, 2)}\\n`,\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {}\n\t}\n\n\treturn {\n\t\tphase: \"setup\",\n\t\tstatus: \"complete\",\n\t\tnextAction: {\n\t\t\ttype: \"complete\",\n\t\t\tmessage:\n\t\t\t\t\"Neon setup is complete! Your database is connected and your agent has the Neon MCP server and skills available.\",\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,gBAA+B;CAC9C,MAAM,kBAAkB,QAAQ,QAAQ,IAAI,GAAG,OAAO;CACtD,IAAI,WAAW,eAAe,GAC7B,IAAI;EACH,MAAM,UAAU,KAAK,MAAM,aAAa,iBAAiB,OAAO,CAAC;EACjE,IAAI,QAAQ,UAAU,KAAA,GAAW;GAChC,OAAO,QAAQ;GACf,cACC,iBACA,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,EAAE,GACrC;EACD;CACD,QAAQ,CAAC;CAGV,OAAO;EACN,OAAO;EACP,QAAQ;EACR,YAAY;GACX,MAAM;GACN,SACC;EACF;CACD;AACD"}
@@ -0,0 +1,17 @@
1
+ import { PhaseResponse } from "../types.js";
2
+
3
+ //#region src/lib/phases/db.d.ts
4
+ interface DbPhaseOptions {
5
+ agent?: string;
6
+ orgId?: string;
7
+ projectId?: string;
8
+ orgsResult?: string;
9
+ projectsResult?: string;
10
+ framework?: string;
11
+ orm?: string;
12
+ error?: string;
13
+ }
14
+ declare function handleDbPhase(options: DbPhaseOptions): Promise<PhaseResponse>;
15
+ //#endregion
16
+ export { DbPhaseOptions, handleDbPhase };
17
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","names":[],"sources":["../../../src/lib/phases/db.ts"],"mappings":";;;UAeiB,cAAA;;EAAA,KAAA,CAAA,EAAA,MAAA;EAWK,SAAA,CAAA,EAAA,MAAa;EAAA,UAAA,CAAA,EAAA,MAAA;gBACzB,CAAA,EAAA,MAAA;WACC,CAAA,EAAA,MAAA;KAAR,CAAA,EAAA,MAAA;EAAO,KAAA,CAAA,EAAA,MAAA;;iBAFY,aAAA,UACZ,iBACP,QAAQ"}