Skip to content

feat: 自建命令框架重构 + 合入 main 新功能#90

Open
XXPermanentXX wants to merge 23 commits into
mainfrom
feat/self-built-framework
Open

feat: 自建命令框架重构 + 合入 main 新功能#90
XXPermanentXX wants to merge 23 commits into
mainfrom
feat/self-built-framework

Conversation

@XXPermanentXX

Copy link
Copy Markdown
Collaborator

概述

将 CLI 从旧命令框架重构为自建框架,并把 main 上按旧框架新增的功能全部迁移过来。分支拆成 core / runtime / commands / cli / kscli 五个包,命令与框架解耦。

架构改动

  • 内核:resolve/middleware 洋葱模型 + 声明式参数校验,bare command 显示帮助
  • 凭证:god Config 拆成 Identity / Settings / Credential,在 dispatch 边界一次解析;鉴权集中到 authStage + Client,命令必须声明 auth: "apiKey" | "console" | "none"
  • 命令签名:run(config, flags)run(ctx);options: [] 数组 → keyed 类型推导的 FlagsDef;yes / async / concurrent / 凭证 flag 按命令归属
  • 错误/退出:统一 UsageError,所有退出集中到 runtime 的 handleError
  • 输出:ANSI 样式集中,移除 --no-color(改走 NO_COLOR)

合入 main 的新功能(已迁移到新框架)

功能 说明
dataset(5) upload / list / get / delete / validate + core 校验器(chatml/dpo/cpt)
finetune(10) create / list / get / cancel / delete / logs / checkpoints / export / watch / capability
deploy(8) create / list / get / models / plans / scale / update / delete
knowledge search / chat(workspace 专属域名、多模态、SSE 流式、query-history)
token-plan(4) 席位管理,保留私有 AK/SK ACS3 签名(暂不收编进凭证域)
kscli packages/ragpackages/kscli 更名 + 独立发布
其他 advisor 意图识别(intent-detect-v3 并行)+ 召回算法更新、omni/speech 音色、video happyhorse 1.1、自动更新

⚠️ 破坏性行为差异(需周知)

  • 默认输出 json → text 翻转:不带 --output 时默认人读文本(不再按 TTY 自动 json)。脚本/agent 需显式 --output json
  • 破坏性操作必填 --yes:dataset delete、finetune create/cancel/delete、deploy create/delete/scale/update 不再交互确认,缺 --yes 直接 exit 2
  • flag 改名(规避全局保留 flag 撞名):deploy models --version--catalog-version;finetune watch --timeout--poll-timeout
  • advisor recommend:移除位置参数与交互追问,--message 必填(默认仍出 json)
  • token-plan AK/SK:只从 flag/env 解析,不再读 config.json
  • --output rich / --no-color / --non-interactive 移除;DASHSCOPE_ACCESS_TOKEN 不再用于 console 凭证

验证

  • vp check(格式 + lint + 类型)、build、单测全绿
  • deploy / finetune 命令族逐命令深度审计,零行为回归
  • 各命令族 --help / --dry-run / 本地校验冒烟通过
  • skill 参考文档已重新生成对齐真实 flag

建议 reviewer 重点回归

  • advisor:唯一手工缝合的重冲突(意图识别 + 召回算法),覆盖 single/pipeline、scoped/comparison/alternative 四种模式
  • finetune create:全链路(训练参数、数据集自动上传、扣配额前 --yes 门)
  • knowledge/ksclitoken-plan:真机对 workspace / POP API 回归

Commands now declare their credential requirement explicitly via a
required `auth: "apiKey" | "console" | "none"` field instead of the
boolean `skipDefaultApiKeySetup`. The runtime prepares credentials
based on this declaration and skips API-key setup under --dry-run.

- core: add AuthRequirement type and required `auth` field to
  Command/CommandSpec; drop skipDefaultApiKeySetup
- runtime: gate API-key setup on `auth === "apiKey" && !dryRun`
- commands: annotate all 45 commands (apiKey 25 / console 11 / none 9)
…tion

把 main 从一堆 if + process.exit 重构为「argv 解析成数据 → 交给统一管线执行」。

内核
- resolve(argv) → Resolution(version/help/run/usageError):路由即数据,dispatch 只 switch
- compose 洋葱中间件 (versionCheck/telemetry/auth/runCommand),命令仍收 (config, flags)
- registry.locate() 统一 leaf/group/unknown,取代 isGroupPath + 抛异常的 resolve
- 删除 command-help.ts 全局可变单例:help 渲染收口到错误边界

