@lovrabet/lovrabet-cli 2.1.23 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -10
- package/lib/cli.js +1 -1
- package/lib/commands/api-doc/index.js +1 -1
- package/lib/commands/app/cache.js +1 -1
- package/lib/commands/app/definitions.js +1 -1
- package/lib/commands/app/eligibility.js +1 -1
- package/lib/commands/app/mock-loader.js +1 -1
- package/lib/commands/app/remote-source.js +1 -1
- package/lib/commands/app/shared.js +1 -1
- package/lib/commands/app-config/get.js +1 -1
- package/lib/commands/app-config/index.js +1 -1
- package/lib/commands/artifact/index.js +1 -1
- package/lib/commands/auth/device.js +1 -1
- package/lib/commands/auth/index.js +1 -1
- package/lib/commands/auth/prompt.js +1 -1
- package/lib/commands/bff/detail.js +1 -1
- package/lib/commands/bff/exec.js +1 -1
- package/lib/commands/bff/index.js +1 -1
- package/lib/commands/cli-skill/index.js +1 -1
- package/lib/commands/common/config-policy.js +1 -1
- package/lib/commands/common/constraints.js +1 -1
- package/lib/commands/common/flags.js +1 -1
- package/lib/commands/common/local-file.js +1 -1
- package/lib/commands/config/definitions.js +1 -1
- package/lib/commands/config/shared.js +1 -1
- package/lib/commands/data/index.js +1 -1
- package/lib/commands/dataset/detail.js +1 -1
- package/lib/commands/dataset/index.js +1 -1
- package/lib/commands/dataset/list.js +1 -1
- package/lib/commands/dataset/sdk-doc.js +1 -1
- package/lib/commands/doctor.js +1 -1
- package/lib/commands/file/index.js +1 -1
- package/lib/commands/init.js +1 -1
- package/lib/commands/kb/index.js +1 -1
- package/lib/commands/logs/index.js +1 -1
- package/lib/commands/ocr/index.js +1 -1
- package/lib/commands/personal-bff/index.js +1 -1
- package/lib/commands/registry.js +1 -1
- package/lib/commands/schedule/index.js +1 -1
- package/lib/commands/schema.js +1 -1
- package/lib/commands/service/dynamic.js +1 -1
- package/lib/commands/service/function-name-adapter.js +1 -1
- package/lib/commands/service/index.js +1 -1
- package/lib/commands/service/registry.js +1 -1
- package/lib/commands/skill/commands/create.js +1 -1
- package/lib/commands/skill/commands/diagram.js +1 -1
- package/lib/commands/skill/commands/install.js +1 -1
- package/lib/commands/skill/commands/list.js +1 -1
- package/lib/commands/skill/commands/push.js +1 -1
- package/lib/commands/skill/commands/validate.js +1 -1
- package/lib/commands/skill/diagram.js +1 -1
- package/lib/commands/skill/flags.js +1 -1
- package/lib/commands/skill/index.js +1 -1
- package/lib/commands/skill/manifest-helpers.js +1 -1
- package/lib/commands/skill/push-execute.js +1 -1
- package/lib/commands/skill/push-flow-helpers.js +1 -1
- package/lib/commands/skill/push-retarget.js +1 -1
- package/lib/commands/skill/scopes.js +1 -1
- package/lib/commands/skill/summary.js +1 -1
- package/lib/commands/skill/templates.js +1 -1
- package/lib/commands/skill/validate.js +1 -1
- package/lib/commands/sql/detail.js +1 -1
- package/lib/commands/sql/exec.js +1 -1
- package/lib/commands/sql/index.js +1 -1
- package/lib/commands/update.d.ts +2 -2
- package/lib/commands/update.js +1 -1
- package/lib/commands/workspace/index.js +1 -1
- package/lib/config/schema.js +1 -1
- package/lib/constant/app.js +1 -1
- package/lib/constant/auth-mode.js +1 -1
- package/lib/constant/cli.js +1 -1
- package/lib/constant/defaults.js +1 -1
- package/lib/constant/distribution.js +1 -1
- package/lib/constant/domain.js +1 -1
- package/lib/constant/env.js +1 -1
- package/lib/constant/output.js +1 -1
- package/lib/constant/product.js +1 -1
- package/lib/constant/risk.js +1 -1
- package/lib/constant/url.js +1 -1
- package/lib/context.js +1 -1
- package/lib/core/api-client.js +1 -1
- package/lib/core/db-resolver.js +1 -1
- package/lib/core/sdk-client.js +1 -1
- package/lib/errors.js +1 -1
- package/lib/framework/build-all-flags.js +1 -1
- package/lib/framework/dryrun.js +1 -1
- package/lib/framework/flags.js +1 -1
- package/lib/framework/help.js +1 -1
- package/lib/framework/index.js +1 -1
- package/lib/framework/output.js +1 -1
- package/lib/framework/preparse.js +1 -1
- package/lib/framework/rate-limit.js +1 -1
- package/lib/framework/raw-flags.js +1 -1
- package/lib/framework/response.js +1 -1
- package/lib/framework/runner-confirmation.js +1 -1
- package/lib/framework/runner-error.js +1 -1
- package/lib/framework/runner.js +1 -1
- package/lib/framework/schema-export.js +1 -1
- package/lib/framework/service-order.js +1 -1
- package/lib/framework/types.js +1 -1
- package/lib/generated/build-info.d.ts +4 -4
- package/lib/generated/build-info.js +1 -1
- package/lib/help.js +1 -1
- package/lib/postinstall.d.ts +2 -0
- package/lib/postinstall.js +1 -0
- package/lib/runtime/confirmation.js +1 -1
- package/lib/runtime/event.js +1 -1
- package/lib/runtime/index.js +1 -1
- package/lib/runtime/queue.js +1 -1
- package/lib/runtime/resolve.js +1 -1
- package/lib/skills/builtin-skill.d.ts +37 -0
- package/lib/skills/builtin-skill.js +1 -0
- package/lib/skills/npx-skills-add.d.ts +3 -1
- package/lib/skills/npx-skills-add.js +1 -1
- package/lib/skills/runtime-skill-sync/constants.js +1 -1
- package/lib/skills/runtime-skill-sync/fs-utils.js +1 -1
- package/lib/skills/runtime-skill-sync/hashing.js +1 -1
- package/lib/skills/runtime-skill-sync/install-target.js +1 -1
- package/lib/skills/runtime-skill-sync/links.js +1 -1
- package/lib/skills/runtime-skill-sync/list-local.js +1 -1
- package/lib/skills/runtime-skill-sync/local-files.js +1 -1
- package/lib/skills/runtime-skill-sync/materialize.js +1 -1
- package/lib/skills/runtime-skill-sync/metadata.js +1 -1
- package/lib/skills/runtime-skill-sync/paths.js +1 -1
- package/lib/skills/runtime-skill-sync/push.js +1 -1
- package/lib/skills/runtime-skill-sync/scopes.js +1 -1
- package/lib/skills/runtime-skill-sync/zip-codec.js +1 -1
- package/lib/skills/runtime-skill-sync/zip-package.js +1 -1
- package/lib/skills/runtime-skill-sync.js +1 -1
- package/lib/skills/skill-presence.js +1 -1
- package/lib/utils/apply-jq-filter.js +1 -1
- package/lib/utils/logger.js +1 -1
- package/lib/utils/lossless-json.js +1 -1
- package/lib/utils/params.js +1 -1
- package/lib/utils/platform.js +1 -1
- package/lib/utils/update-notice.js +1 -1
- package/lib/utils/version.js +1 -1
- package/lib/utils/write-cli-side-channel.js +1 -1
- package/package.json +14 -3
- package/scripts/postinstall.mjs +24 -0
- package/skills/lovrabet/SKILL.md +702 -0
- package/skills/lovrabet/guides/app-resolution.md +165 -0
- package/skills/lovrabet/guides/dataset-and-data-workflow.md +170 -0
- package/skills/lovrabet/guides/sql-and-bff-workflow.md +132 -0
- package/skills/lovrabet/guides/troubleshooting.md +91 -0
- package/skills/lovrabet/references/dataset-discovery-workflow.md +160 -0
- package/skills/lovrabet/references/instant-api-workflow.md +259 -0
- package/skills/lovrabet/references/lovrabet-app-config.md +51 -0
- package/skills/lovrabet/references/lovrabet-app.md +113 -0
- package/skills/lovrabet/references/lovrabet-auth.md +136 -0
- package/skills/lovrabet/references/lovrabet-bff-workflow.md +139 -0
- package/skills/lovrabet/references/lovrabet-config-commands.md +104 -0
- package/skills/lovrabet/references/lovrabet-config.md +124 -0
- package/skills/lovrabet/references/lovrabet-doctor.md +26 -0
- package/skills/lovrabet/references/lovrabet-file-workflow.md +62 -0
- package/skills/lovrabet/references/lovrabet-kb-workflow.md +78 -0
- package/skills/lovrabet/references/lovrabet-logs.md +19 -0
- package/skills/lovrabet/references/lovrabet-ocr-workflow.md +83 -0
- package/skills/lovrabet/references/lovrabet-output-format-jq.md +40 -0
- package/skills/lovrabet/references/lovrabet-personal-bff-workflow.md +108 -0
- package/skills/lovrabet/references/lovrabet-schedule-workflow.md +175 -0
- package/skills/lovrabet/references/lovrabet-service-tree.md +279 -0
- package/skills/lovrabet/references/lovrabet-skill-authoring.md +128 -0
- package/skills/lovrabet/references/lovrabet-skill-install.md +34 -0
- package/skills/lovrabet/references/lovrabet-skill-sync.md +146 -0
- package/skills/lovrabet/references/lovrabet-sql-workflow.md +111 -0
- package/skills/lovrabet/references/lovrabet-update.md +34 -0
- package/skills/lovrabet/references/lovrabet-workspace.md +82 -0
- package/skills/lovrabet.manifest.json +38 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Dataset Discovery Workflow
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
在执行 Instant API 数据操作前,需要先找到目标数据集并了解其字段结构。
|
|
6
|
+
|
|
7
|
+
## 先不要默认查 app
|
|
8
|
+
|
|
9
|
+
`dataset` 工作流的第一步不是固定的 `app list`,而是先判断当前是否已经有明确 app 上下文。
|
|
10
|
+
|
|
11
|
+
### 直接进入数据集发现
|
|
12
|
+
|
|
13
|
+
以下情况可以直接执行 `dataset list`:
|
|
14
|
+
|
|
15
|
+
- 用户已经给了 `--appcode`
|
|
16
|
+
- 用户已经给了 `--app <name>`
|
|
17
|
+
- 当前问题明显是在上文已确认的同一 app 里继续操作
|
|
18
|
+
- 用户明确说“当前应用”“默认应用”,且没有新的业务域线索
|
|
19
|
+
|
|
20
|
+
`defaultApp` 只是默认候选。用户提到订单、商品、库存、客户、证照等业务对象且未显式指定 app 时,先在默认候选里按关键词查数据集;命中合理再继续,无命中或不合理再扩大到 app 目录。
|
|
21
|
+
|
|
22
|
+
### 需要先做应用决议
|
|
23
|
+
|
|
24
|
+
以下情况应先获取应用信息,再决定目标 app:
|
|
25
|
+
|
|
26
|
+
- 用户只说了业务需求,没有给 app 线索
|
|
27
|
+
- 当前没有显式 `--appcode` / `--app`,且需求包含业务域或数据对象线索
|
|
28
|
+
- 需求描述可能对应多个业务应用
|
|
29
|
+
- 已经在 `defaultApp` 下按关键词验证过,但没有合理数据集命中
|
|
30
|
+
|
|
31
|
+
若当前有 `defaultApp`,推荐先执行:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
lovrabet dataset list --name "<关键词>"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
默认候选无命中、弱命中或语义不合理时,再执行:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
lovrabet app list
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
再根据业务关键词挑 1-2 个候选应用,执行:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
lovrabet dataset list --app <name> --name "<关键词>"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
通过数据集命中结果反向确认 app,而不是只看 app 名称猜测。
|
|
50
|
+
|
|
51
|
+
## 命令
|
|
52
|
+
|
|
53
|
+
### api-doc list/detail — 查看运行态 API 文档
|
|
54
|
+
|
|
55
|
+
写 personal BFF 或复杂数据访问说明前,先用 API 文档收敛可用接口:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
lovrabet api-doc list --category dataset
|
|
59
|
+
lovrabet api-doc list --keyword aggregate
|
|
60
|
+
lovrabet api-doc detail --code dataset_data_filter
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`api-doc` 是只读文档发现命令,不是通用 HTTP fetch;不要把它替代成任意路径调用。
|
|
64
|
+
|
|
65
|
+
### dataset list — 列出数据集
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# 列出全部
|
|
69
|
+
lovrabet dataset list
|
|
70
|
+
|
|
71
|
+
# 按名称过滤(服务端模糊匹配)
|
|
72
|
+
lovrabet dataset list --name "订单"
|
|
73
|
+
|
|
74
|
+
# 按 code 过滤(服务端精确匹配)
|
|
75
|
+
lovrabet dataset list --code "abc123def4567890abcdef012345678"
|
|
76
|
+
|
|
77
|
+
# JSON 格式输出(AI Agent 推荐)
|
|
78
|
+
lovrabet dataset list --format json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
返回字段: id, code, name, source, description, table, datasetKey, pk, **fields**
|
|
82
|
+
|
|
83
|
+
其中 `fields` 是从 `dbtableConfig.allFields` 解析出的字段名数组,可直接用于构造 `data filter` 的 `select` 和 `where` 参数,无需再调 `dataset detail`。
|
|
84
|
+
|
|
85
|
+
| Flag | 类型 | 必填 | 说明 |
|
|
86
|
+
|------|------|------|------|
|
|
87
|
+
| `--name` | string | 否 | 按名称模糊过滤(服务端) |
|
|
88
|
+
| `--code` | string | 否 | 按 dataset code 精确过滤(服务端,32 位 hex) |
|
|
89
|
+
| `--format` | string | 否 | 输出格式:`json` / `pretty` / `table` |
|
|
90
|
+
|
|
91
|
+
### dataset detail — 查看数据集结构
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
lovrabet dataset detail --code <datasetCode>
|
|
95
|
+
|
|
96
|
+
# 返回 CLI 归一化 JSON 结构
|
|
97
|
+
lovrabet dataset detail --code <datasetCode> --format json
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
| Flag | 类型 | 必填 | 说明 |
|
|
101
|
+
|------|------|------|------|
|
|
102
|
+
| `--code` | string | **是** | 数据集 code(32 位 hex UUID) |
|
|
103
|
+
| `--format` | string | 否 | 输出格式:`json` / `pretty` / `compress` |
|
|
104
|
+
|
|
105
|
+
返回内容:
|
|
106
|
+
- **字段列表** — name, displayName, type, dbType, pk, required, description, options
|
|
107
|
+
- **关联信息** — `relations` 直接透出接口返回的原始关联信息;结构以服务端返回为准,CLI 不做补全推断
|
|
108
|
+
- **操作列表** — name, method, path(getList, getOne, create, update, delete 等)
|
|
109
|
+
- **统计** — fieldCount, operationCount
|
|
110
|
+
|
|
111
|
+
当运行态详情接口未返回 `fields` / `properties` 时,CLI 会从 `dataset list` 兜底字段名,保证 `fieldCount` 和字段名可用于 `data filter`;此时类型、必填、选项等详细字段属性可能为空。
|
|
112
|
+
|
|
113
|
+
### dataset sdk-doc — 查看 SDK 使用文档
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
lovrabet dataset sdk-doc --code <datasetCode>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`dataset sdk-doc` 只接受 32 位数据集 code,不接受数字 ID。返回为空时,CLI 会给出稳定的空文档提示。
|
|
120
|
+
|
|
121
|
+
## 典型工作流
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# 0. 如果默认候选验证不成立,再看应用目录
|
|
125
|
+
lovrabet app list
|
|
126
|
+
|
|
127
|
+
# 1. 在候选 app 中搜索数据集
|
|
128
|
+
lovrabet dataset list --app crm --name "公司"
|
|
129
|
+
|
|
130
|
+
# 2. 命中后查看字段结构
|
|
131
|
+
lovrabet dataset detail --code 2874b19935c240659e8872e9e2416ae3
|
|
132
|
+
|
|
133
|
+
# 3. 确认字段名后,开始 Instant API 数据操作
|
|
134
|
+
lovrabet data filter --code 2874b19935c240659e8872e9e2416ae3 \
|
|
135
|
+
--params '{"where":{"name":{"$contain":"test"}},"currentPage":1,"pageSize":20}'
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
如果当前 app 已明确,则直接:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# 1. 搜索数据集
|
|
142
|
+
lovrabet dataset list --name "公司"
|
|
143
|
+
|
|
144
|
+
# 2. list 已返回 fields 数组,可直接用于构造查询
|
|
145
|
+
# 如果需要字段类型等详细信息,再调 detail
|
|
146
|
+
lovrabet dataset detail --code 2874b19935c240659e8872e9e2416ae3
|
|
147
|
+
|
|
148
|
+
# 3. 确认字段名后,开始 Instant API 数据操作
|
|
149
|
+
lovrabet data filter --code 2874b19935c240659e8872e9e2416ae3 \
|
|
150
|
+
--params '{"where":{"name":{"$contain":"test"}},"currentPage":1,"pageSize":20}'
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## 注意事项
|
|
154
|
+
|
|
155
|
+
1. 使用 `--format json` 获取结构化输出,便于程序解析
|
|
156
|
+
2. `dataset list` 返回的 `fields` 数组包含所有字段名,多数场景下无需额外调 `detail`
|
|
157
|
+
3. `dataset detail` 返回的字段兼容 v1(properties)和 v2(fields)两种数据集格式;运行态接口未给完整字段时会兜底字段名
|
|
158
|
+
4. 数据集的 code 是 32 位 hex UUID,是所有 `data *` 命令的必填参数
|
|
159
|
+
5. 当业务需求不明确落在哪个 app 时,先验证 `defaultApp`;验证不成立再 `app list`,并用 `dataset list --app <name> --name <关键词>` 做验证式收敛
|
|
160
|
+
6. 写 personal BFF 或其他数据访问源码前,除非用户已经提供明确数据,否则先用 `api-doc`、`dataset detail`、`dataset sdk-doc` 和只读 `data` 命令确认真实结构
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# Instant API Workflow
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
通过运行态 CLI 对数据集记录进行增删改查和聚合统计。`Instant API` 分组下的所有 `data` 子命令共享统一接口:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
lovrabet data <command> --code <datasetCode> --params '<json>'
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
- `--code`:数据集 code(路由标识,必填)
|
|
12
|
+
- `--params`:JSON 请求体,直接透传给运行态 API
|
|
13
|
+
|
|
14
|
+
## data 之前如何确定 app
|
|
15
|
+
|
|
16
|
+
`data` 子命令本身只依赖 `dataset code`,但这个 `dataset code` 总是来自某个具体 app。
|
|
17
|
+
|
|
18
|
+
因此决策顺序应该是:
|
|
19
|
+
|
|
20
|
+
1. 先判断当前 app 是否已明确
|
|
21
|
+
2. 当前 app 明确时,直接 `dataset list --name ...`
|
|
22
|
+
3. 当前 app 不明确但有 `defaultApp` 时,先 `dataset list --name <关键词>` 验证默认候选
|
|
23
|
+
4. 默认候选无命中、弱命中或语义不合理时,再 `app list`
|
|
24
|
+
5. 再用 `dataset list --app <name> --name <关键词>` 收敛到正确 app
|
|
25
|
+
6. 拿到 `dataset code` 后,再执行 `data filter/getOne/create/batchCreate/update/delete`
|
|
26
|
+
|
|
27
|
+
不要直接在 app 未决议的情况下盲目构造 `data` 命令。
|
|
28
|
+
|
|
29
|
+
## 架构说明
|
|
30
|
+
|
|
31
|
+
7 个 data 子命令对应 7 个运行态 API 端点:
|
|
32
|
+
|
|
33
|
+
| 子命令 | 说明 | 风险等级 |
|
|
34
|
+
|--------|------|----------|
|
|
35
|
+
| `filter` | 条件查询(分页) | read |
|
|
36
|
+
| `getOne` | 按 ID 获取单条 | read |
|
|
37
|
+
| `aggregate` | 聚合统计(分组、求和、计数等) | read |
|
|
38
|
+
| `create` | 新建记录 | write |
|
|
39
|
+
| `batchCreate` | 批量新建同一数据集记录 | write |
|
|
40
|
+
| `update` | 更新记录 | write |
|
|
41
|
+
| `delete` | 删除记录(需 `--yes`) | high-risk-write |
|
|
42
|
+
|
|
43
|
+
`--params` JSON 就是 API 请求体,无额外封装。
|
|
44
|
+
|
|
45
|
+
### Backend Function HOOK
|
|
46
|
+
|
|
47
|
+
Backend Function HOOK 绑定到某个 Dataset 的一个具体 Instant API operation 及 BEFORE/AFTER 节点。Agent 不直接调用 HOOK;HOOK 是否已绑定必须来自可信业务 Skill 或平台已确认契约。绑定已确认时,执行对应的 `data` 命令会进入 Instant API 请求管线;服务端成功解析并加载绑定脚本时,HOOK 会在同一管线中执行。
|
|
48
|
+
|
|
49
|
+
`--dry-run` 不会触发 HOOK,它只预览 CLI 将发送的请求。基础访问权限由平台 RBAC 控制;HOOK 仅用于补充个性化校验和处理。已成功加载并执行的 BEFORE HOOK 失败时会阻止对应 Instant API 主操作;绑定查询或脚本加载异常会记录日志并跳过 HOOK,补充逻辑可能被跳过,因此不得把 HOOK 作为必须强制执行的合规或业务校验唯一保障。AFTER HOOK 失败时不能据此断言主操作已回滚,也不能直接重试。对于写操作,先按业务唯一键只读回查主记录和必要的后置结果,再依据可信的事务、幂等或可重试契约决定下一步。
|
|
50
|
+
|
|
51
|
+
### 超长整数标识
|
|
52
|
+
|
|
53
|
+
运行态数据中的 BIGINT 标识可能超过 JavaScript 安全整数范围。CLI 会在首次解析响应时把这类整数字面量保留为字符串,避免相邻标识被舍入成同一个值;`--params` 中超过安全范围的整数也会按字符串传递。业务编排仍应把商品、SKU、品牌等标识当作不透明字符串,不对标识执行算术、`Number(...)` 或 `parseInt(...)`。已经被其他工具解析成不安全 `number` 的值无法靠后续 `tostring` 恢复,应重新从无损边界读取。
|
|
54
|
+
|
|
55
|
+
## 各命令详解
|
|
56
|
+
|
|
57
|
+
### data filter — 条件查询
|
|
58
|
+
|
|
59
|
+
`where`、`select`、`orderBy`、`currentPage`、`pageSize` 必须放在同一个 `--params` JSON 对象中。它们不是独立 CLI flags;禁止使用 `--where`、`--select`、`--order-by`、`--current-page`、`--page`、`--page-size`。
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# 查全部(默认第一页)
|
|
63
|
+
lovrabet data filter --code <code> --params '{"orderBy":[{"id":"asc"}],"currentPage":1,"pageSize":20}'
|
|
64
|
+
|
|
65
|
+
# 带条件
|
|
66
|
+
lovrabet data filter --code <code> --params '{"where":{"status":{"$eq":"active"}},"orderBy":[{"id":"asc"}],"currentPage":1,"pageSize":20}'
|
|
67
|
+
|
|
68
|
+
# 翻页:完整复制上一页参数,只递增 currentPage
|
|
69
|
+
lovrabet data filter --code <code> --params '{"where":{"status":{"$eq":"active"}},"orderBy":[{"id":"asc"}],"currentPage":2,"pageSize":20}'
|
|
70
|
+
|
|
71
|
+
# 完整示例:条件 + 分页 + 排序 + 选字段
|
|
72
|
+
lovrabet data filter --code <code> --params '{
|
|
73
|
+
"where": {"$and":[{"status":{"$eq":"active"}},{"amount":{"$gte":100}}]},
|
|
74
|
+
"select": ["id","name","status"],
|
|
75
|
+
"orderBy": [{"id":"desc"}],
|
|
76
|
+
"currentPage": 1,
|
|
77
|
+
"pageSize": 20
|
|
78
|
+
}'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**--params 结构:**
|
|
82
|
+
|
|
83
|
+
| 字段 | 类型 | 说明 |
|
|
84
|
+
|------|------|------|
|
|
85
|
+
| `where` | object | 查询条件 |
|
|
86
|
+
| `select` | string[] | 返回字段列表 |
|
|
87
|
+
| `orderBy` | object[] | 稳定排序,例如按唯一字段 `[{"id":"asc"}]` |
|
|
88
|
+
| `currentPage` | number | 页码,从 1 开始 |
|
|
89
|
+
| `pageSize` | number | 每页条数;翻页时保持不变 |
|
|
90
|
+
|
|
91
|
+
翻页时必须保持 `where`、`select`、`orderBy`、`pageSize` 不变,只递增 `currentPage`。分页查询优先使用唯一且稳定的排序字段,避免跨页重复或遗漏。查询后可投影记录和分页元数据:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
lovrabet data filter --code <code> --params '{"where":{"status":{"$eq":"active"}},"orderBy":[{"id":"asc"}],"currentPage":2,"pageSize":20}' --format compress --jq '.data.result | {tableData, paging}'
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
确认 `paging.currentPage`、`paging.pageSize` 与请求一致,并检查 `tableData` 是否满足 `where`。条件未生效或返回形状异常时,本次结果不可作为业务结论;先修正查询,不要把未过滤内容解释为完整业务事实。
|
|
98
|
+
|
|
99
|
+
### data getOne — 单条查询
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
lovrabet data getOne --code <code> --params '{"id":123}'
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### data aggregate — 聚合统计
|
|
106
|
+
|
|
107
|
+
对数据集进行分组、求和、计数、平均值等聚合操作。
|
|
108
|
+
|
|
109
|
+
`aggregate` 仅支持单个 `DB_TABLE` 数据集;`METADATA` 数据集不支持 `aggregate` 或 Custom SQL。JOIN、跨表统计、数据库特有函数或 `aggregate` 无法表达的查询,应在编码前显式选择已有且契约可信的 Custom SQL;不要在运行时静默切换,也不要动态拼接 SQL。
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# 按状态分组求总金额
|
|
113
|
+
lovrabet data aggregate --code <code> --params '{
|
|
114
|
+
"aggregate": [{"column": "amount","type":"SUM","alias":"total"}],
|
|
115
|
+
"groupBy": ["status"]
|
|
116
|
+
}'
|
|
117
|
+
|
|
118
|
+
# 按地区统计活跃订单数
|
|
119
|
+
lovrabet data aggregate --code <code> --params '{
|
|
120
|
+
"aggregate": [{"column": "id","type":"COUNT","alias":"cnt"}],
|
|
121
|
+
"groupBy": ["region"],
|
|
122
|
+
"where": {"status":{"$eq":"active"}}
|
|
123
|
+
}'
|
|
124
|
+
|
|
125
|
+
# 多维聚合:按状态和地区分组,求总金额并按聚合结果排序
|
|
126
|
+
lovrabet data aggregate --code <code> --params '{
|
|
127
|
+
"aggregate": [{"column": "amount","type":"SUM","alias":"total"}],
|
|
128
|
+
"groupBy": ["status","region"],
|
|
129
|
+
"having": {"status":{"$notNull":true}},
|
|
130
|
+
"orderBy": [{"total":"desc"}]
|
|
131
|
+
}'
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**--params 结构:**
|
|
135
|
+
|
|
136
|
+
| 字段 | 类型 | 说明 |
|
|
137
|
+
|------|------|------|
|
|
138
|
+
| `aggregate` | object[] | **必填**。聚合定义列表 |
|
|
139
|
+
| `groupBy` | string[] | 分组字段 |
|
|
140
|
+
| `where` | object | 聚合前过滤(与 filter 相同的 where 语法) |
|
|
141
|
+
| `having` | object | 聚合后过滤;使用与 `where` 相同的对象结构,字段必须是真实数据集字段,不支持聚合别名 |
|
|
142
|
+
| `select` | string[] | 随聚合结果返回的原始字段 |
|
|
143
|
+
| `orderBy` | object[] | 排序;可以引用聚合输出别名,如 `[{"total":"desc"}]` |
|
|
144
|
+
| `currentPage` | number | 页码 |
|
|
145
|
+
| `pageSize` | number | 每页条数 |
|
|
146
|
+
|
|
147
|
+
`aggregate[].column` 必须使用真实数据集字段;`aggregate[].alias` 只定义返回结果字段名,不会成为新的数据集字段。
|
|
148
|
+
|
|
149
|
+
| 位置 | 聚合别名 | 约束 |
|
|
150
|
+
|------|----------|------|
|
|
151
|
+
| `aggregate[].alias` | 支持 | 仅定义返回结果字段名 |
|
|
152
|
+
| `select` | 不支持 | 使用真实数据集字段 |
|
|
153
|
+
| `where` | 不支持 | 使用真实数据集字段 |
|
|
154
|
+
| `having` | 不支持 | 使用真实数据集字段 |
|
|
155
|
+
| `groupBy` | 不支持 | 使用真实数据集字段 |
|
|
156
|
+
| `orderBy` | 支持 | 可以引用聚合输出别名 |
|
|
157
|
+
|
|
158
|
+
需要按聚合结果过滤且 `aggregate` 无法用真实字段表达时,使用已有且契约可信的 Custom SQL。不要在运行时静默切换到 Custom SQL,也不要动态拼接 SQL。
|
|
159
|
+
|
|
160
|
+
**聚合类型:**
|
|
161
|
+
|
|
162
|
+
| type | 说明 | 示例 |
|
|
163
|
+
|------|------|------|
|
|
164
|
+
| `SUM` | 求和 | `{"column": "amount","type":"SUM","alias":"total"}` |
|
|
165
|
+
| `COUNT` | 计数 | `{"column": "id","type":"COUNT","alias":"cnt"}` |
|
|
166
|
+
| `COUNT` (distinct) | 去重计数 | `{"column": "id","type":"COUNT","alias":"cnt","distinct":true}` |
|
|
167
|
+
| `AVG` | 平均值 | `{"column": "score","type":"AVG","alias":"avg_score"}` |
|
|
168
|
+
| `AVG` (rounded) | 带精度平均值 | `{"column": "score","type":"AVG","alias":"avg","round":true,"precision":2}` |
|
|
169
|
+
|
|
170
|
+
### data create — 新建记录
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# 预览
|
|
174
|
+
lovrabet data create --code <code> --params '{"name":"test","amount":100}' --dry-run
|
|
175
|
+
|
|
176
|
+
# 执行
|
|
177
|
+
lovrabet data create --code <code> --params '{"name":"test","amount":100}'
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### data batchCreate — 批量新建同一数据集记录
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# 预览
|
|
184
|
+
lovrabet data batchCreate --code <code> --params '[{"name":"a"},{"name":"b"}]' --dry-run
|
|
185
|
+
|
|
186
|
+
# 执行
|
|
187
|
+
lovrabet data batchCreate --code <code> --params '[{"name":"a"},{"name":"b"}]'
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
`--params` 可以是 JSON 数组,也可以是 `{"items":[...]}`。该命令适合同一数据集多条新增,用于减少请求次数。
|
|
191
|
+
|
|
192
|
+
不要把 `batchCreate` 当作正式业务流程入口。跨多个数据集、upsert、依赖顺序、频率保护、幂等恢复或 handoff 结果要求,应封装在 Backend Function/CLI service 中,再由内部按需使用 `batchCreate`。Backend Function 写入类执行仍需先确认业务授权、Studio 权限和人工确认语义;CLI 将 `bff exec` 标记为 `read`,不等同于免审批写入。
|
|
193
|
+
|
|
194
|
+
### data update — 更新记录
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# 单条预览
|
|
198
|
+
lovrabet data update --code <code> --params '{"id":123,"status":"completed"}' --dry-run
|
|
199
|
+
|
|
200
|
+
# 单条执行
|
|
201
|
+
lovrabet data update --code <code> --params '{"id":123,"status":"completed"}'
|
|
202
|
+
|
|
203
|
+
# 批量预览
|
|
204
|
+
lovrabet data update --code <code> --params '{"id":[1,2,3],"status":"completed"}' --dry-run
|
|
205
|
+
|
|
206
|
+
# 批量执行
|
|
207
|
+
lovrabet data update --code <code> --params '{"id":[1,2,3],"status":"completed"}'
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
`id` 支持单值或数组。数组不能为空,id 必须是正整数或数字字符串,一次最多 1000 条。批量更新成功时 CLI 会用稳定 envelope 表达结果:`operation:"update"`、`mode:"batch"`、`ids`、`total`、`result`。为兼容当前运行时 metadata 路径,批量数组 id 会在实际请求体和 dry-run 预览中序列化为逗号字符串,例如 `id:"1,2,3"`;用户输入仍使用数组。底层服务端批量回查仍在 follow-up 中。
|
|
211
|
+
|
|
212
|
+
### data delete — 删除记录
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# 预览
|
|
216
|
+
lovrabet data delete --code <code> --params '{"id":123}' --dry-run
|
|
217
|
+
|
|
218
|
+
# 执行(需确认)
|
|
219
|
+
lovrabet data delete --code <code> --params '{"id":123}' --yes
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## where 查询语法
|
|
223
|
+
|
|
224
|
+
| 操作符 | 含义 | 示例 |
|
|
225
|
+
|--------|------|------|
|
|
226
|
+
| `$eq` | 等于 | `{"status":{"$eq":"active"}}` |
|
|
227
|
+
| `$ne` | 不等于 | `{"status":{"$ne":"deleted"}}` |
|
|
228
|
+
| `$gte/$gteq/$lte/$lteq` | 比较 | `{"amount":{"$gte":100}}` |
|
|
229
|
+
| `$contain` | 包含匹配 | `{"name":{"$contain":"test"}}` |
|
|
230
|
+
| `$startWith` | 前缀匹配 | `{"name":{"$startWith":"pre"}}` |
|
|
231
|
+
| `$endWith` | 后缀匹配 | `{"name":{"$endWith":"suf"}}` |
|
|
232
|
+
| `$notNull` | 非空判断 | `{"app_code":{"$notNull":true}}` |
|
|
233
|
+
| `$in` | 包含 | `{"status":{"$in":["active","pending"]}}` |
|
|
234
|
+
| `$and` | AND 组合 | `{"$and":[cond1, cond2]}` |
|
|
235
|
+
| `$or` | OR 组合 | `{"$or":[cond1, cond2]}` |
|
|
236
|
+
|
|
237
|
+
## aggregate 参数结构(与 SDK 对齐)
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"select": ["category_id"],
|
|
242
|
+
"aggregate": [
|
|
243
|
+
{ "type": "SUM", "column": "amount", "alias": "total_amount", "round": true, "precision": 2 }
|
|
244
|
+
],
|
|
245
|
+
"where": { "status": { "$eq": "active" } },
|
|
246
|
+
"groupBy": ["category_id"],
|
|
247
|
+
"having": { "category_id": { "$notNull": true } },
|
|
248
|
+
"orderBy": [{ "total_amount": "desc" }],
|
|
249
|
+
"currentPage": 1,
|
|
250
|
+
"pageSize": 20
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## 错误处理
|
|
255
|
+
|
|
256
|
+
- 缺少认证 → `Error: No authentication configured`
|
|
257
|
+
- `--params` 不是合法 JSON → `Error: Invalid JSON for --params: ...`
|
|
258
|
+
- 数据集不存在 → API 返回错误
|
|
259
|
+
- 非交互模式下 delete 未加 `--yes` → 高风险保护拦截
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# app-config — 运行态 app-config value 查询
|
|
2
|
+
|
|
3
|
+
按当前应用和配置 key 读取运行态 app-config value。
|
|
4
|
+
|
|
5
|
+
app-config 用于应用维度的运行态配置管理。`app-config get` 直接输出 value,返回值可能包含敏感信息。
|
|
6
|
+
|
|
7
|
+
## app-config get
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
lovrabet app-config get <key>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
14
|
+
|------|------|------|------|
|
|
15
|
+
| `<key>` | string | 是 | app-config key |
|
|
16
|
+
|
|
17
|
+
**风险等级**:`read`
|
|
18
|
+
|
|
19
|
+
**输出**:`data` 为 value 的具体结果:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"ok": true,
|
|
24
|
+
"command": "lovrabet app-config get",
|
|
25
|
+
"risk": "read",
|
|
26
|
+
"data": "example-value"
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 边界
|
|
31
|
+
|
|
32
|
+
- `lovrabet app-config get` 不支持 `--reveal`,命令直接输出 value。
|
|
33
|
+
- `lovrabet` 不提供 app-config 的 set/delete/list 管理入口。
|
|
34
|
+
- 不要把 app-config value 写入 `.lovrabet.json`、缓存、日志、命令参数或业务 Skill 入参。
|
|
35
|
+
- 输出可能是敏感值,Agent 只在用户明确要求查询指定 key 时执行。
|
|
36
|
+
- 示例 key 仅用于说明;实际执行必须使用调用方明确给出的 key,不能猜测、按 tags 查找或默认使用示例 key。
|
|
37
|
+
- Agent 执行 Skill 需要 value 时也调用该 CLI,不创建或复用取配置 BFF。
|
|
38
|
+
- value 只在当前任务内消费;除非用户明确要求查看,最终答复默认不重复展示。
|
|
39
|
+
|
|
40
|
+
## 示例
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
lovrabet app-config get example_api_key --format compress
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
若 key 不存在、当前 AK 无权限或运行态只读接口不可用,命令会返回错误。错误排查只基于 key、appCode、traceId 等定位信息,不应要求用户提供或回显明文 value。
|
|
47
|
+
|
|
48
|
+
## 参考
|
|
49
|
+
|
|
50
|
+
- [SKILL.md](../SKILL.md)
|
|
51
|
+
- [lovrabet-output-format-jq.md](lovrabet-output-format-jq.md)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# app — 应用管理
|
|
2
|
+
|
|
3
|
+
`app` 子命令负责应用目录发现和本地缓存刷新:
|
|
4
|
+
|
|
5
|
+
- **应用目录发现**:通过远端接口和本地 cache 获取当前 AK 可运行态访问的应用列表
|
|
6
|
+
- **缓存刷新**:在需要显式更新本地应用目录时使用 `app pull`
|
|
7
|
+
|
|
8
|
+
> **核心边界**:平台应用列表不再写入 `.lovrabet.json`。`.lovrabet.json` 只保存用户配置;应用目录缓存位于 `~/.lovrabet/cache/...`。
|
|
9
|
+
>
|
|
10
|
+
> 给当前工作目录绑定默认应用时,使用 `lovrabet workspace init/use`;命令选择取决于当前目录是否已经存在应用绑定。
|
|
11
|
+
|
|
12
|
+
## app list — 列出当前 AK 可运行态访问应用
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
lovrabet app list
|
|
16
|
+
lovrabet app list --local
|
|
17
|
+
lovrabet app list --no-cache
|
|
18
|
+
lovrabet app list --env daily
|
|
19
|
+
lovrabet app list --include-unpublished
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
| Flag | 说明 |
|
|
23
|
+
|------|------|
|
|
24
|
+
| `--env <env>` | 指定环境,默认当前环境 |
|
|
25
|
+
| `--local` | 只读本地 cache,不打远端 |
|
|
26
|
+
| `--no-cache` | 强制打远端并刷新 cache |
|
|
27
|
+
| `--include-unpublished` | 排查用:包含未发布应用 |
|
|
28
|
+
|
|
29
|
+
**行为**:
|
|
30
|
+
- 默认:远端优先,成功后刷新 cache,只展示已发布应用
|
|
31
|
+
- 远端失败且本地有 cache:回退到 cache
|
|
32
|
+
- `--local`:只读 cache
|
|
33
|
+
- `--include-unpublished`:仅用于确认未发布应用是否在远端目录或 cache 中;不要把未发布应用作为 `dataset` / `data` / `sql` / `bff` 目标
|
|
34
|
+
- 输出中的 `meta.source` 为 `remote` / `cache` / `mock`
|
|
35
|
+
|
|
36
|
+
**缓存路径**:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
~/.lovrabet/cache/<env>/<ak-fingerprint>/my-apps.json
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**输出**:
|
|
43
|
+
- `data.items`:应用列表;默认只包含已发布、可运行态访问的应用
|
|
44
|
+
- `data.items[].enableI18n`:应用是否开启国际化;旧缓存或远端缺失该字段时为 `null`
|
|
45
|
+
- `data.items[].languages`:应用支持的语种列表,来自平台真实 `i18nInfo.langs`
|
|
46
|
+
- `data.items[].i18nInfo`:平台返回的应用国际化配置
|
|
47
|
+
- `data.items[].locale`:CLI 本地兼容配置字段,不代表应用支持语种,可能为 `null`
|
|
48
|
+
- `data.meta.env`:环境
|
|
49
|
+
- `data.meta.source`:来源
|
|
50
|
+
- `data.meta.fetchedAt`:最近同步时间
|
|
51
|
+
- `data.meta.cachePath`:cache 文件路径
|
|
52
|
+
- `data.meta.defaultApp` / `defaultAppSource`:当前默认候选应用决议结果
|
|
53
|
+
- `data.meta.remoteTotal`:远端或 cache 原始应用数量
|
|
54
|
+
- `data.meta.hiddenUnpublishedCount`:默认列表中因未发布被隐藏的应用数量
|
|
55
|
+
- `data.meta.includeUnpublished`:本次是否包含未发布应用
|
|
56
|
+
|
|
57
|
+
## 何时应该先跑 app list
|
|
58
|
+
|
|
59
|
+
应该先跑 `app list` 的场景:
|
|
60
|
+
|
|
61
|
+
- 用户只说了业务域,没有给 app 线索
|
|
62
|
+
- 当前没有显式 `--appcode` / `--app`,且需求包含业务域、对象名或数据集线索
|
|
63
|
+
- 你怀疑需求可能落在多个 app 中
|
|
64
|
+
- 你需要先确认当前 AK 在该环境下有哪些可运行态访问的应用
|
|
65
|
+
- 已经在 `defaultApp` 下按关键词验证过,但没有合理数据集命中
|
|
66
|
+
|
|
67
|
+
不需要先跑 `app list` 的场景:
|
|
68
|
+
|
|
69
|
+
- 用户已经给了 `--appcode`
|
|
70
|
+
- 用户已经给了 `--app <name>`
|
|
71
|
+
- 问题明显沿用上文已确认的同一 app 上下文
|
|
72
|
+
- 用户明确说“当前应用”“默认应用”,且没有新的业务域线索
|
|
73
|
+
|
|
74
|
+
`defaultApp` 只是默认候选,不是强上下文。未显式指定 app 且存在 `defaultApp` 时,应先用 `dataset list --name <关键词>` 验证默认候选;命中不合理时,再通过 `app list` 扩大搜索。
|
|
75
|
+
|
|
76
|
+
## 如何选择使用哪个应用
|
|
77
|
+
|
|
78
|
+
推荐方法不是只看 app 名,而是:
|
|
79
|
+
|
|
80
|
+
1. 有 `defaultApp` 时,先在默认候选下执行 `dataset list --name <关键词>`
|
|
81
|
+
2. 默认候选命中合理时直接继续
|
|
82
|
+
3. 默认候选无命中、弱命中或语义不合理时,再用 `app list` 拿到候选 app
|
|
83
|
+
4. 按需求关键词挑 1-2 个候选,对每个候选执行 `dataset list --app <name> --name <关键词>`
|
|
84
|
+
5. 用数据集命中情况反向确认正确 app
|
|
85
|
+
|
|
86
|
+
这样比纯靠 app 名猜测更稳。
|
|
87
|
+
|
|
88
|
+
## app pull — 手动刷新本地 app cache
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
lovrabet app pull
|
|
92
|
+
lovrabet app pull --env daily
|
|
93
|
+
lovrabet app pull --local
|
|
94
|
+
lovrabet app pull --no-cache
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
| Flag | 说明 |
|
|
98
|
+
|------|------|
|
|
99
|
+
| `--env <env>` | 指定环境,默认当前环境 |
|
|
100
|
+
| `--local` | 只读 cache,不请求远端 |
|
|
101
|
+
| `--no-cache` | 强制打远端并刷新 cache |
|
|
102
|
+
|
|
103
|
+
**注意**:
|
|
104
|
+
- 平时优先用 `lovrabet app list`;只有你明确想单独刷新缓存时才用 `app pull`
|
|
105
|
+
- `app pull` **不再**把远端应用列表写入 `.lovrabet.json`
|
|
106
|
+
- 它的职责只是“刷新本地 cache”
|
|
107
|
+
|
|
108
|
+
详见 [lovrabet-workspace.md](lovrabet-workspace.md)。
|
|
109
|
+
|
|
110
|
+
## 参考
|
|
111
|
+
|
|
112
|
+
- [SKILL.md](../SKILL.md)
|
|
113
|
+
- [lovrabet-config.md](lovrabet-config.md)
|