Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

feat(output): 区分请求成功、业务成功与异步任务完成

Open
#32 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
28/100
Issue type
Feature
Clarity
Clearly specified
Activity status
Active
Tech stack
go

Research direction

Start with the listed entry points: internal/output/envelope.go, internal/api/response.go, cmd/api/api.go, internal/system/runner.go, internal/systemcmd/executor.go, and main.go; then read docs/design.md section 7.2. First establish the HTTP and business failure baseline for raw API, YAML, and Go action paths, then trace the shared output and exit code handling. Done means legacy behavior is covered and a selectable detailed mode preserves raw responses while distinguishing request, business, and task outcomes with the specified exit semantics.

Written by the indexing model from the issue text.

Description

背景与目标

Agent 需要明确区分:请求是否得到有效响应、上游业务是否接受/执行成功、异步任务是否最终完成。HTTP 200、CLI 退出 0、返回 task ID 都不足以独立证明用户目标已完成。

目标是建立可解释、可逐系统适配的结果契约,避免错误成功判断、重复提交作业,以及把未知状态当成功。

本 Issue 为需求与实现方案,新增字段/flag 名为建议,尚未实现。调研日期:2026-10-18;基线:80065f5。

当前行为:需要兼容而非直接改写

源码支持以下结论,尚未用真实蓝鲸环境复测:

  1. Envelope.APIResponse 的 ok 仅依据 HTTP 2xx;DryRun 返回 ok: true, dry_run: true。
  2. BuildResponseEnvelope 保留上游 body,没有公共业务结果分类器。
  3. raw API、YAML runner 和 Go action 公共执行器 在拿到响应后写出 JSON;普通路径中没有因 env.OK == false 自动返回进程错误。EnsureEnvelope 只检查 nil。因此,非 2xx 响应在成功输出后也可能退出 0。
  4. main.go 的退出码来自命令返回的错误;CLIError 当前区分 1(输入错误)和 2(运行时错误)。
  5. 设计契约 7.2 已明确 ok 的 HTTP 含义。静默改变它及既有退出码会影响脚本。

以上是公共路径结论,不代表所有具体命令均无额外检查;doctor 等诊断命令已有自身退出语义。

需求场景与状态模型

建议引入可选择的新结果模式,例如 --result-mode detailed。默认 legacy 模式保持现有输出和退出行为;新增模式提供如下分层事实:

层 建议状态 说明
request not_sent / responded / failed 是否发出并获得响应;另保留 HTTP status、http_ok、请求 ID
business succeeded / failed / unknown / not_evaluated 按明确接口契约判断;unknown 表示没有足够证据
task not_applicable / pending / running / succeeded / failed / canceled / unknown / not_evaluated 异步状态来自声明的状态查询协议,不能从 task ID 存在推断完成

建议结果中保留:

  • 原始 status、headers、data,不丢弃上游业务 body。
  • 可版本化的 outcome 对象,包含分层状态、判定来源/适配器、原始业务码,以及任务 ID/原始状态(如适用)。
  • 稳定的错误分类和下一步信息:认证失效、网关资源权限不足、业务 IAM 权限不足、限流、业务失败、未知协议。
  • 无法证实的字段省略或标 unknown,不凭接口名猜申请地址、任务状态、幂等性。

示意(非最终字段协议):

{
  "ok": true,
  "status": 200,
  "data": {"原始上游响应": "保留"},
  "outcome": {
    "version": "1",
    "request": {"state": "responded", "http_ok": true},
    "business": {"state": "succeeded", "source": "declared_action_contract"},
    "task": {"state": "pending", "id": "example-task-id"}
  }
}

这个示例表示提交成功、任务尚未完成;保留顶层 ok 的历史 HTTP 语义。示例中的 data 是说明占位,不声称某个真实接口返回该结构。

新模式的退出与输出建议
情况 detailed 模式行为
本地参数/协议选择错误 请求前失败,退出 1
网络失败、HTTP 非 2xx、已确认业务失败、已确认任务失败/取消 退出 2,保留可用的原始响应及分层事实
已确认业务成功、同步完成或任务成功 退出 0
已确认提交成功但 pending/running;或成功查询到任务仍在运行 退出 0,但明确 task 非终态;0 仅表示本次提交/查询成功,不承诺任务完成
收到响应但无法判定业务协议、预期状态字段缺失或出现未知任务状态 严格的新模式退出 2,结果标 unknown,不伪装成功
dry-run 本地预览成功 退出 0,request=not_sent,business/task=not_evaluated

