@lark-apaas/coding-steering 0.1.6-alpha.9 → 0.1.6-beta.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.
Files changed (30) hide show
  1. package/package.json +1 -1
  2. package/steering/nestjs-react-fullstack/skills/authz-guide/SKILL.md +1 -1
  3. package/steering/nestjs-react-fullstack/skills/authz-guide/references/dynamic-permission-guide.md +6 -0
  4. package/steering/nestjs-react-fullstack/skills/authz-guide/references/management-page-spec.md +4 -1
  5. package/steering/nestjs-react-fullstack/skills/client-add-aily-web-chat/SKILL.md +1 -1
  6. package/steering/nestjs-react-fullstack/skills/client-builtins-file-storage-service/SKILL.md +30 -4
  7. package/steering/nestjs-react-fullstack/skills/client-builtins-user-service/SKILL.md +39 -127
  8. package/steering/nestjs-react-fullstack/skills/feishu/SKILL.md +0 -1
  9. package/steering/nestjs-react-fullstack/skills/feishu/references/approval.md +1 -1
  10. package/steering/nestjs-react-fullstack/skills/feishu/references/attendance.md +1 -1
  11. package/steering/nestjs-react-fullstack/skills/feishu/references/bitable.md +3 -1
  12. package/steering/nestjs-react-fullstack/skills/feishu/references/calendar.md +1 -1
  13. package/steering/nestjs-react-fullstack/skills/feishu/references/contacts.md +1 -1
  14. package/steering/nestjs-react-fullstack/skills/feishu/references/doc.md +2 -1
  15. package/steering/nestjs-react-fullstack/skills/feishu/references/drive.md +2 -1
  16. package/steering/nestjs-react-fullstack/skills/feishu/references/events.md +2 -1
  17. package/steering/nestjs-react-fullstack/skills/feishu/references/id-convert.md +2 -2
  18. package/steering/nestjs-react-fullstack/skills/feishu/references/messaging.md +1 -1
  19. package/steering/nestjs-react-fullstack/skills/feishu/references/oauth.md +2 -1
  20. package/steering/nestjs-react-fullstack/skills/feishu/references/perm.md +2 -1
  21. package/steering/nestjs-react-fullstack/skills/feishu/references/wiki.md +3 -2
  22. package/steering/nestjs-react-fullstack/skills/openapi-guide/SKILL.md +1 -0
  23. package/steering/nestjs-react-fullstack/skills/plugin-guide/SKILL.md +36 -17
  24. package/steering/nestjs-react-fullstack/skills/plugin-guide/references/plugin-coding-guide.md +4 -1
  25. package/steering/nestjs-react-fullstack/skills/plugin-guide/references/table.md +4 -2
  26. package/steering/nestjs-react-fullstack/skills/react-hook-best-practices/SKILL.md +4 -4
  27. package/steering/nestjs-react-fullstack/skills/trigger-guide/SKILL.md +1 -0
  28. package/steering/nestjs-react-fullstack/skills/user-identity/SKILL.md +1 -0
  29. package/steering/nestjs-react-fullstack/skills_local/code-fix/SKILL.md +42 -28
  30. package/steering/nestjs-react-fullstack/skills_local/coding-guide/SKILL.md +37 -149
@@ -1,6 +1,6 @@
1
1
  # 日历与会议室 (Calendar)
2
2
 
3
- > 开放平台文档(Markdown 版):https://open.larkoffice.com/document/server-docs/calendar-v4/overview.md
3
+ > 开放平台文档(Markdown 版):<https://open.larkoffice.com/document/server-docs/calendar-v4/overview.md>
4
4
 
5
5
  使用 `@larksuiteoapi/node-sdk` 在 NestJS 中管理日程、预约会议室和查询忙闲状态。
6
6
 
@@ -1,6 +1,6 @@
1
1
  # 通讯录 (Contacts)
2
2
 
3
- > 开放平台文档(Markdown 版):https://open.larkoffice.com/document/server-docs/contact-v3/resources.md
3
+ > 开放平台文档(Markdown 版):<https://open.larkoffice.com/document/server-docs/contact-v3/resources.md>
4
4
 
5
5
  使用 `@larksuiteoapi/node-sdk` 在 NestJS 中查询飞书通讯录用户和部门信息。
6
6
 
@@ -1,6 +1,7 @@
1
1
  # 云文档 (Document)
2
2
 
3
- > 开放平台文档(Markdown 版):https://open.larkoffice.com/document/server-docs/docs/docs-overview
3
+ > 开放平台文档(Markdown 版):<https://open.larkoffice.com/document/server-docs/docs/docs-overview>
4
+ .md
4
5
 
5
6
  使用 `@larksuiteoapi/node-sdk` 在 NestJS 中操作飞书云文档。
6
7
 
@@ -1,6 +1,7 @@
1
1
  # 云空间 (Drive)
2
2
 
3
- > 开放平台文档(Markdown 版):https://open.larkoffice.com/document/server-docs/docs/drive-v1/introduction
3
+ > 开放平台文档(Markdown 版):<https://open.larkoffice.com/document/server-docs/docs/drive-v1/introduction>
4
+ .md
4
5
 
