Qwen Text Chat (OpenAI-Compatible) Generate text, conduct conversations, write code, and invoke tools using Qwen models through the OpenAI-compatible API. This skill is part of QianWen-AI/qianwen-ai . Skill directory Use this skill's internal files to execute and learn. Load reference files on demand when the default path fails or you need details. | Location | Purpose | |-------------------------------------|-------------------------------------------------------------------------------------| | | Default execution — chat/completions request, streaming, output save | | | Fallback: curl, Pyth…

\n for candidate in candidates:\n m = re.search(pattern, candidate)\n if m:\n agent, skill = m.group(1) or \"default\", m.group(2)\n if len(agent) \u003c= 32 and len(skill) \u003c= 32:\n return json.dumps({\"channel\": \"qianwenai-skill\", \"tags\": {\"t1\": skill, \"t2\": agent}}, separators=(',', ':'))\n return None\n\n\n# ---------------------------------------------------------------------------\n# Section 6: HTTP infrastructure\n# ---------------------------------------------------------------------------\n\n_RETRYABLE_CODES = frozenset({429, 500, 502, 503, 504})\n\n\ndef http_request(\n method: str,\n url: str,\n api_key: str,\n payload: dict[str, Any] | None = None,\n *,\n extra_headers: dict[str, str] | None = None,\n timeout: int = 120,\n retries: int = 2,\n backoff: float = 1.5,\n) -> dict[str, Any]:\n \"\"\"Generic HTTP request with retry and exponential backoff.\n\n Handles JSON serialisation, provider header injection, and retryable\n HTTP codes.\n \"\"\"\n hdrs = get_provider().make_headers(api_key, payload)\n if extra_headers:\n hdrs.update(extra_headers)\n data = json.dumps(payload).encode(\"utf-8\") if payload else None\n last_err = \"\"\n for attempt in range(retries + 1):\n req = urllib.request.Request(url, data=data, headers=hdrs, method=method)\n try:\n with urllib.request.urlopen(req, timeout=timeout) as resp:\n return json.loads(resp.read().decode(\"utf-8\"))\n except urllib.error.HTTPError as exc:\n body = \"\"\n try:\n body = exc.read().decode(\"utf-8\", errors=\"replace\")\n except Exception:\n pass\n last_err = f\"HTTP {exc.code}: {body[:500]}\"\n if api_key and len(api_key) > 8 and api_key in body:\n last_err = last_err.replace(api_key, mask_key(api_key))\n if exc.code not in _RETRYABLE_CODES or attempt >= retries:\n raise RuntimeError(last_err) from exc\n time.sleep(backoff * (2 ** attempt))\n except urllib.error.URLError as exc:\n last_err = str(exc.reason)\n if attempt >= retries:\n raise RuntimeError(f\"Network error: {last_err}\") from exc\n time.sleep(backoff * (2 ** attempt))\n raise RuntimeError(last_err)\n\n\ndef http_post(\n url: str,\n api_key: str,\n payload: dict[str, Any],\n *,\n timeout: int = 120,\n retries: int = 2,\n backoff: float = 1.5,\n) -> dict[str, Any]:\n \"\"\"Convenience: non-streaming POST, returns parsed JSON.\"\"\"\n return http_request(\n \"POST\", url, api_key, payload,\n timeout=timeout, retries=retries, backoff=backoff,\n )\n\n\ndef _sse_error_message(\n chunk: Any,\n event_type: str,\n api_key: str,\n) -> Optional[str]:\n \"\"\"Return a safe error message for an SSE error payload, if present.\"\"\"\n error_payload = chunk.get(\"error\") if isinstance(chunk, dict) else None\n has_top_level_error = isinstance(chunk, dict) and (\n not chunk.get(\"choices\")\n and chunk.get(\"code\") is not None\n and chunk.get(\"message\") is not None\n )\n if event_type.lower() != \"error\" and error_payload is None and not has_top_level_error:\n return None\n\n payload = error_payload if error_payload is not None else chunk\n if isinstance(payload, dict):\n code = payload.get(\"code\") or payload.get(\"type\")\n message = payload.get(\"message\")\n if code and message:\n detail = f\"{code}: {message}\"\n elif code or message:\n detail = str(code or message)\n else:\n detail = json.dumps(payload, ensure_ascii=False)\n else:\n detail = str(payload)\n\n if api_key and len(api_key) > 8 and api_key in detail:\n detail = detail.replace(api_key, mask_key(api_key))\n return f\"SSE error: {sanitize_diagnostic(detail)[:500]}\"\n\n\ndef stream_sse(\n url: str,\n api_key: str,\n payload: dict[str, Any],\n *,\n timeout: int = 180,\n) -> Iterator[dict[str, Any]]:\n \"\"\"Streaming POST. Yields parsed SSE ``data:`` chunks.\n\n Automatically sets ``stream: true`` in the payload and sends the\n appropriate ``Accept`` header.\n \"\"\"\n payload[\"stream\"] = True\n hdrs = get_provider().make_headers(api_key, payload)\n hdrs[\"Accept\"] = \"text/event-stream\"\n data = json.dumps(payload).encode(\"utf-8\")\n req = urllib.request.Request(url, data=data, headers=hdrs, method=\"POST\")\n try:\n resp = urllib.request.urlopen(req, timeout=timeout)\n except urllib.error.HTTPError as exc:\n body = \"\"\n try:\n body = exc.read().decode(\"utf-8\", errors=\"replace\")\n except Exception:\n pass\n if api_key and len(api_key) > 8 and api_key in body:\n body = body.replace(api_key, mask_key(api_key))\n raise RuntimeError(f\"HTTP {exc.code}: {sanitize_diagnostic(body)[:500]}\") from None\n except urllib.error.URLError as exc:\n raise RuntimeError(f\"Network error: {sanitize_diagnostic(str(exc.reason))}\") from None\n\n buf = b\"\"\n event_type = \"\"\n try:\n while True:\n raw = resp.read(4096)\n if not raw:\n break\n buf += raw\n while b\"\\n\" in buf:\n line_bytes, buf = buf.split(b\"\\n\", 1)\n line = line_bytes.decode(\"utf-8\", errors=\"replace\").strip()\n if not line:\n event_type = \"\"\n continue\n if line.startswith(\"event:\"):\n event_type = line[6:].strip()\n continue\n if not line.startswith(\"data:\"):\n continue\n json_str = line[5:].strip()\n if json_str == \"[DONE]\":\n return\n try:\n chunk = json.loads(json_str)\n except json.JSONDecodeError:\n if event_type.lower() == \"error\":\n detail = json_str\n if api_key and len(api_key) > 8 and api_key in detail:\n detail = detail.replace(api_key, mask_key(api_key))\n detail = sanitize_diagnostic(detail)[:500]\n raise RuntimeError(f\"SSE error: {detail}\") from None\n pass\n else:\n error_message = _sse_error_message(chunk, event_type, api_key)\n if error_message:\n raise RuntimeError(error_message)\n yield chunk\n event_type = \"\"\n finally:\n resp.close()\n\n\n# ---------------------------------------------------------------------------\n# Section 7: File upload / download\n# ---------------------------------------------------------------------------\n\n_BASE64_FILE_LIMIT = 7 * 1024 * 1024 # 7 MB (base64 adds ~33%; API limit is 10 MB)\n\n\ndef upload_local_file(api_key: str, model: str, fp: Path) -> str:\n \"\"\"Upload a local file to the active provider's temp storage.\n\n Returns a provider-managed URL (e.g. ``oss://`` for DashScope).\n \"\"\"\n return get_provider().upload_file(api_key, model, fp)\n\n\ndef resolve_file(\n value: str,\n *,\n api_key: str | None = None,\n model: str | None = None,\n) -> str:\n \"\"\"Resolve a file reference for API consumption.\n\n URLs (``http``, ``https``, ``data``, and provider-managed schemes)\n pass through unchanged. Local files are handled based on context:\n\n - *api_key* + *model* provided: upload to temp storage.\n - Otherwise: convert to ``data:`` base64 URI (must be \u003c 7 MB).\n \"\"\"\n provider = get_provider()\n pass_through = (\"http://\", \"https://\", \"data:\") + provider.managed_url_schemes()\n if value.startswith(pass_through):\n return value\n if value.startswith(\"file://\"):\n parsed = urllib.parse.urlparse(value)\n if parsed.netloc and parsed.netloc.lower() != \"localhost\":\n raise ValueError(\n f\"Cannot resolve non-local file URI authority {parsed.netloc!r}; \"\n \"only an empty authority or 'localhost' is supported.\"\n )\n value = urllib.request.url2pathname(parsed.path)\n p = Path(value)\n if not (p.exists() and p.is_file()):\n return value\n\n file_size = p.stat().st_size\n\n if api_key and model:\n managed_url = provider.upload_file(api_key, model, p)\n tag = \"48 h TTL\" if managed_url.startswith(\"oss://\") else \"custom OSS\"\n print(sanitize_diagnostic(f\"Uploaded {p.name} -> {managed_url} ({tag})\"), file=sys.stderr)\n return managed_url\n\n if file_size > _BASE64_FILE_LIMIT:\n print(\n f\"Warning: {p.name} is {file_size / 1024 / 1024:.1f} MB -- \"\n \"base64 may exceed the 10 MB API limit. \"\n \"Use --upload-files to auto-upload, or provide an online URL.\",\n file=sys.stderr,\n )\n\n mime = mimetypes.guess_type(p.name)[0] or \"application/octet-stream\"\n b64 = base64.b64encode(p.read_bytes()).decode(\"ascii\")\n return f\"data:{mime};base64,{b64}\"\n\n\ndef download_file(url: str, dest: Path, *, timeout: int = 120) -> Path:\n \"\"\"Download a file from *url* to *dest*, creating parent dirs as needed.\"\"\"\n dest.parent.mkdir(parents=True, exist_ok=True)\n req = urllib.request.Request(url, headers={\"User-Agent\": \"qianwenai-skill\"})\n try:\n with urllib.request.urlopen(req, timeout=timeout) as resp:\n dest.write_bytes(resp.read())\n except urllib.error.URLError as exc:\n raise RuntimeError(f\"Download failed: {sanitize_diagnostic(str(exc))}\") from None\n return dest\n\n\n# ---------------------------------------------------------------------------\n# Section 8: Request / response utilities\n# ---------------------------------------------------------------------------\n\ndef load_request(args: Any) -> dict[str, Any]:\n \"\"\"Load request dict from ``--request`` or ``--file`` CLI argument.\"\"\"\n if getattr(args, \"request\", None):\n return json.loads(args.request)\n if getattr(args, \"file\", None):\n return json.loads(Path(args.file).read_text(encoding=\"utf-8\"))\n raise ValueError(\"Provide --request '{...}' or --file path/to/request.json\")\n\n\ndef save_result(result: dict[str, Any], output_path: str | Path) -> None:\n \"\"\"Write *result* as JSON to *output_path*, creating parent dirs.\"\"\"\n p = Path(output_path)\n p.parent.mkdir(parents=True, exist_ok=True)\n p.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding=\"utf-8\")\n\n\ndef extract_text(content: Any) -> str:\n \"\"\"Extract plain text from a message ``content`` field.\n\n Handles ``str``, ``list[{type, text}]``, and ``None``.\n \"\"\"\n if isinstance(content, str):\n return content\n if isinstance(content, list):\n for item in content:\n if isinstance(item, dict) and item.get(\"type\") == \"text\":\n text = item.get(\"text\")\n if isinstance(text, str):\n return text\n return json.dumps(content, ensure_ascii=False)\n if content is None:\n return \"\"\n return json.dumps(content, ensure_ascii=False)\n\n\ndef try_parse_json(text: str) -> Any | None:\n \"\"\"Attempt to parse *text* as JSON; return ``None`` on failure.\"\"\"\n text = text.strip()\n if not text:\n return None\n try:\n return json.loads(text)\n except json.JSONDecodeError:\n return None\n\n\n# ---------------------------------------------------------------------------\n# Section 9: Async task polling\n# ---------------------------------------------------------------------------\n\ndef poll_task(\n task_id: str,\n api_key: str,\n *,\n timeout_s: int = 600,\n interval: int = 10,\n verbose: bool = True,\n) -> dict[str, Any]:\n \"\"\"Poll an async task until it reaches a terminal state.\n\n Returns the final result dict. Raises ``TimeoutError`` if\n *timeout_s* is exceeded.\n \"\"\"\n provider = get_provider()\n url = provider.task_poll_url(task_id)\n terminals = provider.terminal_statuses()\n start = time.time()\n poll_count = 0\n while True:\n result = http_request(\"GET\", url, api_key)\n elapsed = int(time.time() - start)\n poll_count += 1\n status = provider.extract_task_status(result)\n if verbose:\n print(f\" [{elapsed}s] task={task_id} status={status}\", file=sys.stderr)\n if status in terminals:\n return result\n if time.time() - start > timeout_s:\n raise TimeoutError(\n f\"Task {task_id} timed out after {timeout_s}s \"\n f\"({poll_count} polls, last status: {status})\"\n )\n time.sleep(interval)\n\n\n# ---------------------------------------------------------------------------\n# Section 10: Update-check signal\n# ---------------------------------------------------------------------------\n\ntry:\n from gossamer import run as _run_update_signal_impl\nexcept ImportError:\n _run_update_signal_impl = None # type: ignore[assignment]\n\n\ndef run_update_signal(caller: str | Path | None = None) -> None:\n \"\"\"Emit update-check signals to stderr (non-blocking, failure-safe).\n\n Parameters\n ----------\n caller : str or Path, optional\n ``__file__`` of the calling script.\n \"\"\"\n if _run_update_signal_impl:\n try:\n _run_update_signal_impl(caller=caller or __file__)\n except Exception:\n pass\n","content_type":"text/x-python; charset=utf-8","language":"python","size":43758,"content_sha256":"9343069363f8e31b7178d2462c79e2e7d56cb7a30665544d9072b1d39589d8b0"},{"filename":"scripts/text.py","content":"#!/usr/bin/env python3\n\"\"\"Chat with Qwen models via OpenAI-compatible API. Self-contained, stdlib only.\"\"\"\nfrom __future__ import annotations\n\nimport sys\n\nif sys.version_info \u003c (3, 9):\n print(f\"Error: Python 3.9+ required (found {sys.version}). \"\n \"Install: https://www.python.org/downloads/\", file=sys.stderr)\n sys.exit(1)\n\nimport argparse\nimport json\nfrom pathlib import Path\nfrom typing import Any\n\nsys.path.insert(0, str(Path(__file__).resolve().parent))\n\nfrom qianwen_lib import ( # noqa: E402\n chat_url,\n http_post,\n load_cdn_model_config,\n load_request,\n require_api_key,\n run_update_signal,\n stream_sse,\n validate_token_plan_model,\n)\n\n\ndef _default_model() -> str:\n config = load_cdn_model_config(\n \"qianwen-text-config.json\",\n required_keys=(\"default_model\",),\n )\n model = config[\"default_model\"]\n if not isinstance(model, str) or not model:\n raise RuntimeError(\"Invalid text model configuration: default_model must be a string\")\n return model\n\n\n# ---------------------------------------------------------------------------\n# Response helpers\n# ---------------------------------------------------------------------------\n\ndef _extract_content(resp: dict[str, Any]) -> str:\n choices = resp.get(\"choices\", [])\n if choices:\n msg = choices[0].get(\"message\", {})\n return msg.get(\"content\", \"\") or \"\"\n return \"\"\n\n\n# ---------------------------------------------------------------------------\n# Streaming\n# ---------------------------------------------------------------------------\n\ndef _run_stream(url: str, api_key: str, request: dict[str, Any],\n print_response: bool, print_reasoning: bool = True) -> dict[str, Any]:\n full_content = \"\"\n reasoning_content = \"\"\n is_answering = False\n model = request.get(\"model\", \"\")\n tool_calls: dict[int, dict[str, Any]] = {} # keyed by index per official docs\n finish_reason = \"stop\"\n\n for chunk in stream_sse(url, api_key, request):\n choices = chunk.get(\"choices\", [])\n if not choices:\n continue\n choice = choices[0]\n delta = choice.get(\"delta\", {})\n\n # Handle reasoning_content (thinking mode)\n rc = delta.get(\"reasoning_content\") or \"\"\n if rc:\n reasoning_content += rc\n if print_response and print_reasoning and not is_answering:\n print(rc, end=\"\", flush=True, file=sys.stderr)\n\n # Handle regular content\n text = delta.get(\"content\", \"\") or \"\"\n if text:\n if not is_answering:\n is_answering = True\n if print_response and reasoning_content:\n print(\"\\n\", file=sys.stderr) # newline after reasoning\n full_content += text\n if print_response:\n print(text, end=\"\", flush=True)\n\n # Handle function calling (delta.tool_calls) - per official docs pattern\n if \"tool_calls\" in delta and delta[\"tool_calls\"]:\n for tc in delta[\"tool_calls\"]:\n idx = tc.get(\"index\", 0)\n args = (tc.get(\"function\") or {}).get(\"arguments\") or \"\"\n if idx not in tool_calls:\n tool_calls[idx] = tc\n # Ensure arguments is string, not None\n if \"function\" in tool_calls[idx]:\n tool_calls[idx][\"function\"][\"arguments\"] = args\n else:\n # Accumulate arguments across chunks\n tool_calls[idx][\"function\"][\"arguments\"] += args\n\n # Track finish_reason\n if choice.get(\"finish_reason\"):\n finish_reason = choice[\"finish_reason\"]\n\n if not model and chunk.get(\"model\"):\n model = chunk[\"model\"]\n\n if print_response:\n print()\n\n message: dict[str, Any] = {\"role\": \"assistant\", \"content\": full_content}\n if tool_calls:\n message[\"tool_calls\"] = list(tool_calls.values())\n\n result: dict[str, Any] = {\n \"model\": model,\n \"choices\": [{\"message\": message, \"finish_reason\": finish_reason}],\n }\n if reasoning_content:\n result[\"reasoning\"] = reasoning_content\n return result\n\n\n# ---------------------------------------------------------------------------\n# Main\n# ---------------------------------------------------------------------------\n\ndef main() -> None:\n run_update_signal(caller=__file__)\n parser = argparse.ArgumentParser(\n description=\"Chat with Qwen models via OpenAI-compatible API\",\n formatter_class=argparse.RawDescriptionHelpFormatter,\n epilog=\"\"\"\\\nrequest JSON fields (--request / --file):\n messages (required) Array of {role, content} message objects\n model Model ID — overridden by --model flag\n enable_thinking true/false — enable chain-of-thought (default: let model decide)\n tools Array of tool/function definitions for function calling\n response_format {\"type\":\"json_object\"} or {\"type\":\"json_schema\",\"json_schema\":{...}}\n temperature Sampling temperature (0-2)\n max_tokens Maximum output tokens\n stream true/false — overridden by --stream flag\n\nenvironment variables:\n DASHSCOPE_API_KEY (required) API key — also loaded from .env file\n QIANWEN_API_KEY (alternative) Alias for DASHSCOPE_API_KEY\n QWEN_REGION cn-beijing (default)\n QWEN_BASE_URL Override the API base URL entirely\n\nexamples:\n # Simple chat\n python scripts/text.py --request '{\"messages\":[{\"role\":\"user\",\"content\":\"Hello\"}]}'\n\n # With system prompt and streaming\n python scripts/text.py --request '{\"messages\":[\n {\"role\":\"system\",\"content\":\"You are a helpful assistant\"},\n {\"role\":\"user\",\"content\":\"Explain quantum computing\"}\n ]}' --stream --print-response\n\n # From file, save output\n python scripts/text.py --file request.json --output results/ --print-response\n\n # Structured JSON output\n python scripts/text.py --request '{\"messages\":[{\"role\":\"user\",\"content\":\"List 3 colors\"}],\n \"response_format\":{\"type\":\"json_object\"}}' --print-response\n\"\"\",\n )\n parser.add_argument(\"--request\", help=\"Inline JSON: must contain 'messages' array\")\n parser.add_argument(\"--file\", help=\"Path to JSON file containing request body\")\n parser.add_argument(\"--output\", default=\"output/qianwen-text\",\n help=\"Directory to save response JSON (default: output/qianwen-text)\")\n parser.add_argument(\"--print-response\", action=\"store_true\", help=\"Print generated text to stdout\")\n parser.add_argument(\"--model\", default=None,\n help=\"Model ID (default loaded from CDN model configuration)\")\n parser.add_argument(\"--stream\", action=\"store_true\", help=\"Enable streaming response (SSE)\")\n parser.add_argument(\"--enable-thinking\", action=\"store_true\", dest=\"enable_thinking_flag\",\n help=\"Enable chain-of-thought thinking mode (overrides model defaults). \"\n \"Recommended for complex reasoning/math tasks. Adds latency for qwen3.6-plus/qwen3.5-plus/flash.\")\n parser.add_argument(\"--hide-reasoning\", action=\"store_true\",\n help=\"Suppress reasoning process output to stderr (reasoning still saved to JSON)\")\n args = parser.parse_args()\n\n try:\n request = load_request(args)\n except ValueError as e:\n print(f\"Error: {e}\", file=sys.stderr)\n sys.exit(1)\n\n if args.model:\n request[\"model\"] = args.model\n elif \"model\" not in request:\n request[\"model\"] = _default_model()\n \n # Thinking mode handling:\n # - User explicitly enabled via flag → set true\n # - User specified in request JSON → respect their choice \n # - Otherwise → let API apply model defaults (qwen3.6-plus/qwen3.5-plus/flash have thinking ON by default)\n if args.enable_thinking_flag:\n request[\"enable_thinking\"] = True\n print(\"Note: Thinking mode enabled explicitly. May add latency for qwen3.6-plus/qwen3.5-plus/flash.\", file=sys.stderr)\n elif \"enable_thinking\" not in request:\n # Do nothing - preserve API defaults per model\n pass\n\n api_key = require_api_key(script_file=__file__)\n validate_token_plan_model(api_key, request[\"model\"])\n url = chat_url()\n\n try:\n if args.stream or request.get(\"stream\"):\n print(\"Connecting to model (streaming)...\", file=sys.stderr)\n response_data = _run_stream(url, api_key, request, args.print_response,\n print_reasoning=not args.hide_reasoning)\n else:\n request[\"stream\"] = False\n print(\"Sending request to model, please wait...\", file=sys.stderr)\n response_data = http_post(url, api_key, request)\n # Extract reasoning_content from non-streaming response (normalize to top-level)\n msg = (response_data.get(\"choices\") or [{}])[0].get(\"message\", {})\n if msg.get(\"reasoning_content\"):\n response_data[\"reasoning\"] = msg[\"reasoning_content\"]\n if args.print_response:\n print(_extract_content(response_data))\n except RuntimeError as e:\n print(f\"API error: {e}\", file=sys.stderr)\n sys.exit(1)\n\n out = Path(args.output)\n if out.suffix.lower() == \".json\":\n out_file = out\n out_dir = out.parent\n else:\n out_dir = out\n out_file = out_dir / \"response.json\"\n out_dir.mkdir(parents=True, exist_ok=True)\n out_file.write_text(json.dumps(response_data, ensure_ascii=False, indent=2), encoding=\"utf-8\")\n print(f\"Response saved to {out_file}\", file=sys.stderr)\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":9713,"content_sha256":"4d25433aa6ed7373ccbcf911a11dd19f1377ac07568de7a443579bb9e64382c6"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Qwen Text Chat (OpenAI-Compatible)","type":"text"}]},{"type":"paragraph","content":[{"text":"Generate text, conduct conversations, write code, and invoke tools using Qwen models through the OpenAI-compatible API. This skill is part of ","type":"text"},{"text":"QianWen-AI/qianwen-ai","type":"text","marks":[{"type":"strong"}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Skill directory","type":"text"}]},{"type":"paragraph","content":[{"text":"Use this skill's internal files to execute and learn. Load reference files on demand when the default path fails or you need details.","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Location","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Purpose","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"scripts/text.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Default execution — chat/completions request, streaming, output save","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/execution-guide.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Fallback: curl, Python SDK, function calling, thinking mode","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/api-guide.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"API supplement and full code examples","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/prompt-guide.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Prompt engineering: CO-STAR framework, CoT, few-shot, task steps","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"references/sources.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Official documentation URLs (manual lookup only)","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Security","type":"text"}]},{"type":"paragraph","content":[{"text":"NEVER output any API key or credential in plaintext.","type":"text","marks":[{"type":"strong"}]},{"text":" Always use variable references (","type":"text"},{"text":"$DASHSCOPE_API_KEY","type":"text","marks":[{"type":"code_inline"}]},{"text":" in shell, ","type":"text"},{"text":"os.environ[\"DASHSCOPE_API_KEY\"]","type":"text","marks":[{"type":"code_inline"}]},{"text":" in Python). Any check or detection of credentials must be ","type":"text"},{"text":"non-plaintext","type":"text","marks":[{"type":"strong"}]},{"text":": report only status (e.g. \"set\" / \"not set\", \"valid\" / \"invalid\"), never the value. Never display contents of ","type":"text"},{"text":".env","type":"text","marks":[{"type":"code_inline"}]},{"text":" or config files that may contain secrets.","type":"text"}]},{"type":"paragraph","content":[{"text":"When the API key is not configured, NEVER ask the user to provide it directly.","type":"text","marks":[{"type":"strong"}]},{"text":" Instead, help create a ","type":"text"},{"text":".env","type":"text","marks":[{"type":"code_inline"}]},{"text":" file with a placeholder (","type":"text"},{"text":"DASHSCOPE_API_KEY=sk-your-key-here","type":"text","marks":[{"type":"code_inline"}]},{"text":") and instruct the user to replace it with their actual key from the ","type":"text"},{"text":"QianWen Console","type":"text","marks":[{"type":"link","attrs":{"href":"https://platform.qianwenai.com/home/api-keys","title":null}}]},{"text":". Only write the actual key value if the user explicitly requests it.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Key Compatibility","type":"text"}]},{"type":"paragraph","content":[{"text":"Both PAYG (","type":"text"},{"text":"sk-ws-...","type":"text","marks":[{"type":"code_inline"}]},{"text":"; legacy ","type":"text"},{"text":"sk-...","type":"text","marks":[{"type":"code_inline"}]},{"text":") and Token Plan (","type":"text"},{"text":"sk-sp-...","type":"text","marks":[{"type":"code_inline"}]},{"text":") keys are supported. Detect the API key type without exposing the Key:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 -c \"\nimport sys; sys.path.insert(0, 'scripts')\nfrom qianwen_lib import detect_api_key_type\nprint(detect_api_key_type('scripts/qianwen_lib.py'))\n\"","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Output","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Meaning","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"token-plan","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Token Plan key — use only models from the Token Plan catalog below.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"payg","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Pay-as-you-go key — full model catalog available.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"not-set","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"No key configured.","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"For Token Plan, fetch and read the current ","type":"text"},{"text":"Token Plan model catalog","type":"text","marks":[{"type":"link","attrs":{"href":"https://alioth.alicdn.com/skills-info/models/references/qianwen-token-plan-models.md","title":null}}]},{"text":", then use an exact listed model. If CDN access fails, use the ","type":"text"},{"text":"local fallback","type":"text","marks":[{"type":"link","attrs":{"href":"cdn/references/qianwen-token-plan-models.md","title":null}}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"Token Plan supports only specific models — use exactly a model from the references above; do not guess or probe model availability. For PAYG, continue below.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Model Selection","type":"text"}]},{"type":"paragraph","content":[{"text":"Before selecting, recommending, or defaulting a model, fetch and read the current ","type":"text"},{"text":"Qwen text model catalog","type":"text","marks":[{"type":"link","attrs":{"href":"https://alioth.alicdn.com/skills-info/models/references/qianwen-text-models.md","title":null}}]},{"text":". It contains the model list, basic model information, recommendations, and default model. If CDN access fails, use the ","type":"text"},{"text":"local fallback","type":"text","marks":[{"type":"link","attrs":{"href":"cdn/references/qianwen-text-models.md","title":null}}]},{"text":".","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"User specified a model","type":"text","marks":[{"type":"strong"}]},{"text":" → use directly.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Consult the qianwen-model-selector skill","type":"text","marks":[{"type":"strong"}]},{"text":" when model choice depends on requirement, scenario, or pricing.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"No signal, clear task","type":"text","marks":[{"type":"strong"}]},{"text":" → use the default from the model catalog. For strongest reasoning/coding, use its recommended high-capability option.","type":"text"}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"⚠️ Important","type":"text","marks":[{"type":"strong"}]},{"text":": The model catalog is a ","type":"text"},{"text":"point-in-time snapshot","type":"text","marks":[{"type":"strong"}]},{"text":" and may be outdated. Model availability changes frequently. ","type":"text"},{"text":"Always check the ","type":"text","marks":[{"type":"strong"}]},{"text":"official model list","type":"text","marks":[{"type":"link","attrs":{"href":"https://www.qianwenai.com/models","title":null}},{"type":"strong"}]},{"text":" for the authoritative, up-to-date catalog before making model decisions.","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Model details","type":"text","marks":[{"type":"strong"}]},{"text":": For more information about a specific model, direct the user to ","type":"text"},{"text":"https://www.qianwenai.com/models/\u003cmodel-name>","type":"text","marks":[{"type":"code_inline"}]},{"text":". Replace ","type":"text"},{"text":"\u003cmodel-name>","type":"text","marks":[{"type":"code_inline"}]},{"text":" with the exact model ID; never modify or guess it.","type":"text"}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Dynamic model queries","type":"text","marks":[{"type":"strong"}]},{"text":": If the ","type":"text"},{"text":"qianwen-model-selector","type":"text","marks":[{"type":"strong"}]},{"text":" skill or ","type":"text"},{"text":"QianWen CLI","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"qianwen models info \u003cmodel>","type":"text","marks":[{"type":"code_inline"}]},{"text":") is available, use it for real-time model data. CLI requires authentication — see the ","type":"text"},{"text":"qianwen-usage","type":"text","marks":[{"type":"strong"}]},{"text":" skill for login flow.","type":"text"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Execution","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Prerequisites","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"API Key","type":"text","marks":[{"type":"strong"}]},{"text":": Use the non-plaintext detector in ","type":"text"},{"text":"Key Compatibility","type":"text","marks":[{"type":"strong"}]},{"text":"; do not replace it with a variable-presence check. If no Key is found, use qianwen-ops-auth when available or guide the user to configure ","type":"text"},{"text":"DASHSCOPE_API_KEY","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"QIANWEN_API_KEY","type":"text","marks":[{"type":"code_inline"}]},{"text":" in ","type":"text"},{"text":".env","type":"text","marks":[{"type":"code_inline"}]},{"text":". Skills may be installed independently.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Python 3.9+ (stdlib only, ","type":"text"},{"text":"no pip install needed","type":"text","marks":[{"type":"strong"}]},{"text":" for script execution)","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Environment Check","type":"text"}]},{"type":"paragraph","content":[{"text":"Before first execution, verify Python is available:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 --version # must be 3.9+","type":"text"}]},{"type":"paragraph","content":[{"text":"If ","type":"text"},{"text":"python3","type":"text","marks":[{"type":"code_inline"}]},{"text":" is not found, try ","type":"text"},{"text":"python --version","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"py -3 --version","type":"text","marks":[{"type":"code_inline"}]},{"text":". If Python is unavailable or below 3.9, skip to * ","type":"text"},{"text":"Path 2 (curl)","type":"text","marks":[{"type":"em"}]},{"text":"* in ","type":"text"},{"text":"execution-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/execution-guide.md","title":null}}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Default: Run Script","type":"text"}]},{"type":"paragraph","content":[{"text":"Script path","type":"text","marks":[{"type":"strong"}]},{"text":": Scripts are in the ","type":"text"},{"text":"scripts/","type":"text","marks":[{"type":"code_inline"}]},{"text":" subdirectory ","type":"text"},{"text":"of this skill's directory","type":"text","marks":[{"type":"strong"}]},{"text":" (the directory containing this SKILL.md). ","type":"text"},{"text":"You MUST first locate this skill's installation directory, then ALWAYS use the full absolute path to execute scripts.","type":"text","marks":[{"type":"strong"}]},{"text":" Do NOT assume scripts are in the current working directory. Do NOT use ","type":"text"},{"text":"cd","type":"text","marks":[{"type":"code_inline"}]},{"text":" to switch directories before execution.","type":"text"}]},{"type":"paragraph","content":[{"text":"Execution note:","type":"text","marks":[{"type":"strong"}]},{"text":" Run all scripts in the ","type":"text"},{"text":"foreground","type":"text","marks":[{"type":"strong"}]},{"text":" — wait for stdout; do not background.","type":"text"}]},{"type":"paragraph","content":[{"text":"Discovery:","type":"text","marks":[{"type":"strong"}]},{"text":" Run ","type":"text"},{"text":"python3 \u003cthis-skill-dir>/scripts/text.py --help","type":"text","marks":[{"type":"code_inline"}]},{"text":" first to see all available arguments.","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 \u003cthis-skill-dir>/scripts/text.py \\\n --request '{\"messages\":[{\"role\":\"user\",\"content\":\"Hello!\"}],\"model\":\"qwen3.7-plus\"}' \\\n --output output/qianwen-text/ --print-response","type":"text"}]},{"type":"paragraph","content":[{"text":"For streaming (recommended for interactive use):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 \u003cthis-skill-dir>/scripts/text.py \\\n --request '{\"messages\":[{\"role\":\"user\",\"content\":\"Write a poem about the sea\"}],\"model\":\"qwen3.7-plus\"}' \\\n --stream --print-response","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Argument","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--request '{...}'","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"JSON request body","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--file path.json","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Load request from file (alternative to ","type":"text"},{"text":"--request","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--stream","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Enable streaming output","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--output path","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Save response JSON to path (file if ","type":"text"},{"text":".json","type":"text","marks":[{"type":"code_inline"}]},{"text":" suffix, otherwise directory); use distinct filenames across calls to avoid overwriting","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--print-response","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Print response to stdout","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--model ID","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Override model (also settable in request JSON)","type":"text"}]}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Model priority","type":"text","marks":[{"type":"strong"}]},{"text":": ","type":"text"},{"text":"--model","type":"text","marks":[{"type":"code_inline"}]},{"text":" CLI flag > ","type":"text"},{"text":"\"model\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" field in ","type":"text"},{"text":"--request","type":"text","marks":[{"type":"code_inline"}]},{"text":" JSON > built-in default.","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Verify Result","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Exit code ","type":"text"},{"text":"0","type":"text","marks":[{"type":"code_inline"}]},{"text":" + output contains valid JSON with ","type":"text"},{"text":"choices","type":"text","marks":[{"type":"code_inline"}]},{"text":" field → ","type":"text"},{"text":"success","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Non-zero exit, HTTP error, empty response, or JSON with ","type":"text"},{"text":"\"code\"","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"\"message\"","type":"text","marks":[{"type":"code_inline"}]},{"text":" error → ","type":"text"},{"text":"fail","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If agent cannot read exit codes, scan output for error patterns (","type":"text"},{"text":"Error","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"Traceback","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"401","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"403","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Post-execution check","type":"text","marks":[{"type":"strong"}]},{"text":": When ","type":"text"},{"text":"--output","type":"text","marks":[{"type":"code_inline"}]},{"text":" is used, verify the response JSON file exists and contains ","type":"text"},{"text":"choices","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"MANDATORY — stderr signal check","type":"text","marks":[{"type":"strong"}]},{"text":": After confirming the result, scan the command's stderr output for ","type":"text"},{"text":"[ACTION_REQUIRED]","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"[UPDATE_AVAILABLE]","type":"text","marks":[{"type":"code_inline"}]},{"text":". If either signal is present, you ","type":"text"},{"text":"MUST","type":"text","marks":[{"type":"strong"}]},{"text":" follow the instructions in ","type":"text"},{"text":"Update Check","type":"text","marks":[{"type":"link","attrs":{"href":"#update-check-mandatory-post-execution","title":null}}]},{"text":" below before responding to the user.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"On Failure","type":"text"}]},{"type":"paragraph","content":[{"text":"If the script fails, match the error output against the diagnostic table below to determine the resolution. If no match, read ","type":"text"},{"text":"execution-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/execution-guide.md","title":null}}]},{"text":" for alternative paths: curl commands (Path 2), Python SDK code generation (Path 3), and autonomous resolution (Path 5).","type":"text"}]},{"type":"paragraph","content":[{"text":"If Python is not available at all","type":"text","marks":[{"type":"strong"}]},{"text":" → skip directly to Path 2 (curl) in ","type":"text"},{"text":"execution-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/execution-guide.md","title":null}}]},{"text":".","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Error Pattern","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Diagnosis","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Resolution","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"command not found: python3","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Python not on PATH","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Try ","type":"text"},{"text":"python","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"py -3","type":"text","marks":[{"type":"code_inline"}]},{"text":"; install Python 3.9+ if missing","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Python 3.9+ required","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Script version check failed","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Upgrade Python to 3.9+","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"SyntaxError","type":"text","marks":[{"type":"code_inline"}]},{"text":" near type hints","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Python \u003c 3.9","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Upgrade Python to 3.9+","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"QIANWEN_API_KEY/DASHSCOPE_API_KEY not found","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Missing API key","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Obtain key from ","type":"text"},{"text":"QianWen Console","type":"text","marks":[{"type":"link","attrs":{"href":"https://platform.qianwenai.com/home/api-keys","title":null}}]},{"text":"; add to ","type":"text"},{"text":".env","type":"text","marks":[{"type":"code_inline"}]},{"text":": ","type":"text"},{"text":"echo 'DASHSCOPE_API_KEY=sk-...' >> .env","type":"text","marks":[{"type":"code_inline"}]},{"text":"; or run ","type":"text"},{"text":"qianwen-ops-auth","type":"text","marks":[{"type":"strong"}]},{"text":" if available","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"HTTP 401","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Invalid or mismatched key","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"qianwen-ops-auth","type":"text","marks":[{"type":"strong"}]},{"text":" (non-plaintext check only); verify key is valid","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"SSL: CERTIFICATE_VERIFY_FAILED","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"SSL cert issue (proxy/corporate)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"macOS: run ","type":"text"},{"text":"Install Certificates.command","type":"text","marks":[{"type":"code_inline"}]},{"text":"; else set ","type":"text"},{"text":"SSL_CERT_FILE","type":"text","marks":[{"type":"code_inline"}]},{"text":" env var","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"URLError","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"ConnectionError","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Network unreachable","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Check internet; set ","type":"text"},{"text":"HTTPS_PROXY","type":"text","marks":[{"type":"code_inline"}]},{"text":" if behind proxy","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"HTTP 429","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rate limited","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Wait and retry with backoff","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"HTTP 5xx","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Server error","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Retry with backoff","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"PermissionError","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Can't write output","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"--output","type":"text","marks":[{"type":"code_inline"}]},{"text":" to specify writable directory","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quick Reference","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Request Fields","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Field","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Type","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"prompt","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"messages","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"string | array","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"User input or message list","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"model","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"string","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Model ID (e.g. ","type":"text"},{"text":"qwen3.7-plus","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"system","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"string","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"System prompt (optional)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"temperature","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"float","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"0–2, controls randomness","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"max_tokens","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"int","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Max output tokens","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"tools","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"array","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Function definitions for tool calling","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"stream","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"bool","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Enable streaming (recommended for interactive use)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"enable_thinking","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"bool","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Enable thinking mode. Model defaults vary; check the model catalog above before overriding them. Adds latency for real-time tasks.","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Response Fields","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Field","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"text","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Generated text content","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"model","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Model used","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"usage","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Token usage (prompt_tokens, completion_tokens)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"tool_calls","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Function call requests (if tools used)","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Advanced Features","type":"text"}]},{"type":"paragraph","content":[{"text":"These are API-level features supported through request parameters. All use the same ","type":"text"},{"text":"chat/completions","type":"text","marks":[{"type":"code_inline"}]},{"text":" endpoint.","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Feature","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"How to Enable","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Notes","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Structured output","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"response_format: {\"type\": \"json_schema\", \"json_schema\": {...}}","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Force JSON output conforming to schema","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Web search","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"enable_search: true","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Real-time web search augmented responses","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Deep thinking","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"enable_thinking: true","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Extended reasoning; only when user requests it","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Function calling","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"tools: [...]","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Define functions for tool use","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Context cache","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Automatic for repeated prefixes; or explicit session-based","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Reduces cost for repeated context","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Partial mode","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Last message: ","type":"text"},{"text":"{\"role\": \"assistant\", \"content\": \"prefix…\", \"partial\": true}","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Continue/complete a prefix","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Batch inference","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Async batch API with JSONL input","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"50% cost discount","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"For detailed usage of each feature, see ","type":"text"},{"text":"api-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/api-guide.md","title":null}}]},{"text":" and ","type":"text"},{"text":"sources.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/sources.md","title":null}}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Error Handling","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Error","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cause","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Action","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"401 Unauthorized","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Invalid or missing API key","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"qianwen-ops-auth","type":"text","marks":[{"type":"strong"}]},{"text":" if available; else prompt user to set key (non-plaintext check only)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"429 Too Many Requests","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Rate limit exceeded","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Retry with backoff","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"500","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"502","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"503","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Server error","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Retry; check status page","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Invalid model","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Model ID not found","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Verify the ID against the model catalog above","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Invalid parameter","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Bad request body","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Validate JSON and field types","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"TypeError: ...proxies","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"openai SDK vs httpx incompatibility","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"pip install --upgrade openai","type":"text","marks":[{"type":"code_inline"}]},{"text":" (>=1.55.0); or use script (pure stdlib)","type":"text"}]}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Usage & billing","type":"text","marks":[{"type":"strong"}]},{"text":": Use the ","type":"text"},{"text":"qianwen-usage","type":"text","marks":[{"type":"strong"}]},{"text":" skill to check usage, free tier quota, and billing directly. Alternatively, the user can visit the QianWen console: ","type":"text"},{"text":"Usage Analytics","type":"text","marks":[{"type":"link","attrs":{"href":"https://platform.qianwenai.com/home/analytics","title":null}}]},{"text":" | ","type":"text"},{"text":"Pay-as-you-go Billing","type":"text","marks":[{"type":"link","attrs":{"href":"https://platform.qianwenai.com/home/billing/pay-as-you-go","title":null}}]},{"text":" | ","type":"text"},{"text":"Token Plan Subscription","type":"text","marks":[{"type":"link","attrs":{"href":"https://platform.qianwenai.com/home/billing/subscription/token-plan","title":null}}]}]},{"type":"paragraph","content":[{"text":"NEVER fabricate, guess, or construct usage/billing/console URLs.","type":"text","marks":[{"type":"strong"}]},{"text":" Only provide the exact links listed in this skill. If a URL is not listed here, do not invent one.","type":"text"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Output Location","type":"text"}]},{"type":"paragraph","content":[{"text":"Prefer the ","type":"text"},{"text":"current working directory","type":"text","marks":[{"type":"strong"}]},{"text":" for all outputs. Default subdirectory when ","type":"text"},{"text":"--output","type":"text","marks":[{"type":"code_inline"}]},{"text":" is used: ","type":"text"},{"text":"./output/qianwen-text/","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"Write prohibition","type":"text","marks":[{"type":"strong"}]},{"text":": NEVER write output files into this skill's installation directory or any ","type":"text"},{"text":"skills/","type":"text","marks":[{"type":"code_inline"}]},{"text":" hierarchy. All generated content must go to ","type":"text"},{"text":"output/","type":"text","marks":[{"type":"code_inline"}]},{"text":" under the current working directory or a user-specified path.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Update Check (MANDATORY Post-Execution)","type":"text"}]},{"type":"paragraph","content":[{"text":"After script execution, check stderr for action signals. The script automatically detects update status and emits structured signals. You MUST act on them. This section also applies when the user explicitly asks to check for updates.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Signal: ","type":"text"},{"text":"[ACTION_REQUIRED] qianwen-update-check skill is not installed","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"When stderr contains this signal, you MUST present the following options to the user and ","type":"text"},{"text":"wait for their response before proceeding","type":"text","marks":[{"type":"strong"}]},{"text":". Do NOT silently skip this.","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"The update-check skill is not installed. It keeps you informed about new QianWen-AI/qianwen-ai features and bug fixes.","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Install now","type":"text","marks":[{"type":"strong"}]},{"text":" — I'll run the install command for you","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Skip for now","type":"text","marks":[{"type":"strong"}]},{"text":" — do nothing this time","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never remind me","type":"text","marks":[{"type":"strong"}]},{"text":" — permanently suppress this prompt","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"After the user responds:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"User chooses ","type":"text"},{"text":"1","type":"text","marks":[{"type":"strong"}]},{"text":" → run: ","type":"text"},{"text":"npx skills add QianWen-AI/qianwen-ai --skill qianwen-update-check -y","type":"text","marks":[{"type":"code_inline"}]},{"text":", then run: ","type":"text"},{"text":"python3 \u003cthis-skill-scripts-dir>/gossamer.py --dismiss","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"User chooses ","type":"text"},{"text":"2","type":"text","marks":[{"type":"strong"}]},{"text":" → run: ","type":"text"},{"text":"python3 \u003cthis-skill-scripts-dir>/gossamer.py --dismiss","type":"text","marks":[{"type":"code_inline"}]},{"text":", then continue normally","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"User chooses ","type":"text"},{"text":"3","type":"text","marks":[{"type":"strong"}]},{"text":" → run: ","type":"text"},{"text":"python3 \u003cthis-skill-scripts-dir>/gossamer.py --never-install","type":"text","marks":[{"type":"code_inline"}]},{"text":", then continue normally","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Signal: ","type":"text"},{"text":"[UPDATE_AVAILABLE]","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"When stderr contains this signal, you MUST append a brief update notice to your response, including the version info and the update command shown in the stderr output.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"No signal in stderr","type":"text"}]},{"type":"paragraph","content":[{"text":"If stderr contains neither ","type":"text"},{"text":"[ACTION_REQUIRED]","type":"text","marks":[{"type":"code_inline"}]},{"text":" nor ","type":"text"},{"text":"[UPDATE_AVAILABLE]","type":"text","marks":[{"type":"code_inline"}]},{"text":", no action is needed — the skill is installed and up to date (or cached within 24h).","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Explicit user request","type":"text"}]},{"type":"paragraph","content":[{"text":"When the user explicitly asks to check for updates (e.g. \"check for updates\", \"check version\"):","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Look for ","type":"text"},{"text":"qianwen-update-check/SKILL.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" in sibling skill directories.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If found — run: ","type":"text"},{"text":"python3 \u003cqianwen-update-check-dir>/scripts/check_update.py --print-response","type":"text","marks":[{"type":"code_inline"}]},{"text":" and report the result.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If not found — present the install options above.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"References","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"execution-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/execution-guide.md","title":null}}]},{"text":" — Fallback paths (curl, SDK, autonomous), function calling, thinking mode","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"api-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/api-guide.md","title":null}}]},{"text":" — API supplementary guide with full code examples","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"sources.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/sources.md","title":null}}]},{"text":" — Official documentation URLs","type":"text"}]}]}]}]},"metadata":{"date":"2026-11-02","name":"qianwen-text","author":"@skillopedia","source":{"stars":120,"repo_name":"qianwen-ai","origin_url":"https://github.com/QianWen-AI/qianwen-ai/blob/HEAD/skills/text/qianwen-text/SKILL.md","repo_owner":"QianWen-AI","body_sha256":"327546c71739afae57c6091daf403f5fc6f84db2c54c55c87d8f5d6f2dd065c2","cluster_key":"2204a99299cef46146762190617b925bb79aae18a43d4df4fd6298a06589534d","clean_bundle":{"format":"clean-skill-bundle-v1","source":"QianWen-AI/qianwen-ai/skills/text/qianwen-text/SKILL.md","text_bytes":87315,"source_commit":"11b1805167d91bc931dbaad85e17036a72e98ae0","skills_sh_rank":3959,"attachment_count":11,"text_attachments":11,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"skills/text/qianwen-text/SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"ai-agent-development","category_label":"AI"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"ai-agent-development","import_tag":"skills-sh-top20k-2026-11","description":"Generate text, have conversations, write code, reason, and call functions with Qwen models. TRIGGER when: user asks to chat with Qwen, generate text, write code with Qwen, use Qwen function calling, or explicitly invokes this skill by name (e.g. use qianwen-text). DO NOT TRIGGER when: general coding questions without Qwen, non-Qwen AI model usage (OpenAI, Gemini, etc.), image/video understanding (use qianwen-vision), image/video/audio generation.","compatibility":"Requires Python 3.9+ and curl. Cursor: auto-loaded. Claude Code: read this skill's SKILL.md before first use."}},"renderedAt":1793671786688}

Qwen Text Chat (OpenAI-Compatible) Generate text, conduct conversations, write code, and invoke tools using Qwen models through the OpenAI-compatible API. This skill is part of QianWen-AI/qianwen-ai . Skill directory Use this skill's internal files to execute and learn. Load reference files on demand when the default path fails or you need details. | Location | Purpose | |-------------------------------------|-------------------------------------------------------------------------------------| | | Default execution — chat/completions request, streaming, output save | | | Fallback: curl, Pyth…