收到 HTTP 响应时,stdout 保留一个完整结果 envelope,即使退出非 0;无响应的 CLI 错误沿用 stderr。避免同一错误在 stdout/stderr 输出两份相互不一致的 JSON。实现需调整现有“构造错误即打印”的边界,不能调用 PrintError 后再重复打印。

实现原理

请求构造与执行
  → HTTP 响应与原始 body
  → 以 gateway/action/协议版本明确选择的业务适配器
  → 可选任务状态适配器
  → 结果判定与退出码决策
  → 公共输出边界(之后才允许 --jq 展示投影)
  1. 通用 HTTP 层只提供事实,不扫描任意 JSON 中的 code 或 result 猜成功。
  2. 为已确认的系统协议注册纯分类函数;YAML 和 Go action 都能引用。code: 0、result: true、HTTP-only 等协议必须分别声明,未知 raw API 不自动套用其他系统的规则。
  3. 任务提交与任务查询采用不同适配规则。状态映射必须查真实接口文档/生产定义及 fixture,不能假设跨 JOB/PaaS/SOPS 共用数值枚举。
  4. 任务查询 HTTP 200 + 业务查询成功 + task failed 可以同时成立,三个层次都应保留;不能覆盖成单一布尔值。
  5. 结果分类器不主动刷新凭据、不自动申请权限、不重放提交请求。可重试性必须来自协议/幂等保证,不能仅按 5xx 推断。
  6. 后续等待入口可消费这些状态,设置总体截止时间并保留 task ID;超时/取消观察不能擅自把远端任务标 canceled,也不能重新提交任务。本 Issue 第一期不实现通用轮询引擎。

首批交付与依赖

  • 第一阶段:legacy/detailed 两种契约、HTTP/业务分类、统一输出和退出决策;先选择一个有明确成功/失败响应 fixture 的系统试点。
  • 第二阶段:JOB 提交、状态查询、日志路径的任务事实分类;验证后再接 PaaS。当前已存在 JOB 状态/日志命令,无需为了这一需求批量扩接口。
  • 与 #5 的快捷任务工作流衔接;与 #8 的错误 type/subtype/hint 设计统一命名,不同时建设两套错误分类。
  • “统一分页”需要按每页真实结果停止;“--jq”只能做展示,不能改变本层判定。
  • 新模式的最终 flag、字段名与退出协议需要在实现 PR 的设计评审中冻结;本 Issue 推荐兼容路径,不授权改变现有默认行为。

验收标准

  • 先建立现有 raw/YAML/Go 路径的 HTTP 200/403/500 及业务失败基线,明确 stdout、stderr、退出码。
  • legacy 模式输出和退出行为有回归覆盖。
  • HTTP 200 + 业务失败不会被 detailed 模式报告为业务成功。
  • HTTP 200 + 未知响应不默认成功;字段缺失、类型不符、未知状态有稳定 unknown 结果。
  • 提交成功与任务完成分离;查询成功但任务失败/运行中均可表达。
  • dry-run 不伪造业务/任务成功,不访问上游。
  • 网关权限与业务 IAM 权限可区分,原始错误码/请求 ID 保留。
  • 取消观察/等待超时不改变远端任务状态、不重复提交。
  • 配合 --jq 筛选、空输出或失败时,不把上游失败改成成功。
  • 每条失败路径只有约定的主结果/错误输出,无重复 envelope。

验证与参考

实现时使用 httptest 覆盖 HTTP/业务/任务组合及进程级退出语义,并运行适用的 fmt/lint/test/build、覆盖率和集成门禁。同步 docs/design.md、中英文 README、用户指南、公共/系统 Skills 和扩展契约说明。这次仅完成源码分析,未运行上述测试,也未验证线上任务状态枚举。

竞品参考:飞书成功/错误契约、飞书异步创建:等待完成且不重复创建、企业微信错误与退出约定。

配套需求

建议先冻结结果判定和聚合输出的契约,再让分页与 jq 共用输出边界。Affordance 可独立推进;jq 不需要等待全部系统的业务适配完成,但不得越过既有结果判定。以上属于配套关系,不要求四项合并为一个实现 PR。

Dominant language
Go
Stars
7
Forks
6
Avg merge
2d 19h
Merged PRs (30d)
14

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from TencentBlueKing/bk-cli

All issues in TencentBlueKing/bk-cli

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.