Metadata-Version: 2.4
Name: scnet-cli
Version: 0.1.0
Summary: SCNet 超算互联网 OpenAPI 命令行客户端
Author: fengyucn
Project-URL: Homepage, https://github.com/fengyucn/scnet
Classifier: Environment :: Console
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: System :: Distributed Computing
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: typer>=0.9
Requires-Dist: rich>=13.0
Requires-Dist: requests>=2.28

# scnet-cli

SCNet 超算互联网平台 OpenAPI 命令行客户端（公有云 CLI 风格），覆盖平台全部 API：
作业、文件、容器、Notebook、桌面 VNC、用户资源（成员）、模型服务（LLM）。

## 安装

```bash
pip install scnet-cli                # 依赖 typer / rich / requests
scnet --version
```

## 快速上手

```bash
# 1. 配置 AK/SK（个人中心 → 访问控制 下载授权码）与模型服务 API Key（可选）
scnet configure

# 2. 登录（获取各区域 token，缓存于 ~/.scnet/cache/）
scnet auth login

# 3. 常用查询
scnet job stats                 # 当前作业数量（运行/排队/保留/挂起/其他）
scnet job list --status running # 运行中的作业
scnet job detail 36082          # 作业详情（实时结束自动回退历史）
scnet usage walltime            # 已用机时
```

多区域账号：`scnet --cluster <clusterId> job list` 或在 configure 时设默认区域。

## 命令总览

| 组 | 命令 |
| --- | --- |
| `configure` | `configure` / `configure show` —— 配置 AK/SK、默认区域、模型服务 API Key |
| `auth` | `login` `renew` `whoami` `regions` —— token 获取/续约/校验、授权区域（hpcUrls 等） |
| `cluster` / `queue` | `cluster list`（调度器 ID）、`queue list`（可访问队列） |
| `job` | `stats` `list` `detail` `history` `logs` `submit` `delete` |
| `usage` | `walltime`（机时）`cores`（核心数）`storage`（存储配额） |
| `file` | `ls` `upload`（大文件自动分片）`download` `mkdir` `touch` `rm` `mv` `cp` `rename` `exists` `preview` `permission` `share` `unshare` `check` `async-cp` `async-mv` `async-rm` `task` `task-cancel` |
| `container` | `ls` `create` `start` `stop` `rm` `script` `spec` `detail` `url` `mounts` `resources` `groups` `images` |
| `notebook` | `ls` `create` `start` `stop` `release` `rename` `detail` `url` `custom-start` `custom-url` `resources` `images` `model-images` |
| `desktop` | `create` `ls` `rm` `url`（VNC 会话） |
| `member` | `ls` `jobs` `add` `quota`（团队成员/成员作业/配额） |
| `llm` | `models` `chat`（流式/交互）`ask`（Responses）`anthropic` `embed` `image` `video` `tts` `ocr` `ocr-rec` `doc-convert` `task` `task-cancel` `presign` |

全局选项：`--profile` `-p`、`--output table|json` `-o`、`--cluster` `-c`、`--debug`（打印等效 curl）。

## 示例

```bash
# 提交作业（命令行模式 / 脚本模式）
scnet job submit --name demo --queue debug --nodes 1 --ppn 4 --walltime 24:00:00 \
    --workdir /public/home/me/demo --cmd "python train.py"
scnet job submit --name slurm-job --queue debug --script /public/home/me/job.slurm --ppn 8

# 查看作业输出（自动定位 std.out，结束后按约定路径回退）
scnet job logs 36082
scnet job logs 36082 --err --trigger 2

# 上传/下载（>50MB 自动分片）
scnet file upload model.pt --to /public/home/me/
scnet file download /public/home/me/result.tar.gz --to D:\data\

# 大目录异步复制并跟踪任务
scnet file async-cp /public/home/me/dataset /public/home/me/backup
scnet file task <taskId>

# 模型服务（需 API Key；优先级 --api-key > 环境变量 SCNET_API_KEY > configure 保存值）
scnet llm models
scnet llm chat -m Qwen3.8-Max -p "用一句话介绍超算互联网"
scnet llm chat -m Qwen3.8-Max            # 交互模式
scnet llm image -m Qwen-Image-2.0 -p "一只橘猫" --size 1024x1024
scnet llm video -m Wan2.7-T2V -p "海边日落" --duration 5
```

## 认证与 token 说明（实现要点）

- **平台功能**：AK/SK 签名换 token（`POST api.scnet.cn/api/user/v3/tokens`，
  签名 = HMAC-SHA256(SK, `{"accessKey":…,"timestamp":…,"user":…}`) 小写 hex，秒级时间戳）。
  每个区域一个 token；`clusterId=0/ac` 为平台 token（认证/用户/成员/Notebook 创建启动），
  其余为区域 token（作业 `{hpcUrls}`、文件 `{efileUrls}`、容器/Notebook `{aiUrls}`，均取 `enable=="true"` 的 url）。
- **仅实现 AK/SK 登录**（已定决策）：官方另有用户名密码换 token 端点
  （`POST www.scnet.cn/ac/openapi/v2/tokens`，Header 带 user/password/orgId），
  但 orgId 为线下颁发给第三方的标记码、官方也明确不推荐该方式，故不接入。
- token 自动管理：JWT 内 `expireTime` 到期前自动续约（`/tokens/next`，过期超 24h 不可续约自动重新登录）；
  收到 `10008` 自动重登并重试一次。
- **模型服务**：`Authorization: Bearer <API Key>`（`sk-` 按量 / `sk-tp-` TokenPlan），与平台 token 无关。
- 作业接口的「用户名」用 center 返回的 `clusterUserInfo.userName`，不是登录账号。

## 测试

```bash
cd scnet-cli
python -m unittest discover -s tests
```

## 目录

```
src/scnet/
├── signing.py   AK/SK 签名（对照官方算法）
├── config.py    ~/.scnet/ 多 profile 配置 + token 缓存（SCNET_HOME 可重定向）
├── client.py    API 客户端（全组端点、token 生命周期、10008 重试、envelope 解析）
├── output.py    作业状态映射（实时/历史两套枚举）、时长格式化
├── runtime.py   命令层共用（客户端构建、错误处理、table/json 输出分发）
└── commands/    12 个命令组
tests/           unittest（签名/配置/客户端纯函数/状态映射）
```

## 已知边界（对照离线文档实现的注意事项）

- 本项目依据 `../openapi/`（2026-10-18 抓取的官方文档快照）实现，未用真实 AK/SK 逐接口联调；
  `--debug` 可打印等效 curl，遇到字段出入请对照 `openapi/api-doc/endpoints/<group>.json` 与
  `openapi/orig-html/` 原始页面核对。
- 文档个别接口参数风格混乱（如容器列表 GET 带 body、添加成员参数放 Header、merge 的 `indentifier` 拼写），
  实现均按官方 curl 示例照抄，必要时加兜底。
