PicoBot/skills/lark-wiki/references/lark-wiki-delete-space.md
ooodc a7883dbed9 refactor(todo): 重构待办事项管理逻辑及更新状态规则
- 移除 TodoItem 中的 priority、created_at 和 updated_at 字段
- 强制每个任务都必须有唯一 id,且由用户负责生成
- 修改合并模式逻辑,merge=true 下保留未提及的旧任务
- 支持已完成和已取消任务重新激活(状态改回 pending 或 in_progress)
- 禁止 in_progress 状态退回到 pending,必须标记为 completed 或 cancelled
- 优化状态转换校验,允许特定状态间合法切换
- 简化任务变更消息,移除详细的新增/更新/移除统计
- 更新文档和示例,明确 id 必须由用户生成和使用
- 修复和补充测试,增强状态转换和合并模式验证
- 调整任务时间戳生成逻辑,统一使用当前时间及索引
- 该变更提供更合理的任务状态机械及管理模式,提升稳定性和易用性
2026-06-13 09:22:33 +08:00

206 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# wiki +delete-space
> **前置条件:** 先阅读 [`../lark-shared/SKILL.md`](../../lark-shared/SKILL.md) 了解认证、全局参数和安全规则。
删除一个飞书知识空间知识库。OpenAPI 对应 `DELETE /open-apis/wiki/v2/spaces/:space_id`
- **不可逆**:该操作会将知识空间连同其下所有节点彻底删除,执行前必须反复确认
- **同步 / 异步两种返回**
- 如果接口直接返回空 `task_id`说明删除同步完成shortcut 立即返回 `ready=true`
- 如果接口返回非空 `task_id`shortcut 会先对任务做有限轮询;轮询窗口内仍未完成会输出 `next_command`,引导调用方使用 `lark-cli drive +task_result --scenario wiki_delete_space --task-id <TASK_ID>` 继续查
## 命令
```bash
# 同步或异步删除一个知识空间(必须显式加 --yes 确认)
lark-cli wiki +delete-space \
--space-id <SPACE_ID> \
--yes
# 预览底层调用链(不会真的删除)
lark-cli wiki +delete-space \
--space-id <SPACE_ID> \
--dry-run
```
## 参数
| 参数 | 必填 | 说明 |
|------|------|------|
| `--space-id` | 是 | 要删除的知识空间 ID |
| `--yes` | 是(真删时) | 高风险写操作确认。不传则 CLI 直接返回 `unsafe_operation_blocked` 错误 |
## 行为说明
- **请求**:对 `/open-apis/wiki/v2/spaces/{space_id}` 发送 `DELETE`
- **同步返回**:响应 `data.task_id` 为空字符串时直接返回 `ready=true``failed=false``status_msg="success"`
- **异步返回**:响应 `data.task_id` 非空时进入有限轮询
- **任务轮询**:调用 `GET /open-apis/wiki/v2/tasks/{task_id}?task_type=delete_space`,读取 `data.task.delete_space_result.status`
- `status=success``ready=true`
- `status=failure` / `status=failed` → 返回错误(`wiki delete-space task failed: <status_msg 或 status>`
- 其他值(如 `processing``running`)→ 视为进行中,继续轮询
- **有限轮询窗口**:固定最多轮询 `30` 次,每次间隔 `2`
- **轮询超时不是失败**:如果窗口结束任务仍在处理中,会返回 `task_id``status``status_msg``ready=false``timed_out=true``next_command`
- **继续查询**:看到 `next_command` 后,改用 `lark-cli drive +task_result --scenario wiki_delete_space --task-id <TASK_ID>` 继续查
- **轮询请求全部失败时直接报错**如果任务已创建但后续每一次状态查询都失败shortcut 会返回带 hint 的错误,并给出继续查询命令
## 返回结果
### 同步删除
```json
{
"space_id": "7629741305993170448",
"ready": true,
"failed": false,
"status": "success",
"status_msg": "success"
}
```
### 异步删除完成
```json
{
"space_id": "7629741305993170448",
"task_id": "7631425120875056669-965458aec67417f5982250806c97950697ccb82f",
"ready": true,
"failed": false,
"status": "success",
"status_msg": "success"
}
```
### 异步轮询超时
```json
{
"space_id": "7629741305993170448",
"task_id": "7631425120875056669-965458aec67417f5982250806c97950697ccb82f",
"ready": false,
"failed": false,
"status": "processing",
"status_msg": "processing",
"timed_out": true,
"next_command": "lark-cli drive +task_result --scenario wiki_delete_space --task-id 7631425120875056669-965458aec67417f5982250806c97950697ccb82f --as user"
}
```
**输出字段说明:**
- `space_id`:入参的知识空间 ID
- `ready`:任务是否已经完成
- `failed`:任务是否已失败(显式返回 `failure` / `failed` 时为 `true`
- `task_id`:异步任务 ID仅异步场景返回
- `status` / `status_msg`:异步任务的原始状态和可读标签
- `timed_out``next_command`:轮询窗口内未完成时返回
## dry-run 编排
dry-run 会展示两步调用链:
1. `DELETE /open-apis/wiki/v2/spaces/{space_id}`
2. `GET /open-apis/wiki/v2/tasks/{task_id}?task_type=delete_space`(仅异步时真实发生)
## 权限说明
当前 shortcut 声明的权限为 `wiki:space:write_only``wiki:space:read`。前者用于发起删除请求,后者用于轮询同一命令内的异步任务状态;如果本地 token 缺失任一权限CLI 会直接提示重新执行 `lark-cli auth login --scope "wiki:space:write_only wiki:space:read"`
异步超时后的 `lark-cli drive +task_result --scenario wiki_delete_space --task-id <TASK_ID>` 只需 `wiki:space:read`(纯读任务状态)。
## 空间解析:如何拿到 `space_id`
`wiki +delete-space` 只接受 `--space-id` 作为目标。用户在对话里常常只说知识库的**名称**或贴一条**知识库 URL**,这时**不能**把名称 / URL 原样当成 `space_id` 传进去,必须先解析。三种输入路径:
### 1. 已经有 `space_id`
直接用,无需解析。
### 2. 只有知识库 URL`.../wiki/<token>`
```bash
lark-cli wiki spaces get_node \
--params '{"token":"<wiki_token>"}' \
--format json
```
读取 `data.node.space_id`
### 3. 只有知识库名称
调用 `wiki spaces list`
```bash
# 第一页
lark-cli wiki spaces list --format json
# 如果需要继续翻页(看下方停止条件),带上 page_token
lark-cli wiki spaces list --params '{"page_token":"<上一页返回的 page_token>"}' --format json
```
#### 翻页与匹配策略
**边翻边匹配**:每拿一页就在已累计的 items 上对 `name` 做精确匹配(区分大小写、保留空格),满足任一条件即停止翻页:
- (A) **累计精确匹配 ≥ 1 条** → 停止翻页,已找到目标
- (B) **`has_more=false`**(已翻完所有页)→ 停止翻页
结束后:
1. 如果累计精确匹配 ≥ 1把**所有**精确匹配作为候选列给用户
2. 如果精确匹配 = 0此时必然已走到 `has_more=false`,已收集全量 items在全量 items 上做**宽松匹配**`name` trim 空格 + 大小写不敏感 + 子串包含),作为候选
3. 宽松匹配也 0 条:停下来问用户是不是名字拼错、或者调用方没权限看到这个空间;**不要**自己改名字重试
> 不做更激进的归一化(比如去括号、去版本号尾缀),那些容易把 "客户台账(归档)" 误命中到 "客户台账"。
#### 早停的小边界
早停(条件 A意味着**可能漏掉**位于更后面页的同名空间。这种重名 corner case 由下面的"用户确认"兜底LLM 展示候选时应照抄 `name + space_id`,用户如果觉得不是自己想删的那一个,可以要求继续翻页。
#### 确认流程(硬约束)
**无论精确还是模糊,无论命中 1 条还是多条,发起删除前都必须先把候选列给用户**,由用户明确回选一个 `space_id`。不要因为"只命中一条"就跳过确认直接删。
列候选时至少包含以下字段,方便用户分辨:
- `name`(原始值,不做归一化)
- `space_id`
- `space_type``team` / `person` 等)
- `description`(若有)
- `visibility`(若有)
示例话术:
```text
根据 "客户台账" 找到以下候选:
1) name="客户台账", space_id=7629...0448, space_type=team, description="销售部"
2) name="客户台账(归档)", space_id=7629...0449, space_type=team, description="2023 以前"
请回复序号或 space_id 确认要删除的那一个;如果都不是请说明。
```
命中 0 条:停下来问用户是名称拼错了、还是调用方无权限看到这个空间;**不要**自动尝试改名字再查一次。
#### 执行删除
用户明确选定 `space_id` 后:
```bash
lark-cli wiki +delete-space --space-id <RESOLVED_SPACE_ID> --yes
```
> [!IMPORTANT]
> 删库不可逆。关键不变量:**发给服务端的 `--space-id` 必须是用户在上一轮对话里明确指认过的那一个**,不是 LLM 单方面"从匹配结果自动选"。
## 风险等级
- Risk**`high-risk-write`**
- 框架会强制要求 `--yes` 确认;不传 `--yes` 时命令会直接返回 `unsafe_operation_blocked` 错误,不会真的发请求
> [!CAUTION]
> `wiki +delete-space` 是**不可逆的写入操作**。执行前务必与用户再次确认 `--space-id`,并清楚该空间下的所有节点都会一并被删除。
## 参考
- [lark-wiki](../SKILL.md) -- 知识库全部命令
- [lark-shared](../../lark-shared/SKILL.md) -- 认证和全局参数
- [drive +task_result](../../lark-drive/references/lark-drive-task-result.md) -- 异步任务的续跑查询命令