错误模型
- 新增 UsageError(写错了 → exit 2) 与 IncompleteCommandError(没写完 → 打 help、exit 0)
- version / help / onboarding / 组帮助统一由 resolve 产出、dispatch 分派

参数与校验
- parseFlags 重写:无 positional、新增 switch 类型、值/类型/重复校验
- 无条件必填 → 解析器声明式强制 (OptionDef.required)
- 跨 flag / 条件约束 → 新增 command.validate(flags) 钩子
  (text-chat / search-web / speech / vision / video-ref)
- 移除全部交互式输入 (promptText/Select/Confirm),缺输入直接打 help

输出
- detectOutputFormat 默认 text,不再按 TTY 切 json

测试
- 删除 3 个 stale cli 测试,runtime 单测重写 (29 passed),e2e 适配新行为
…ws help

- drop IncompleteCommandError: missing-required, failed validate, and bad/unknown
  flags are all UsageError now
- error boundary keys on bareness — bare command that fails → help (exit 0);
  non-bare invalid → error + message (exit 2)
- login: drop config.apiKey fallback, --api-key required-unless-console via validate
- speech: drop empty --text-file guard (empty content is the API's concern)
Replace the positional `OptionDef[]` array (key/type regex-parsed from
"--x <v>" strings) with a keyed `FlagsDef` record whose `type` drives both
runtime parsing and compile-time flag-type inference (`Flags<typeof DEF>`).
GLOBAL_FLAGS becomes the single source; the hand-kept GlobalFlags interface
(types/flags.ts) is deleted.

- core: SwitchFlag|ValueFlag union, ParsedFlags/Flags inference, defineCommand
  infers F from spec.flags
- runtime: parseFlags dispatches on def.type (switch/string/number/boolean/
  array/choices) with declarative required-flag enforcement
- commands: migrate every flag declaration to the keyed form
- naming: option→flag throughout (OptionDef→FlagDef, OptionsDef→FlagsDef,
  GLOBAL_OPTIONS→GLOBAL_FLAGS, command field options→flags), plus user-facing
  "Options:"→"Flags:" in help and the regenerated skill reference docs

Behavior-preserving aside from the intentional Options→Flags wording:
vp check clean across all packages, 29 parser tests pass, reference regen
byte-identical before the terminology swap.
Move all credential handling out of commands into one place. authStage
resolves the credential for the command's declared `auth` and bakes it into
`ctx.client`, gating (throw) when missing; commands reach the network only
through `ctx.client` and never touch tokens or baseUrl.

- add Client (request/requestJson/uploadFile/mcp/console/url) wrapping the
  token + baseUrl; commands call it instead of self-resolving
- run(config, flags) → run(ctx) + CommandContext; migrate all 45 commands
- split domains: model = pure api-key (drop access-token fallback), console =
  config.json only (drop DASHSCOPE_ACCESS_TOKEN env)
- consolidate env reads in loadConfig; CredentialSource = flag | env | config;
  priority flag > env > config
- endpoints return paths (xxxPath) instead of full URLs; baseUrl owned by Client
- auth status now uses describeAuth
- video/download: auth "none" → "apiKey" (it needs the model API)
- dedupe fetchModelList behind an injected console-call function
- remove ensureApiKey/ensure-key.ts, prompt.ts + isInteractive, and the old
  resolveCredential/resolveConsoleGatewayCredential resolvers
- tests: adapt auth.e2e to the new auth status shape; drop the
  DASHSCOPE_ACCESS_TOKEN branch from console-readiness gates
AK/SK signing was used only by `knowledge retrieve`'s deprecated fallback,
which the api-key auth gate now makes unreachable. Drop it; the command is
pure api-key.

- knowledge/retrieve: remove the AK/SK path + --access-key-id/secret/workspace-id
  flags; api-key only
- delete client/ak-sign.ts and its signRequest/AkSignConfig exports
- drop access_key_id/access_key_secret from config schema, loader, and
  `config show` / `config set`
- remove the now-unused PascalCase KnowledgeRetrieve request/response types
Commands no longer call process.exit() directly. Every failure now throws
UsageError (bad input → exit 2) or BailianError (runtime failure, with
AUTH/TIMEOUT codes), so the runtime's handleError stays the single exit
point and telemetry always flushes.

- convert 27 process.exit() sites across 15 commands to throws
- move cross-flag/value checks into validate(); use flag `choices` for
  --events / --sort; drop dead --model required check
- keep pipeline's process.exitCode for lint-style soft failures
- enforce with unicorn/no-process-exit, allowed only in runtime/tools/tests
- fix incidental lint: void floating run(), narrow console errorCode,
  align generate-reference type imports to source
Missing required flags now throw UsageError (exit code 2, error on
stderr, JSON under --output json) instead of printing help and exiting
0. Update assertions and titles accordingly:

- missing-flag cases: exitCode 0/1 -> 2, retitle to "errors as usage error (2)"
- auth / video-task-get under --output json: assert the error JSON on stderr
- proxy probe: import setupProxyFromEnv from runtime/src/proxy.ts
- drop tests for the removed config export-schema command
- fix t2v dry-run: cliTimeoutPrefix misplaced between --model and its value
- drop the CI / non-TTY early-return so agents see "Update available" too
- widen check interval 4h→24h; stay silent inside the window (no per-command repeat)
- remove orphan isCI() helper (zero callers)
- versioning.md: drop the now-false "banner suppressed under agent" rationale
…solved at the dispatch boundary

- commands consume a narrowed context (identity/settings/own flags/client);
  config/auth commands additionally use configStore()/authStore() accessors
- resolution happens once at dispatch: buildSources/buildSettings plus
  per-domain credential resolvers; dry-run tolerates missing credentials
- transport takes structured deps; credentials are injected only by Client;
  console gateway takes a resolved target with optional token (anonymous
  catalog calls); pipeline steps and advisor run against client/settings
- telemetry receives authMethod as a value; global/command flags are split
  at dispatch with a same-type shadowing guard at registry build
- behavior change: base URL resolution now prefers DASHSCOPE_BASE_URL env
  over config file base_url (unified flag > env > file > default chain)
- priority chains, store semantics and command capability boundaries are
  locked by unit tests
- flags split into GLOBAL_FLAGS (all commands) plus MODEL_AUTH_FLAGS /
  CONSOLE_AUTH_FLAGS, parsed only for commands of the matching auth
  domain; cross-domain flags now fail with "Unknown flag" instead of
  being silently ignored
- all shadow redeclarations removed; the registry guard now rejects any
  own flag named after a reserved (global or visible-domain) flag
- --workspace-id joins the console domain (chain: flag > env > file);
  usage stats drops its private declaration and in-command priority
- auth login declares its credential args as own command parameters
  (--api-key / --base-url / --console-site, original behavior intact);
  auth status no longer accepts credential-domain overrides (use env or
  config set instead)
- command help and the generated reference both show Flags (own + auth
  domain) plus a full Global Flags section, replacing the footer hint
- breaking: pipeline run --timeout renamed to --step-timeout (collided
  with the global request timeout)
- remove nonInteractive plus yes/async/concurrent from GLOBAL_FLAGS and Settings;
  command dispatch no longer resolves command-only switches into global settings
- add shared ASYNC_FLAG / CONCURRENT_FLAG definitions for commands that actually
  support task-only return or parallel requests
- keep quota downgrade protection by moving --yes onto quota request and reading
  flags.yes for confirmed downgrade submission
- update existing async/concurrent consumers to read own flags; no new capability
  matrix entries are added
- refresh generated command reference and remove stale --non-interactive usage
  from e2e/stress invocations
- scope image/video task execution to --async and --concurrent
- add concurrent task fan-out for video edit and video ref
- extend image edit to the async image task path
- refresh e2e coverage and generated command references
- remove --no-color from GLOBAL_FLAGS and drop Settings.noColor
- move ANSI styling decisions into runtime color helpers with NO_COLOR support
- update command text renderers to use shared color helpers instead of local ANSI codes
- refresh e2e invocations, generated reference, and agent skill guidance
- add openapi auth requirement with command-scoped access key flags and paired credential resolution
- persist OpenAPI credentials through auth login/status/logout using access_key_* config fields
- route token-plan commands through the centralized ACS signing client
- keep legacy openapi_access_key_* config readable while rejecting it as a new config set key
- refresh docs, generated references, telemetry authMethod, and e2e coverage
- render auth flag sections only for auth domains used by registered commands
- make quick-start prompts opt-in through createCli options
- keep the existing quick-start prompts wired only for bl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant