can1357/oh-my-pi · error · AIError.OnPromptRequiredError

Alibaba Coding Plan

Error message

Alibaba Coding Plan

What it means

loginAlibabaCodingPlan performs an interactive OAuth-style login and requires an onPrompt callback to ask the user which endpoint (International/China/Custom) to use. If the OAuthController passed in has no onPrompt function — e.g. a non-interactive environment — it throws OnPromptRequiredError naming 'Alibaba Coding Plan' so the host application can surface an interactive prompt flow.

Source

Thrown at packages/ai/src/registry/alibaba-coding-plan.ts:14

import * as AIError from "../error";
import * as apiKeyValidation from "./api-key-validation";
import type { OAuthController, OAuthCredentials, OAuthLoginCallbacks } from "./oauth/types";
import type { ProviderDefinition } from "./types";

const DEFAULT_AUTH_URL = "https://modelstudio.console.alibabacloud.com/";
const CHINA_AUTH_URL = "https://bailian.console.aliyun.com/?tab=model#/api-key";
const DEFAULT_API_BASE_URL = "https://coding-intl.dashscope.aliyuncs.com/v1";
const CHINA_API_BASE_URL = "https://coding.dashscope.aliyuncs.com/v1";
const VALIDATION_MODEL = "qwen3.5-plus";

export async function loginAlibabaCodingPlan(options: OAuthController): Promise<OAuthCredentials> {
	if (!options.onPrompt) {
		throw new AIError.OnPromptRequiredError("Alibaba Coding Plan");
	}

	// Ask which endpoint to use
	const endpointChoice = await options.onPrompt({
		message: "Select Alibaba Coding Plan endpoint: 1=International (default), 2=China, 3=Custom — enter 1, 2, or 3",
		placeholder: "1",
	});

	// Check for abort after endpoint selection (Escape returns "")
	if (options.signal?.aborted) {
		throw new AIError.LoginCancelledError();
	}

	const choice = endpointChoice.trim();
	let baseUrl: string;
	let authUrl: string;
	let instructions: string;
	if (choice === "2") {

View on GitHub (pinned to 9690622007)

Solutions

  1. Pass an OAuthController that implements `onPrompt` (returning the user's choice string)
  2. Run the login flow through the interactive CLI that provides prompt handling
  3. For headless environments, provision credentials directly (API key config) instead of invoking the interactive login

Example fix

// before
await loginAlibabaCodingPlan({});
// after
await loginAlibabaCodingPlan({ onPrompt: async q => { /* show q.message, return answer */ } });
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof controller?.onPrompt !== 'function') throw new Error('Alibaba Coding Plan login requires an interactive onPrompt callback');

Type guard

function canPrompt(c: OAuthController): c is OAuthController & { onPrompt: NonNullable<OAuthController['onPrompt']> } { return typeof c.onPrompt === 'function'; }

Try / catch

try { creds = await loginAlibabaCodingPlan(controller); } catch (e) { if (e instanceof AIError.OnPromptRequiredError) creds = await interactiveFallback('alibaba-coding-plan'); else throw e; }

Prevention

When it happens

Trigger: Calling loginAlibabaCodingPlan with an OAuthController that lacks `onPrompt` (undefined), typically in headless/CI code or when constructing the controller without implementing the prompt hooks.

Common situations: Automated credential setup scripts; embedding the registry login in a CLI without wiring a prompt UI; running in a non-TTY context where the host skipped prompt handlers.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/88fe95388c08f115. Report an issue: GitHub.