5
6
  使用 `@larksuiteoapi/node-sdk` 在 NestJS 中管理飞书云空间文件和文件夹。
6
7
 
@@ -1,6 +1,7 @@
1
1
  # 事件订阅 (Events)
2
2
 
3
- > 开放平台文档(Markdown 版):https://open.larkoffice.com/document/server-docs/event-subscription-guide/overview
3
+ > 开放平台文档(Markdown 版):<https://open.larkoffice.com/document/server-docs/event-subscription-guide/overview>
4
+ .md
4
5
 
5
6
  通过 WebSocket 长连接接收飞书事件推送,无需公网 IP / 域名,无需加解密。
6
7
 
@@ -1,8 +1,8 @@
1
1
  # 妙搭与飞书开放平台 — ID 识别与转换
2
2
 
3
- > 开放平台文档(Markdown 版):https://open.larkoffice.com/document/uAjLw4CM/ukTMukTMukTM/spark-v1/overview.md
3
+ > 开放平台文档(Markdown 版):<https://open.larkoffice.com/document/uAjLw4CM/ukTMukTMukTM/spark-v1/overview.md>
4
4
  >
5
- > 飞书用户身份体系官方说明:https://open.larkoffice.com/document/platform-overveiw/basic-concepts/user-identity-introduction/introduction
5
+ > 飞书用户身份体系官方说明:<https://open.larkoffice.com/document/platform-overveiw/basic-concepts/user-identity-introduction/introduction>
6
6
  >
7
7
  > **承接 `user-identity` skill 决策树**:如果只需 妙搭 userId → 飞书 user_id(employee_id),在 nestjs-react-fullstack 项目内优先用 `AuthNPaasService`。本文覆盖 `AuthNPaasService` 不支持的场景:需要 `open_id` / `union_id`、或需要任何方向的反查、或不在该模板内的项目。
8
8
 
@@ -1,6 +1,6 @@
1
1
  # 消息 (Messaging)
2
2
 
3
- > 开放平台文档(Markdown 版):https://open.larkoffice.com/document/server-docs/im-v1/introduction.md
3
+ > 开放平台文档(Markdown 版):<https://open.larkoffice.com/document/server-docs/im-v1/introduction.md>
4
4
 
5
5
  使用 `@larksuiteoapi/node-sdk` 在 NestJS 中发送和回复飞书消息。
6
6
 
@@ -1,6 +1,7 @@
1
1
  # OAuth 用户授权
2
2
 
3
- > 开放平台文档(Markdown 版):https://open.larkoffice.com/document/ukTMukTMukTM/uMTNz4yM1MjLzUzM
3
+ > 开放平台文档(Markdown 版):<https://open.larkoffice.com/document/ukTMukTMukTM/uMTNz4yM1MjLzUzM>
4
+ .md
4
5
 
5
6
  默认的 tenant_access_token 以应用身份调用 API。
6
7
  部分场景(个人日历、搜索联系人)需要 user_access_token 代表用户操作。
@@ -1,6 +1,7 @@
1
1
  # 权限管理 (Permission)
2
2
 
3
- > 开放平台文档(Markdown 版):https://open.larkoffice.com/document/server-docs/docs/permission/overview
3
+ > 开放平台文档(Markdown 版):<https://open.larkoffice.com/document/server-docs/docs/permission/overview>
4
+ .md
4
5
 
5
6
  使用 `@larksuiteoapi/node-sdk` 在 NestJS 中管理飞书云文档的协作者权限。
6
7
 
@@ -1,6 +1,7 @@
1
1
  # 知识库 (Wiki)
2
2
 
3
- > 开放平台文档(Markdown 版):https://open.larkoffice.com/document/server-docs/docs/wiki-v2/wiki-overview
3
+ > 开放平台文档(Markdown 版):<https://open.larkoffice.com/document/server-docs/docs/wiki-v2/wiki-overview>
4
+ .md
4
5
 
5
6
  使用 `@larksuiteoapi/node-sdk` 在 NestJS 中操作飞书知识库。
6
7
 
@@ -151,7 +152,7 @@ Wiki API 不提供搜索功能。获取内容需通过以下方式:
151
152
 
152
153
  1. 打开知识空间 → 设置 → 成员管理
153
154
  2. 添加机器人应用
154
- 3. 参考:https://open.feishu.cn/document/server-docs/docs/wiki-v2/wiki-qa
155
+ 3. 参考:<https://open.feishu.cn/document/server-docs/docs/wiki-v2/wiki-qa>
155
156
 
156
157
  ## Common Mistakes
157
158
 
@@ -72,6 +72,7 @@ modules/orders/
72
72
  ```
73
73
 
74
74
  在 `orders.module.ts` 中注册:
75
+
75
76
  ```typescript
76
77
  @Module({
77
78
  controllers: [OrdersController, OpenApiOrdersController],
@@ -134,17 +134,20 @@ const structured = await capabilityClient
134
134
  ```
135
135
 
136
136
  > **Client 侧提示**:`capabilityClient` 支持直接传 File/Blob 对象作为文件参数,无需先上传到 dataloom 获取 URL:
137
+ >
137
138
  > ```typescript
138
139
  > // Client 侧:直接传 File 对象,SDK 自动处理上传
139
140
  > const rawResult = await capabilityClient
140
141
  > .load('doc_parser_instance')
141
142
  > .call('parseDocToMarkdown', { fileUrl: [file] }); // file 为 File/Blob 对象
142
143
  > ```
144
+ >
143
145
  > ⚠️ 仅 `capabilityClient`(Client 侧)支持此能力,Server 侧 `CapabilityService` 仅支持 URL 字符串。
144
146
 
145
147
  ### 创建结构化提取 PluginInstance 的关键要求
146
148
 
147
149
  创建 `ai-text-to-json` 或 `ai-image-to-json` 类型的 PluginInstance 时:
150
+
148
151
  1. **必须一次性定义所有需要提取的字段**(参考数据库 schema / 表单定义 / UI 设计),宁多勿漏
149
152
  2. 字段类型仅支持 String / Number / Boolean,最多 20 个字段
150
153
  3. 先调用 `get_plugin_ai_json` 确认上游插件的 `outputSchema`,确保输入格式正确
@@ -190,6 +193,7 @@ const structured = await capabilityClient
190
193
  2. **明确报错**:plugin 未配置/未就绪时直接 `toast.error('未配置飞书多维表格,请前往设置页配置')` + 跳转配置页,**不**编一个假的"同步成功"
191
194
 
192
195
  ## 核心概念
196
+
193
197
  新版链路中,**Plugin(插件)**、**PluginInstance(插件实例配置)**、**PluginInstanceAIJson(运行时投影:pluginInstance.ai.json)** 的关系如下:
194
198
 
195
199
  - **Plugin(插件)**:底层承载单元,包含插件元信息与表单定义(form.schema)。模型侧只感知插件及其表单字段,不感知插件内部实现细节。
@@ -201,9 +205,10 @@ const structured = await capabilityClient
201
205
  - Code Agent 在生成**调用代码**前,必须读取它作为权威依据(Server 侧用 `CapabilityService`,Client 侧用 `capabilityClient`)
202
206
 
203
207
  ### 插件 Plugin
208
+
204
209
  插件是插件实例的承载单元,包含:
205
- 插件元信息(tags/name/description/version/...)
206
- 插件表单定义(form.schema),用于描述"这个插件需要哪些表单字段"。
210
+ 插件元信息(tags/name/description/version/...)
211
+ 插件表单定义(form.schema),用于描述"这个插件需要哪些表单字段"。
207
212
  重要:模型侧只感知插件与其表单 schema,不感知插件内部实现(如 Action的实现、API 细节等)。
208
213
 
209
214
  Plugin 的具体内容以JSON格式给出,例如:
@@ -227,17 +232,19 @@ Plugin 的具体内容以JSON格式给出,例如:
227
232
  ```
228
233
 
229
234
  ### 插件实例 PluginInstance
235
+
230
236
  开发框架内置 `plugin` 工具,用于创建和管理基于 **Plugin(插件表单)** 的业务插件实例(PluginInstance)。
231
237
 
232
238
  **重要说明**:
239
+
233
240
  - PluginInstance 的配置以"单文件 JSON"形式存储在 `server/capabilities/`(每个插件实例一个文件,逻辑上对应 server/capabilities/<id>.json)。
234
241
  - 运行时调用前,Code Agent 需要通过 get_plugin_ai_json 获取对应插件实例的 pluginInstance.ai.json,再基于其中的 actions/schema/outputMode 生成调用代码。
235
242
  - 运行时调用入口统一走 SDK/Service:
236
- - Server 侧:CapabilityService.load(pluginInstanceId).call(actionKey, input)
237
- - Client 侧:capabilityClient.load(pluginInstanceId).call(actionKey, input)(流式用 callStream)
238
-
243
+ - Server 侧:CapabilityService.load(pluginInstanceId).call(actionKey, input)
244
+ - Client 侧:capabilityClient.load(pluginInstanceId).call(actionKey, input)(流式用 callStream)
239
245
 
240
246
  PluginInstance 的配置以 JSON 形式输出,例如:
247
+
241
248
  ```json
242
249
  {
243
250
  "id": "create_feishu_group", // 全局唯一语义化 ID
@@ -263,6 +270,7 @@ PluginInstance 的配置以 JSON 形式输出,例如:
263
270
  **注意**paramsSchema 支持以下 4 种参数类型,需要按下面规定的格式进行填充:
264
271
 
265
272
  1. **文本** - 单行或多行文本输入
273
+
266
274
  ```json
267
275
  {
268
276
  "type": "string",
@@ -271,6 +279,7 @@ PluginInstance 的配置以 JSON 形式输出,例如:
271
279
  ```
272
280
 
273
281
  2. **数组** - 字符串数组(如 ID 列表、标签列表等)
282
+
274
283
  ```json
275
284
  {
276
285
  "type": "array",
@@ -283,6 +292,7 @@ PluginInstance 的配置以 JSON 形式输出,例如:
283
292
  ```
284
293
 
285
294
  3. **图片** - 图片资源(需指定 format 为 picture)
295
+
286
296
  ```json
287
297
  {
288
298
  "type": "string",
@@ -292,6 +302,7 @@ PluginInstance 的配置以 JSON 形式输出,例如:
292
302
  ```
293
303
 
294
304
  4. **文件** - 文件资源(需指定 format 为 file)
305
+
295
306
  ```json
296
307
  {
297
308
  "type": "string",
@@ -301,17 +312,20 @@ PluginInstance 的配置以 JSON 形式输出,例如:
301
312
  ```
302
313
 
303
314
  > **注意**:`format` 为 `file`、`picture` 或 `plugin-file-url` 的字段在 Client 侧调用时均支持直接传入 File/Blob 对象,`capabilityClient` SDK 会自动处理上传;Server 侧 `CapabilityService` 仅支持 URL 字符串。**禁止**Client 侧先通过 dataloom 上传文件拿 URL 再传给插件——dataloom 的 `download_url` 是内部存储路径,插件服务端可能无法访问。
315
+ >
304
316
  #### PluginInstanceAIJson(运行时投影 / 工程转化层产物:pluginInstance.ai.json)
317
+
305
318
  pluginInstance.ai.json 是从 PluginInstance 配置派生出的运行时插件实例说明(Runtime Spec),用于 Code Agent 动态生成调用代码。
306
319
  它包含:
307
- 插件实例元数据(id/pluginKey/pluginVersion/name/description)
308
- 可执行入口列表 actions[](每个入口包含 key/inputSchema/outputSchema/outputMode)
309
- 详细说明 readme
310
- type:单入口/多入口(single_action | multi_action)
320
+ 插件实例元数据(id/pluginKey/pluginVersion/name/description)
321
+ 可执行入口列表 actions[](每个入口包含 key/inputSchema/outputSchema/outputMode)
322
+ 详细说明 readme
323
+ type:单入口/多入口(single_action | multi_action)
311
324
 
312
325
  **重要**:模型不能自行猜测某个插件实例有哪些 action、入参/出参结构;在生成调用代码前必须通过工具读取该 pluginInstance.ai.json。
313
326
 
314
327
  PluginInstanceAIJson 的配置以 JSON 形式输出,例如:
328
+
315
329
  ```json
316
330
  {
317
331
  "type": "multi_action", // 插件实例类型:single_action 表示仅 1 个 action;multi_action 表示多个 action(调用前需选择 actionKey)
@@ -347,17 +361,21 @@ PluginInstanceAIJson 的配置以 JSON 形式输出,例如:
347
361
  ```
348
362
 
349
363
  ## 可用的 Plugin
364
+
350
365
  ```
351
366
  {{available_plugins}}
352
367
  ```
368
+
353
369
  说明:先从可用的 PluginInstance 进行选择,如果无法满足需求,看可用的 Plugin,如果有满足的插件,调用插件生成工具进行生成,如果没有,直接拒答。
354
370
 
355
371
  ## 可用的 PluginInstance
372
+
356
373
  ```
357
374
  {{available_plugin_instances}}
358
375
  ```
359
376
 
360
377
  ### 使用方式
378
+
361
379
  1. **创建/修改 PluginInstance(配置层)**:调用 `plugin_instance` 工具生成/更新单文件 PluginInstance JSON(基于插件表单封装)。
362
380
  2. **查询已有 PluginInstance(配置层)**:优先使用可用的 PluginInstance;如仍需核对细节,再读取对应插件实例配置(调用'get_plugin_ai_json')。
363
381
  3. **生成运行时代码(调用层)**:
@@ -366,17 +384,19 @@ PluginInstanceAIJson 的配置以 JSON 形式输出,例如:
366
384
  - 仔细阅读返回的 readme,必须严格遵循里面制定的规则
367
385
 
368
386
  ### 典型场景示例
387
+
369
388
  - **消息通知类**:封装"发送飞书消息"相关插件为业务插件实例
370
389
  - **群组管理类**:封装"创建飞书群组"相关插件为业务插件实例
371
390
  - **AI 生成类**:封装"AI 生文/生图/图片理解"相关插件为业务插件实例
372
391
 
373
392
  ### 使用限制
393
+
374
394
  - PluginInstance 必须通过 `plugin_instance` 工具创建/更新,不支持 agent 直接手改 `server/capabilities/` 下的配置文件
375
395
  - 调用前必须通过 `get_plugin_ai_json` 获取权威 schema,禁止猜测入参/出参结构
376
396
  - PluginInstance 配置信息存储在 `server/capabilities/` 目录
377
397
  - 运行时调用统一走 SDK/Service,不再为每个插件实例预生成固定的 call 文件
378
- - Server 侧:CapabilityService.load(capabilityId).call(actionKey, input)
379
- - Client 侧:capabilityClient.load(capabilityId).call(actionKey, input)(流式用 callStream)
398
+ - Server 侧:CapabilityService.load(capabilityId).call(actionKey, input)
399
+ - Client 侧:capabilityClient.load(capabilityId).call(actionKey, input)(流式用 callStream)
380
400
 
381
401
  ## PluginInstance 生成约束
382
402
 
@@ -441,11 +461,7 @@ PluginInstanceAIJson 的配置以 JSON 形式输出,例如:
441
461
  ### 第一步:检查现有 PluginInstance(复用优先)
442
462
 
443
463
  1) 用户描述需求后,优先基于上下文提供的插件实例列表检索是否已存在可复用插件实例。
444
- 2) 若存在候选插件实例但你无法确认其是否满足需求,必须调用 `get_plugin_ai_json` 获取该插件实例的运行时投影(pluginInstance.ai.json),根据其中的:
445
- - `actions[].key`
446
- - `actions[].inputSchema / outputSchema`
447
- - `actions[].outputMode`
448
- 来判断是否可复用以及如何调用。
464
+ 2) 若存在候选插件实例但你无法确认其是否满足需求,必须调用 `get_plugin_ai_json` 获取该插件实例的运行时投影(pluginInstance.ai.json),根据其中的 `actions[].key`、`actions[].inputSchema / outputSchema`、`actions[].outputMode` 判断是否可复用以及如何调用。
449
465
  3) 禁止按旧链路去读取/维护 `server/capabilities/capabilities.json` 来做复用判断。
450
466
 
451
467
  > 结论:**复用判断以插件实例列表 + get_plugin_ai_json 为准**,禁止猜测 action、入参/出参、输出模式。
@@ -459,8 +475,9 @@ PluginInstanceAIJson 的配置以 JSON 形式输出,例如:
459
475
  - 其他情况:告知用户该需求目前无法满足
460
476
 
461
477
  **强制约束**:
478
+
462
479
  - 创建/更新 PluginInstance **必须**通过 `plugin_instance` 工具完成,绝对禁止直接修改 `server/capabilities/` 下的配置文件。
463
- - UPDATE 场景严禁修改保护字段:`id / pluginKey / pluginVersion / createdAt `。
480
+ - UPDATE 场景严禁修改保护字段:`id / pluginKey / pluginVersion / createdAt`。
464
481
 
465
482
  ### 第三步:生成调用代码
466
483
 
@@ -524,6 +541,7 @@ PluginInstanceAIJson 的配置以 JSON 形式输出,例如:
524
541
  用户会用「AI 生文」「AI 生图」「发送飞书消息」等**业务语言**描述需求;这些关键词必须被识别为**待使用或待创建的 PluginInstance**。
525
542
 
526
543
  开发流程:
544
+
527
545
  1. 收到需求后,先看可用的 PluginInstance 是否有可以直接使用的插件实例
528
546
  2. 若有候选但不确定是否满足,调用 `get_plugin_ai_json` 查看其 actions/schema/outputMode 再决策
529
547
  3. 若无,立即调用 `plugin_instance` 工具新建
@@ -577,6 +595,7 @@ PluginInstanceAIJson 的配置以 JSON 形式输出,例如:
577
595
  > **关键区分**:`formValue` 中配置固定值 ≠ 代码中硬编码。`formValue` 是插件实例的声明式配置,修改不需要改代码;而代码中硬编码的值散落在业务逻辑中,难以维护。
578
596
 
579
597
  当接收人/配置值是动态的,获取途径:
598
+
580
599
  1. 通过平台角色 API 获取(如"所有 admin_hr 角色的用户")
581
600
  2. 存入应用配置表,通过 API 读取
582
601
  3. 通过环境变量注入
@@ -58,7 +58,9 @@
58
58
  ### Client 侧调用方式(默认首选)
59
59
 
60
60
  #### 1. 调用前获取权威依据
61
+
61
62
  在为某个插件实例生成调用代码前,必须先通过 `get_plugin_ai_json` 工具获取该插件实例的运行时投影(plugin_Instance.ai.json),并以其中信息为准:
63
+
62
64
  - `actions[].key`:调用时要传的 `actionKey`
63
65
  - `actions[].inputSchema / outputSchema`:入参/出参结构
64
66
  - `actions[].outputMode`:`unary | stream`(决定调用与结果处理方式)
@@ -175,7 +177,7 @@ function readFirstStringField(
175
177
 
176
178
  **核心原则**:在插件设计阶段按「原子化拆解」拆分,避免单插件返回多字段 JSON。
177
179
 
178
- ##### 推荐:多插件并行流式
180
+ ##### 推荐:多插件并行流式
179
181
 
180
182
  适用于需求涉及多种输出(标题、正文、图片等),各输出相对独立。
181
183
 
@@ -350,6 +352,7 @@ this.somePluginInstanceSideEffect(input).catch(error => {
350
352
  | 任意(兜底场景) | Server 侧 | `capabilityService.load(id).call(actionKey, input)` |
351
353
 
352
354
  **选择原则**:
355
+
353
356
  - 不涉及持久化时,优先在 Client 侧直接调用
354
357
  - `outputMode = stream` 时,Client 侧使用 `callStream` 做渐进式渲染
355
358
  - 涉及持久化、触发器、敏感凭证、事务编排等场景时,使用 Server 侧
@@ -12,8 +12,8 @@
12
12
 
13
13
  在查看本插件的 Action 时,你将同时获得两部分信息:
14
14
 
15
- 1. **本文档 (README)**: 提供高级指引、业务逻辑、使用场景、重要约束。
16
- 2. **Action 的 `inputSchema` 和 `outputSchema`**: 提供精确的 JSON Schema 格式的输入/输出结构。
15
+ 1. **本文档 (README)**: 提供高级指引、业务逻辑、使用场景、重要约束。
16
+ 2. **Action 的 `inputSchema` 和 `outputSchema`**: 提供精确的 JSON Schema 格式的输入/输出结构。
17
17
 
18
18
  **请遵循以下原则:**
19
19
 
@@ -464,6 +464,7 @@ const columns = [
464
464
  **2. Formula 字段不支持 filter 和 sum/avg 聚合**
465
465
 
466
466
  同一数据常有两个字段:原始 Number 字段(如 `金额`,单位元)和计算 Formula 字段(如 `金额(万元)`)。聚合和过滤**必须用 Number 字段**,在代码里做单位转换:
467
+
467
468
  ```typescript
468
469
  // ❌ 错误:金额(万元) 是 Formula,不能聚合也不能过滤
469
470
  { fieldName: '金额(万元)', aggregation: 'sum' }
@@ -479,6 +480,7 @@ const columns = [
479
480
  与 searchRecords 不同,aggregateQuery 中 `isNot` 会把字段值为空的记录也排除。如果很多记录的该字段为空,结果会远少于预期甚至为 0。
480
481
 
481
482
  解决方案:不在 filter 里用 `isNot` 排除 Text 值,改为在 dimensions 里加上该字段,在结果侧用 if 跳过不要的分组:
483
+
482
484
  ```typescript
483
485
  // ❌ 错误:isNot 会把「目前进展」为空的记录也排掉
484
486
  filter: { conditions: [{ fieldName: '目前进展', operator: 'isNot', value: ['已完成'] }] }
@@ -10,10 +10,10 @@ match-template-name: nestjs-react-fullstack
10
10
 
11
11
  ## ⚡️ 核心原则 (TL;DR)
12
12
 
13
- 1. **优先 React 19 新特性**: 用 `use()` 读取异步数据,用 `useActionState` 管理表单,替代繁琐的 `useEffect` + `useState`。
14
- 2. **拒绝冗余 State**: 能计算得到的变量(派生状态),绝不存入 State,直接计算 or `useMemo`。
15
- 3. **事件驱动 > Effects**: 用户交互(点击、提交)产生的逻辑写在事件处理函数中,`useEffect` 仅用于同步外部系统(订阅、DOM)。
16
- 4. **依赖诚实**: `useEffect/useCallback/useMemo` 的依赖数组必须包含所有引用的响应式变量,禁止欺骗 Linter。
13
+ 1. **优先 React 19 新特性**: 用 `use()` 读取异步数据,用 `useActionState` 管理表单,替代繁琐的 `useEffect` + `useState`。
14
+ 2. **拒绝冗余 State**: 能计算得到的变量(派生状态),绝不存入 State,直接计算 or `useMemo`。
15
+ 3. **事件驱动 > Effects**: 用户交互(点击、提交)产生的逻辑写在事件处理函数中,`useEffect` 仅用于同步外部系统(订阅、DOM)。
16
+ 4. **依赖诚实**: `useEffect/useCallback/useMemo` 的依赖数组必须包含所有引用的响应式变量,禁止欺骗 Linter。
17
17
 
18
18
  ---
19
19
 
@@ -86,6 +86,7 @@ interface WebhookEvent {
86
86
  ```
87
87
 
88
88
  ### 指定值限制
89
+
89
90
  1. Webhook 触发器不可以设置指定值,并且告知用户。
90
91
 
91
92
  ### 代码示例
@@ -208,6 +208,7 @@ const UserInfoPanel = () => {
208
208
  ```
209
209
 
210
210
  **注意**:
211
+
211
212
  - `lark_user_id` 通过额外异步请求获取,可能晚于 `user_id` 等基础字段就绪
212
213
  - 请求失败或用户无对应飞书账号时值为 `undefined`,**必须用条件渲染**
213
214
  - `useCurrentUserProfile()` 的返回值里**不存在** `open_id`、`feishu_id`、`openId` 字段——在这个 Hook 的消费代码里飞书 ID 唯一字段名是 `lark_user_id`(仅约束本 Hook;项目其他场景调 spark `id_convert` / 通讯录 API 出现 `open_id` 是正常的)
@@ -1,9 +1,6 @@
1
1
  ---
2
2
  name: code-fix
3
- description: Use when encountering code errors such as import failures, TypeScript/Dto type mismatches, JSX syntax issues, API call exceptions (traceid troubleshooting), production log troubleshooting that should route through miaoda-cli, route 404 errors, or **lucide-react icon not found / duplicate identifier / barrel-export naming conflicts**. 触发词:导入错误, 模块解析失败, 类型错误, Dto不匹配, JSX语法, API异常, traceid, 线上日志, 线上日志查询, 查询线上日志, 路由404, code fix, debugging, lucide-react import error, icon not found, 图标不存在, Cannot find name, 标识符重复, no-redeclare, export 冲突, 桶导出冲突, dual export, "请修复错误" 通用排错
4
- steering: true
5
- steering-topic: code_fix
6
- match-template-name: nestjs-react-fullstack
3
+ description: Use when encountering code errors such as import failures, TypeScript/Dto type mismatches, JSX syntax issues, API call exceptions, route 404 errors, PostgresError connection verification failed, or **lucide-react icon not found / duplicate identifier / barrel-export naming conflicts**. 触发词:导入错误, 模块解析失败, 类型错误, Dto不匹配, JSX语法, API异常, 路由404, code fix, debugging, lucide-react import error, icon not found, 图标不存在, Cannot find name, 标识符重复, no-redeclare, export 冲突, 桶导出冲突, dual export, "请修复错误" 通用排错, please re-obtain a valid database connection
7
4
  ---
8
5
 
9
6
 
@@ -70,7 +67,7 @@ import { ListPlus, Cake, Home, Building, Twitter } from "lucide-react";
70
67
 
71
68
  1. **不确定就查**:图标名不在你已知列表里 → 先 `Read packages/client/lucide-react/iconMappings.json`(或 lucide-react 包的 d.ts 导出列表)确认存在,再写 import
72
69
  2. **替换图标必须连同 import 列表一起检查**:把旧图标替换成新图标时,**必须先 grep 当前文件 import 列表**确认新名未已 import,避免触发 LSP "标识符重复" / `no-redeclare`
73
- 3. **LSP 警告是硬约束**:multi_edit / 写代码后看到 LSP 任意 "Cannot find name" / "标识符重复" → **必须先修完警告才能 commit**,禁止带 LSP 错误跑 `commit_task`
70
+ 3. **LSP 警告是硬约束**:写代码后看到 LSP 任意 "Cannot find name" / "标识符重复" → **必须先修完警告才能 commit**,禁止带 LSP 错误提交
74
71
 
75
72
  ### 同名 export 重复(修复 SOP)
76
73
 
@@ -82,30 +79,38 @@ import { ListPlus, Cake, Home, Building, Twitter } from "lucide-react";
82
79
  2. 预防规则(跨子组件常量前缀化、行内/桶导出二选一)见 `coding-guide` 的「TypeScript 规范 · 命名约定」与「文件命名约定 · 导入导出」
83
80
 
84
81
  ### 前端 Dto 类型使用错误
82
+
85
83
  **问题描述**:代码中使用的 Dto 类型属性与实际定义不一致,导致 TypeScript 类型检查报错
86
84
 
87
85
  **核心原则**:遇到类型错误,先查 `@client/src/api/gen/types.gen.ts` 确认定义,再修改代码
88
86
 
89
87
  **错误示例**:
88
+
90
89
  - 示例1: 赋值时缺失必需属性
90
+
91
91
  ```
92
92
  Property 'dueDate' is missing in type {...} but required in type 'CreateBorrowRecordDto'
93
93
  ```
94
94
 
95
95
  - 示例2:访问不存在的属性
96
+
96
97
  ```
97
98
  Property 'avatar' does not exist on type 'LotteryParticipantResponseDto'
98
99
  ```
99
100
 
100
101
  - 示例3:导入不存在的类型
102
+
101
103
  ```
102
104
  Module '"@client/src/api/gen"' has no exported member named 'DiscrepancyResponseDto'
103
105
  ```
106
+
104
107
  **解决步骤**:
108
+
105
109
  1. 在 `@client/src/api/gen/types.gen.ts` 中搜索目标Dto实际定义
106
110
  2. 确认类型名称是否正确,明确完整定义
107
111
 
108
112
  **检查清单**:
113
+
109
114
  - [ ] 已查看 `@client/src/api/gen/types.gen.ts` 中的类型定义
110
115
  - [ ] 已对比代码使用与实际定义的差异
111
116
  - [ ] 已根据实际定义修正代码
@@ -156,22 +161,11 @@ Module '"@client/src/api/gen"' has no exported member named 'DiscrepancyResponse
156
161
 
157
162
  ## 调用生成的 API 异常
158
163
 
159
- ### 需要查询线上日志时使用 miaoda-cli
160
-
161
- **适用场景**:仅当用户提供 traceid、logid、线上报错、发布错误日志、线上运行日志、线上链路追踪,或排查必须依赖线上前端/后端日志。
164
+ ### 查看本地运行日志
162
165
 
163
- **处理要求**:引导并使用 `miaoda-cli` skill 查询线上日志。优先通过 `miaoda observability log/trace` 查询线上运行日志与链路追踪;排查发布错误时使用 `miaoda deploy error-log`。本地开发日志、构建日志、测试日志、浏览器控制台日志不在此范围内,按当前技能或对应工具排查。拿到线上日志后再回到本技能继续定位与修复代码问题。
166
+ **适用场景**:本地开发期 API 调用异常、控制台报错、后端进程行为异常。
164
167
 
165
- ### 用户提供了 traceid,排查错误
166
-
167
- **解决方案**:使用 `miaoda-cli` skill 读取线上前端与后端日志,获取详细错误
168
-
169
- **排查示例**:
170
-
171
- 用户输入:8ae6724e-277e-4d51-afbf-b524b654f27f 看看这个 trace 为什么报错了
172
- 排查路径:
173
- 1. 使用 `miaoda-cli` skill 查询线上服务端与 trace 日志
174
- 2. 根据服务端日志中对应的日志内容修复对应代码逻辑
168
+ **处理要求**:本地日志由 `scripts/dev.js` 落到 `logs/` 目录(`dev.log`、`server.log` 及对应的 `.std.log`),直接 `cat` / `tail -F` 查看;浏览器侧错误看 DevTools Console。本地版**不接管线上日志/traceid 排查链路**(那条路径由发布平台和 oncall 工具承接)。
175
169
 
176
170
  ### 调用 API 客户端时后端返回异常
177
171
 
@@ -195,25 +189,45 @@ Module '"@client/src/api/gen"' has no exported member named 'DiscrepancyResponse
195
189
  错误信息:服务内部错误
196
190
  错误堆栈(可选):Error: 这是测试异常:HelloController.getConfig方法故意抛出的错误\n at HelloController.getConfig (/home/gem/workspace/dist/server/modules/hello/hello.controller.js:17:15)\n at /home/gem/workspace/node_modules/@nestjs/core/router/router-execution-context.js:38:29\n at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
197
191
 
198
- 2. 如果错误堆栈存在,优先按照错误堆栈中的相关文件与行列号找到对应文件,读取内容并启发式分析
199
- 3. 如果错误堆栈不存在,按照请求的 URL 找到对应的 controller,检查其中的逻辑,启发式的分析依赖。如发现问题可以直接处理。若仍未发现问题,可以在 controller 抛出的错误对象上增加 `message` 属性,改变 message 内容方便 debug。你可以在增加完之后让用户重新请求触发问题。
192
+ 1. 如果错误堆栈存在,优先按照错误堆栈中的相关文件与行列号找到对应文件,读取内容并启发式分析
193
+ 2. 如果错误堆栈不存在,按照请求的 URL 找到对应的 controller,检查其中的逻辑,启发式的分析依赖。如发现问题可以直接处理。若仍未发现问题,可以在 controller 抛出的错误对象上增加 `message` 属性,改变 message 内容方便 debug。你可以在增加完之后让用户重新请求触发问题。
200
194
 
201
195
  ```typescript
202
196
  try {
203
- // some logic
197
+ // some logic
204
198
  } catch (err) {
205
199
  // 后端异常必须在后端打印日志
206
- this.logger.error('...')
207
- // 后端异常同时需要抛出到前端,方便修复
208
- // 构造为 http-errors compatible 的对象
209
- err.statusCode = 500;
210
- err.message = err.stack; // 抛出 stack 信息,保障有足够的错误内容透出
211
- throw err;
200
+ this.logger.error('...')
201
+ // 后端异常同时需要抛出到前端,方便修复
202
+ // 构造为 http-errors compatible 的对象
203
+ err.statusCode = 500;
204
+ err.message = err.stack; // 抛出 stack 信息,保障有足够的错误内容透出
205
+ throw err;
212
206
  }
213
207
  ```
214
208
 
215
209
  注意:优先让错误信息中包含堆栈信息,以更精确的定位错误发生位置。
216
210
 
211
+ ## 数据库连接问题
212
+
213
+ ### PG 连接串过期 / 失效
214
+
215
+ **问题描述**:`npm run dev` 启动后,后端访问数据库时报类似如下错误(关键特征是 `connection verification failed` + `expired or invalid connection link`,endpoint 域名以实际为准):
216
+
217
+ ```
218
+ PostgresError: connection verification failed for endpoint "<pg-endpoint>": expired or invalid connection link, please re-obtain a valid database connection
219
+ ```
220
+
221
+ **根因**:PG connection string 注入在 `.env.local` 中,由于安全策略,连接串 **5 天过期**。`npm run dev` 启动时只会读取一次 `.env.local`,过期后旧连接串就会触发上述报错。
222
+
223
+ **修复方案**:**重新运行 `npm run dev`** 即可。启动脚本会重新拉取并注入最新的 PG connection string 到 `.env.local`,新进程读取到的就是有效连接串。不要去改后端代码或 ORM 配置。
224
+
225
+ **注意**:
226
+
227
+ - 不要尝试手工编辑 `.env.local` 里的 PG connection string,连接串由启动流程统一管理
228
+ - 不要把这个错误当成业务代码 bug 去排查 controller / service / 数据库 schema
229
+ - 重启 `npm run dev` 后若仍报同样错误,再按其它通用排查路径处理
230
+
217
231
  ## 路由和导航问题
218
232
 
219
233
  ### 路由 404 错误诊断