aitable-workflow-cli 0.1.15 → 0.1.16-beta.1786022310508

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 (263) hide show
  1. package/package.json +3 -3
  2. package/templates/support-qa/lib/__tests__/declarative-matcher.test.ts +240 -0
  3. package/templates/support-qa/lib/__tests__/dingtalk-group-membership.test.ts +127 -0
  4. package/templates/support-qa/lib/__tests__/memory-events.test.ts +90 -0
  5. package/templates/support-qa/lib/action-dispatch.ts +1 -1
  6. package/templates/support-qa/lib/declarative-matcher.ts +398 -0
  7. package/templates/support-qa/lib/dingtalk-group-membership.ts +151 -0
  8. package/templates/support-qa/lib/guards.ts +18 -0
  9. package/templates/support-qa/lib/memory-events.ts +60 -41
  10. package/templates/support-qa/lib/preflight.ts +294 -0
  11. package/templates/support-qa/package.json +2 -4
  12. package/templates/support-qa/profiles/aitable/profile/fastpath/known-answers.yml +1 -1
  13. package/templates/support-qa/profiles/aitable/profile/troubleshoot/classifiers.yml +1 -1
  14. package/templates/support-qa/workflows/config-sync/recipes/config_sync.recipe.ts +10 -8
  15. package/templates/support-qa/workflows/daily-review/recipes/daily_review.recipe.ts +1 -1
  16. package/templates/support-qa/workflows/group-qa/recipes/answer.recipe.ts +2 -7
  17. package/templates/support-qa/workflows/group-qa/recipes/conversation_handler.recipe.ts +3 -3
  18. package/templates/support-qa/workflows/group-qa/recipes/fastpath.recipe.ts +5 -11
  19. package/templates/support-qa/workflows/group-qa/recipes/on-action.recipe.ts +4 -2
  20. package/templates/support-qa/workflows/group-qa/recipes/reply-to-group.recipe.ts +13 -7
  21. package/templates/support-qa/workflows/group-qa/recipes/troubleshoot.recipe.ts +12 -18
  22. package/templates/support-qa/workspaces/support/AGENTS.md +1 -1
  23. package/templates/aitable-handoff/.env.example +0 -17
  24. package/templates/aitable-handoff/aitable-workflow.config.yml +0 -64
  25. package/templates/aitable-handoff/coding-agents.config.json +0 -17
  26. package/templates/aitable-handoff/npmrc +0 -1
  27. package/templates/aitable-handoff/package.json +0 -16
  28. package/templates/aitable-handoff/roles/config-syncer.role.yml +0 -4
  29. package/templates/aitable-handoff/roles/daily-review.role.yml +0 -4
  30. package/templates/aitable-handoff/roles/faq-support.role.yml +0 -9
  31. package/templates/aitable-handoff/roles/faq-troubleshooter.role.yml +0 -17
  32. package/templates/aitable-handoff/roles/kb-editor.role.yml +0 -19
  33. package/templates/aitable-handoff/wiki/faq-support/01-/345/277/253/351/200/237/345/205/245/351/227/250/6/350/212/202/350/257/276/345/270/246/344/275/240/345/277/253/351/200/237/344/270/212/346/211/213AI/350/241/250/346/240/274.md +0 -43
  34. package/templates/aitable-handoff/wiki/faq-support/01-/345/277/253/351/200/237/345/205/245/351/227/250/AI/350/241/250/346/240/274/350/241/214/346/225/260/350/257/264/346/230/216.md +0 -85
  35. package/templates/aitable-handoff/wiki/faq-support/01-/345/277/253/351/200/237/345/205/245/351/227/250//344/275/277/347/224/250/345/277/253/346/215/267/351/224/256.md +0 -34
  36. package/templates/aitable-handoff/wiki/faq-support/01-/345/277/253/351/200/237/345/205/245/351/227/250//345/260/206Excel/346/226/207/344/273/266/345/257/274/345/205/245AI/350/241/250/346/240/274.md +0 -48
  37. package/templates/aitable-handoff/wiki/faq-support/01-/345/277/253/351/200/237/345/205/245/351/227/250//345/270/270/350/247/201/351/227/256/351/242/230.md +0 -88
  38. package/templates/aitable-handoff/wiki/faq-support/01-/345/277/253/351/200/237/345/205/245/351/227/250//346/250/241/346/235/277/344/270/255/345/277/203.md +0 -59
  39. package/templates/aitable-handoff/wiki/faq-support/01-/345/277/253/351/200/237/345/205/245/351/227/250//351/222/211/351/222/211AI/350/241/250/346/240/274/345/270/270/350/247/201/344/270/212/351/231/220.md +0 -181
  40. package/templates/aitable-handoff/wiki/faq-support/01-/345/277/253/351/200/237/345/205/245/351/227/250//351/222/211/351/222/211AI/350/241/250/346/240/274/345/277/253/351/200/237/344/270/212/346/211/213.md +0 -177
  41. package/templates/aitable-handoff/wiki/faq-support/02-/345/237/272/347/241/200/346/223/215/344/275/234/AI/350/241/250/346/240/274/347/232/204/345/257/274/345/207/272.md +0 -27
  42. package/templates/aitable-handoff/wiki/faq-support/02-/345/237/272/347/241/200/346/223/215/344/275/234//344/275/277/347/224/250/345/210/206/347/273/204.md +0 -67
  43. package/templates/aitable-handoff/wiki/faq-support/02-/345/237/272/347/241/200/346/223/215/344/275/234//344/275/277/347/224/250/345/241/253/350/211/262.md +0 -99
  44. package/templates/aitable-handoff/wiki/faq-support/02-/345/237/272/347/241/200/346/223/215/344/275/234//344/275/277/347/224/250/346/216/222/345/272/217.md +0 -66
  45. package/templates/aitable-handoff/wiki/faq-support/02-/345/237/272/347/241/200/346/223/215/344/275/234//344/275/277/347/224/250/347/255/233/351/200/211/345/222/214/347/255/233/351/200/211/346/235/241/344/273/266/347/273/204.md +0 -104
  46. package/templates/aitable-handoff/wiki/faq-support/02-/345/237/272/347/241/200/346/223/215/344/275/234//346/237/245/347/234/213/345/216/206/345/217/262/350/256/260/345/275/225.md +0 -79
  47. package/templates/aitable-handoff/wiki/faq-support/02-/345/237/272/347/241/200/346/223/215/344/275/234//347/224/250AI/350/241/250/346/240/274/344/270/200/350/241/250/344/270/200/345/212/251/347/220/206/345/217/221/346/266/210/346/201/257.md +0 -94
  48. package/templates/aitable-handoff/wiki/faq-support/02-/345/237/272/347/241/200/346/223/215/344/275/234//350/207/252/345/256/232/344/271/211/350/256/260/345/275/225/345/220/215/347/247/260.md +0 -35
  49. package/templates/aitable-handoff/wiki/faq-support/02-/345/237/272/347/241/200/346/223/215/344/275/234//350/207/252/345/256/232/344/271/211/350/256/260/345/275/225/350/257/246/346/203/205/351/241/265/345/222/214/345/241/253/345/206/231/351/241/265.md +0 -141
  50. package/templates/aitable-handoff/wiki/faq-support/02-/345/237/272/347/241/200/346/223/215/344/275/234//350/260/203/346/225/264/345/210/227/345/256/275.md +0 -42
  51. package/templates/aitable-handoff/wiki/faq-support/02-/345/237/272/347/241/200/346/223/215/344/275/234//350/260/203/346/225/264/350/241/214/351/253/230.md +0 -40
  52. package/templates/aitable-handoff/wiki/faq-support/03-/344/275/277/347/224/250/345/255/227/346/256/265//344/270/272/350/241/250/346/240/274/346/267/273/345/212/240/345/255/227/346/256/265.md +0 -188
  53. package/templates/aitable-handoff/wiki/faq-support/03-/344/275/277/347/224/250/345/255/227/346/256/265//345/215/225/351/200/211/345/244/232/351/200/211/345/255/227/346/256/265/345/220/214/346/255/245/345/205/266/344/273/226/350/241/250/351/200/211/351/241/271.md +0 -142
  54. package/templates/aitable-handoff/wiki/faq-support/03-/344/275/277/347/224/250/345/255/227/346/256/265//345/255/227/346/256/265/347/256/241/347/220/206.md +0 -44
  55. package/templates/aitable-handoff/wiki/faq-support/03-/344/275/277/347/224/250/345/255/227/346/256/265//345/255/227/346/256/265/347/261/273/345/236/213/345/210/227/350/241/250.md +0 -95
  56. package/templates/aitable-handoff/wiki/faq-support/03-/344/275/277/347/224/250/345/255/227/346/256/265//345/255/227/346/256/265/347/274/226/347/273/204.md +0 -138
  57. package/templates/aitable-handoff/wiki/faq-support/04-/344/275/277/347/224/250/350/241/250/345/215/225//350/241/250/345/215/225/345/221/250/346/234/237/345/210/206/350/241/250.md +0 -42
  58. package/templates/aitable-handoff/wiki/faq-support/04-/344/275/277/347/224/250/350/241/250/345/215/225//350/241/250/345/215/225/345/237/272/347/241/200/346/223/215/344/275/234.md +0 -344
  59. package/templates/aitable-handoff/wiki/faq-support/04-/344/275/277/347/224/250/350/241/250/345/215/225//350/241/250/345/215/225/346/230/216/347/273/206/350/241/250-/344/270/200/346/254/241/345/241/253/345/206/231/345/244/232/346/235/241/346/217/220/344/272/244.md +0 -174
  60. package/templates/aitable-handoff/wiki/faq-support/04-/344/275/277/347/224/250/350/241/250/345/215/225//350/241/250/345/215/225/351/242/204/345/241/253/351/273/230/350/256/244/345/200/274.md +0 -97
  61. package/templates/aitable-handoff/wiki/faq-support/05-/345/205/254/345/274/217/345/207/275/346/225/260//344/275/277/347/224/250AI/347/224/237/346/210/220/345/205/254/345/274/217.md +0 -26
  62. package/templates/aitable-handoff/wiki/faq-support/05-/345/205/254/345/274/217/345/207/275/346/225/260//344/275/277/347/224/250/345/205/254/345/274/217/345/207/275/346/225/260/345/270/270/350/247/201/351/227/256/351/242/230.md +0 -179
  63. package/templates/aitable-handoff/wiki/faq-support/05-/345/205/254/345/274/217/345/207/275/346/225/260//344/275/277/347/224/250/345/205/254/345/274/217/345/255/227/346/256/265.md +0 -81
  64. package/templates/aitable-handoff/wiki/faq-support/05-/345/205/254/345/274/217/345/207/275/346/225/260//344/275/277/347/224/250/345/207/275/346/225/260.md +0 -21
  65. package/templates/aitable-handoff/wiki/faq-support/05-/345/205/254/345/274/217/345/207/275/346/225/260//345/205/254/345/274/217/345/207/275/346/225/260/345/244/247/345/205/250.md +0 -433
  66. package/templates/aitable-handoff/wiki/faq-support/05-/345/205/254/345/274/217/345/207/275/346/225/260//345/205/254/345/274/217/346/224/257/346/214/201/346/230/276/347/244/272/346/240/274/345/274/217.md +0 -126
  67. package/templates/aitable-handoff/wiki/faq-support/05-/345/205/254/345/274/217/345/207/275/346/225/260//345/205/254/345/274/217/351/224/231/350/257/257/344/273/243/347/240/201/345/210/227/350/241/250.md +0 -30
  68. package/templates/aitable-handoff/wiki/faq-support/05-/345/205/254/345/274/217/345/207/275/346/225/260//345/207/275/346/225/260/345/256/236/350/267/265.md +0 -13
  69. package/templates/aitable-handoff/wiki/faq-support/06-/346/225/260/346/215/256/350/277/236/346/216/245/344/270/255/345/277/203//346/225/260/346/215/256/350/277/236/346/216/245/344/270/255/345/277/203.md +0 -169
  70. package/templates/aitable-handoff/wiki/faq-support/06-/346/225/260/346/215/256/350/277/236/346/216/245/344/270/255/345/277/203//347/273/204/347/273/207/345/206/205/345/205/261/344/272/253/346/225/260/346/215/256/346/272/220.md +0 -106
  71. package/templates/aitable-handoff/wiki/faq-support/06-/346/225/260/346/215/256/350/277/236/346/216/245/344/270/255/345/277/203//350/267/250AI/350/241/250/346/240/274/346/225/260/346/215/256/345/220/214/346/255/245.md +0 -176
  72. package/templates/aitable-handoff/wiki/faq-support/06-/346/225/260/346/215/256/350/277/236/346/216/245/344/270/255/345/277/203//351/222/211/351/222/211AI/345/220/254/350/256/260/346/225/260/346/215/256/345/220/214/346/255/245.md +0 -100
  73. package/templates/aitable-handoff/wiki/faq-support/06-/346/225/260/346/215/256/350/277/236/346/216/245/344/270/255/345/277/203//351/222/211/351/222/211OA/345/256/241/346/211/271/346/225/260/346/215/256/345/220/214/346/255/245.md +0 -194
  74. package/templates/aitable-handoff/wiki/faq-support/06-/346/225/260/346/215/256/350/277/236/346/216/245/344/270/255/345/277/203//351/222/211/351/222/211/345/276/205/345/212/236/346/225/260/346/215/256/345/220/214/346/255/245.md +0 -87
  75. package/templates/aitable-handoff/wiki/faq-support/06-/346/225/260/346/215/256/350/277/236/346/216/245/344/270/255/345/277/203//351/222/211/351/222/211/346/227/245/347/250/213/346/225/260/346/215/256/345/220/214/346/255/245.md +0 -92
  76. package/templates/aitable-handoff/wiki/faq-support/06-/346/225/260/346/215/256/350/277/236/346/216/245/344/270/255/345/277/203//351/222/211/351/222/211/350/200/203/345/213/244/346/211/223/345/215/241/346/225/260/346/215/256/345/220/214/346/255/245.md +0 -129
  77. package/templates/aitable-handoff/wiki/faq-support/06-/346/225/260/346/215/256/350/277/236/346/216/245/344/270/255/345/277/203//351/222/211/351/222/211/350/241/250/346/240/274/346/225/260/346/215/256/345/220/214/346/255/245.md +0 -229
  78. package/templates/aitable-handoff/wiki/faq-support/06-/346/225/260/346/215/256/350/277/236/346/216/245/344/270/255/345/277/203//351/222/211/351/222/211/351/200/232/350/256/257/345/275/225/346/225/260/346/215/256/345/220/214/346/255/245.md +0 -120
  79. package/templates/aitable-handoff/wiki/faq-support/07-/344/275/277/347/224/250/350/247/206/345/233/276//344/275/277/347/224/250AI/350/241/250/346/240/274/350/247/206/345/233/276.md +0 -219
  80. package/templates/aitable-handoff/wiki/faq-support/07-/344/275/277/347/224/250/350/247/206/345/233/276//345/210/206/344/272/253/350/247/206/345/233/276.md +0 -71
  81. package/templates/aitable-handoff/wiki/faq-support/07-/344/275/277/347/224/250/350/247/206/345/233/276//346/225/260/346/215/256/350/241/250/345/222/214/350/247/206/345/233/276/347/232/204/345/205/263/347/263/273.md +0 -48
  82. package/templates/aitable-handoff/wiki/faq-support/07-/344/275/277/347/224/250/350/247/206/345/233/276//346/227/245/345/216/206/350/247/206/345/233/276.md +0 -89
  83. package/templates/aitable-handoff/wiki/faq-support/07-/344/275/277/347/224/250/350/247/206/345/233/276//346/237/245/350/257/242/351/241/265/351/235/242.md +0 -116
  84. package/templates/aitable-handoff/wiki/faq-support/07-/344/275/277/347/224/250/350/247/206/345/233/276//347/224/230/347/211/271/345/233/276.md +0 -135
  85. package/templates/aitable-handoff/wiki/faq-support/07-/344/275/277/347/224/250/350/247/206/345/233/276//347/224/273/345/206/214/350/247/206/345/233/276.md +0 -28
  86. package/templates/aitable-handoff/wiki/faq-support/07-/344/275/277/347/224/250/350/247/206/345/233/276//347/234/213/346/235/277/350/247/206/345/233/276.md +0 -35
  87. package/templates/aitable-handoff/wiki/faq-support/07-/344/275/277/347/224/250/350/247/206/345/233/276//350/241/250/346/240/274/350/247/206/345/233/276.md +0 -116
  88. package/templates/aitable-handoff/wiki/faq-support/07-/344/275/277/347/224/250/350/247/206/345/233/276//351/200/217/350/247/206/350/241/250/350/247/206/345/233/276.md +0 -123
  89. package/templates/aitable-handoff/wiki/faq-support/08-/344/275/277/347/224/250/344/273/252/350/241/250/347/233/230/TOP_N/345/210/206/346/236/220.md +0 -78
  90. package/templates/aitable-handoff/wiki/faq-support/08-/344/275/277/347/224/250/344/273/252/350/241/250/347/233/230//344/273/252/350/241/250/347/233/230/344/270/255/346/267/273/345/212/240/345/244/232/344/270/252/346/225/260/346/215/256/346/272/220.md +0 -129
  91. package/templates/aitable-handoff/wiki/faq-support/08-/344/275/277/347/224/250/344/273/252/350/241/250/347/233/230//344/273/252/350/241/250/347/233/230/345/215/225/345/233/276/350/241/250/345/222/214AI/350/247/243/350/257/273/345/206/205/345/256/271/345/210/206/344/272/253.md +0 -104
  92. package/templates/aitable-handoff/wiki/faq-support/08-/344/275/277/347/224/250/344/273/252/350/241/250/347/233/230//344/273/252/350/241/250/347/233/230/345/270/270/350/247/201/351/227/256/351/242/230.md +0 -31
  93. package/templates/aitable-handoff/wiki/faq-support/08-/344/275/277/347/224/250/344/273/252/350/241/250/347/233/230//344/273/252/350/241/250/347/233/230/346/231/272/350/203/275/346/200/273/347/273/223/345/210/206/346/236/220.md +0 -57
  94. package/templates/aitable-handoff/wiki/faq-support/08-/344/275/277/347/224/250/344/273/252/350/241/250/347/233/230//344/273/252/350/241/250/347/233/230/347/273/204/344/273/266.md +0 -47
  95. package/templates/aitable-handoff/wiki/faq-support/08-/344/275/277/347/224/250/344/273/252/350/241/250/347/233/230//344/275/277/347/224/250AI/350/241/250/346/240/274/344/273/252/350/241/250/347/233/230.md +0 -226
  96. package/templates/aitable-handoff/wiki/faq-support/08-/344/275/277/347/224/250/344/273/252/350/241/250/347/233/230//344/275/277/347/224/250/350/207/252/345/212/250/345/214/226/346/265/201/347/250/213/345/217/221/351/200/201/344/273/252/350/241/250/347/233/230.md +0 -49
  97. package/templates/aitable-handoff/wiki/faq-support/08-/344/275/277/347/224/250/344/273/252/350/241/250/347/233/230//345/210/206/344/272/253/344/273/252/350/241/250/347/233/230.md +0 -74
  98. package/templates/aitable-handoff/wiki/faq-support/08-/344/275/277/347/224/250/344/273/252/350/241/250/347/233/230//345/234/250/344/273/252/350/241/250/347/233/230/344/270/255/347/255/233/351/200/211/346/225/260/346/215/256.md +0 -65
  99. package/templates/aitable-handoff/wiki/faq-support/08-/344/275/277/347/224/250/344/273/252/350/241/250/347/233/230//350/207/252/345/256/232/344/271/211/344/273/252/350/241/250/347/233/230/344/270/255/345/277/203.md +0 -93
  100. package/templates/aitable-handoff/wiki/faq-support/08-/344/275/277/347/224/250/344/273/252/350/241/250/347/233/230//350/267/237/351/232/217/350/256/277/351/227/256/350/200/205/346/235/203/351/231/220/347/273/237/350/256/241.md +0 -48
  101. package/templates/aitable-handoff/wiki/faq-support/09-/345/272/224/347/224/250/346/250/241/345/274/217//345/205/250/346/226/260/345/272/224/347/224/250/346/250/241/345/274/217.md +0 -155
  102. package/templates/aitable-handoff/wiki/faq-support/09-/345/272/224/347/224/250/346/250/241/345/274/217//345/210/227/350/241/250/347/273/204/344/273/266.md +0 -228
  103. package/templates/aitable-handoff/wiki/faq-support/09-/345/272/224/347/224/250/346/250/241/345/274/217//345/233/276/347/211/207.md +0 -93
  104. package/templates/aitable-handoff/wiki/faq-support/09-/345/272/224/347/224/250/346/250/241/345/274/217//346/214/211/351/222/256.md +0 -86
  105. package/templates/aitable-handoff/wiki/faq-support/09-/345/272/224/347/224/250/346/250/241/345/274/217//346/240/207/347/255/276/351/241/265.md +0 -97
  106. package/templates/aitable-handoff/wiki/faq-support/09-/345/272/224/347/224/250/346/250/241/345/274/217//350/247/206/345/233/276/347/273/204/344/273/266.md +0 -125
  107. package/templates/aitable-handoff/wiki/faq-support/09-/345/272/224/347/224/250/346/250/241/345/274/217//350/277/207/346/273/244/345/231/250.md +0 -110
  108. package/templates/aitable-handoff/wiki/faq-support/09-/345/272/224/347/224/250/346/250/241/345/274/217//351/200/217/350/247/206/350/241/250/347/273/204/344/273/266.md +0 -142
  109. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201/Webhook/345/217/202/346/225/260/347/232/204/350/257/246/347/273/206/350/257/264/346/230/216.md +0 -76
  110. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//344/270/200/350/241/250/344/270/200/345/217/267Agent/346/224/257/346/214/201/347/276/244/346/224/266/351/233/206.md +0 -150
  111. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//344/275/277/347/224/250webhook/350/247/246/345/217/221/350/207/252/345/212/250/345/214/226.md +0 -163
  112. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//344/275/277/347/224/250/344/270/215/345/220/214/350/272/253/344/273/275/345/217/221/351/200/201/351/222/211/351/222/211/346/266/210/346/201/257.md +0 -60
  113. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//344/275/277/347/224/250/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201.md +0 -219
  114. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//344/275/277/347/224/250/350/207/252/345/212/250/345/214/226/345/276/252/347/216/257/350/212/202/347/202/271.md +0 -63
  115. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//345/234/250/346/265/201/347/250/213/344/270/255/344/275/277/347/224/250AI/351/227/256/347/255/224.md +0 -69
  116. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//345/234/250/346/266/210/346/201/257/345/215/241/347/211/207/344/270/212/346/267/273/345/212/240/346/214/211/351/222/256.md +0 -93
  117. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//346/265/201/347/250/213/345/217/230/351/207/217/350/247/243/351/207/212/344/270/216/345/270/270/350/247/201/346/212/245/351/224/231.md +0 -158
  118. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//346/265/201/347/250/213/350/247/246/345/217/221/346/235/241/344/273/266/344/270/216/346/211/247/350/241/214/345/212/250/344/275/234/344/270/200/350/247/210.md +0 -310
  119. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//347/224/250AI/350/241/250/346/240/274/344/270/200/350/241/250/344/270/200/345/212/251/347/220/206/345/217/221/346/266/210/346/201/257-/350/207/252/345/212/250/345/214/226.md +0 -129
  120. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//347/224/250/346/237/245/346/211/276/350/256/260/345/275/225/345/217/221/351/200/201/347/273/204/345/220/210/345/255/227/346/256/265/351/200/232/347/237/245.md +0 -66
  121. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//350/207/252/345/212/250/345/214/226/345/210/233/345/273/272/351/222/211/351/222/211/345/276/205/345/212/236/346/210/226/346/227/245/347/250/213.md +0 -84
  122. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//350/207/252/345/212/250/345/214/226/345/217/221/350/265/267AI/347/224/265/350/257/235/345/244/226/345/221/274.md +0 -322
  123. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//350/207/252/345/212/250/345/214/226/345/217/221/350/265/267OA/345/256/241/346/211/271.md +0 -93
  124. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//350/207/252/345/212/250/345/214/226/345/217/221/351/200/201HTTP/350/257/267/346/261/202.md +0 -168
  125. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//350/207/252/345/212/250/345/214/226/345/270/270/350/247/201/351/227/256/351/242/230.md +0 -83
  126. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//350/207/252/345/212/250/345/214/226/346/211/271/351/207/217/345/217/221/351/202/256/344/273/266.md +0 -79
  127. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//350/207/252/345/212/250/345/214/226/346/224/257/346/214/201/346/217/222/345/205/245/345/223/252/344/272/233/345/217/230/351/207/217/345/206/205/345/256/271.md +0 -80
  128. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//350/207/252/345/212/250/345/214/226/346/233/264/345/244/232/346/211/247/350/241/214/345/212/250/344/275/234/344/275/277/347/224/250/346/214/207/345/215/227.md +0 -21
  129. package/templates/aitable-handoff/wiki/faq-support/10-/350/207/252/345/212/250/345/214/226/345/267/245/344/275/234/346/265/201//350/260/203/347/224/250/344/270/211/346/226/271/345/267/245/344/275/234/346/265/201/345/272/224/347/224/250.md +0 -161
  130. package/templates/aitable-handoff/wiki/faq-support/11-AI/350/241/250/346/240/274/345/212/251/347/220/206/AI/350/241/250/346/240/274/344/270/207/350/203/275/350/264/264/344/274/230/345/205/210/344/275/277/347/224/250/347/224/263/350/257/267.md +0 -67
  131. package/templates/aitable-handoff/wiki/faq-support/11-AI/350/241/250/346/240/274/345/212/251/347/220/206/AI/350/241/250/346/240/274/344/270/207/350/203/275/350/264/264/344/275/277/347/224/250/350/257/264/346/230/216.md +0 -63
  132. package/templates/aitable-handoff/wiki/faq-support/11-AI/350/241/250/346/240/274/345/212/251/347/220/206/AI/350/241/250/346/240/274/345/212/251/347/220/206.md +0 -107
  133. package/templates/aitable-handoff/wiki/faq-support/12-/351/253/230/347/272/247/346/235/203/351/231/220//344/275/277/347/224/250AI/350/241/250/346/240/274/351/253/230/347/272/247/346/235/203/351/231/220.md +0 -194
  134. package/templates/aitable-handoff/wiki/faq-support/12-/351/253/230/347/272/247/346/235/203/351/231/220//350/241/214/345/210/227/346/235/203/351/231/220/350/256/276/347/275/256/345/217/212/351/253/230/347/272/247/346/235/203/351/231/220/345/257/271/350/241/250/345/215/225/345/205/254/345/274/217/347/232/204/345/275/261/345/223/215.md +0 -32
  135. package/templates/aitable-handoff/wiki/faq-support/12-/351/253/230/347/272/247/346/235/203/351/231/220//351/242/204/350/247/210/351/253/230/347/272/247/346/235/203/351/231/220/347/273/223/346/236/234.md +0 -43
  136. package/templates/aitable-handoff/wiki/faq-support/12-/351/253/230/347/272/247/346/235/203/351/231/220//351/253/230/347/272/247/346/235/203/351/231/220/345/270/270/350/247/201/351/227/256/351/242/230.md +0 -47
  137. package/templates/aitable-handoff/wiki/faq-support/12-/351/253/230/347/272/247/346/235/203/351/231/220//351/253/230/347/272/247/346/235/203/351/231/220/347/232/204/351/273/230/350/256/244/350/247/222/350/211/262.md +0 -36
  138. package/templates/aitable-handoff/wiki/faq-support/13-/346/217/222/344/273/266/344/270/255/345/277/203/AI/350/241/250/346/240/274/344/270/211/346/226/271/346/217/222/344/273/266/344/275/277/347/224/250/346/216/210/346/235/203.md +0 -19
  139. package/templates/aitable-handoff/wiki/faq-support/13-/346/217/222/344/273/266/344/270/255/345/277/203/AI/350/241/250/346/240/274/346/217/222/344/273/266-/350/204/232/346/234/254/346/217/222/344/273/266.md +0 -42
  140. package/templates/aitable-handoff/wiki/faq-support/13-/346/217/222/344/273/266/344/270/255/345/277/203/AI/350/241/250/346/240/274/346/217/222/344/273/266-/350/207/252/345/256/232/344/271/211/346/217/222/344/273/266.md +0 -51
  141. package/templates/aitable-handoff/wiki/faq-support/13-/346/217/222/344/273/266/344/270/255/345/277/203/AI/350/241/250/346/240/274/346/217/222/344/273/266/344/270/255/345/277/203-/344/275/277/347/224/250/346/214/207/345/215/227.md +0 -97
  142. package/templates/aitable-handoff/wiki/faq-support/14-/347/256/241/347/220/206/345/220/216/345/217/260//344/275/277/347/224/250/346/225/260/346/215/256/350/257/264/346/230/216.md +0 -82
  143. package/templates/aitable-handoff/wiki/faq-support/14-/347/256/241/347/220/206/345/220/216/345/217/260//346/235/203/347/233/212/346/225/260/346/215/256/350/257/264/346/230/216.md +0 -111
  144. package/templates/aitable-handoff/wiki/faq-support/15-/345/234/272/346/231/257/345/256/236/350/267/265/AI/350/241/250/346/240/274/350/257/257/345/210/240/346/201/242/345/244/215/346/214/207/345/215/227.md +0 -37
  145. package/templates/aitable-handoff/wiki/faq-support/15-/345/234/272/346/231/257/345/256/236/350/267/265//345/234/250/350/241/250/346/240/274/344/270/255/346/240/207/350/256/260/351/207/215/345/244/215/345/206/205/345/256/271.md +0 -43
  146. package/templates/aitable-handoff/wiki/faq-support/15-/345/234/272/346/231/257/345/256/236/350/267/265//347/233/264/346/222/255/345/205/254/345/274/200/347/263/273/345/210/227/350/257/276.md +0 -21
  147. package/templates/aitable-handoff/wiki/faq-support/16-/344/273/230/350/264/271/346/235/203/347/233/212//351/222/211/351/222/211AI/350/241/250/346/240/274/344/273/230/350/264/271/346/235/203/347/233/212.md +0 -144
  148. package/templates/aitable-handoff/wiki/faq-support/16-/344/273/230/350/264/271/346/235/203/347/233/212//351/222/211/351/222/211AI/350/241/250/346/240/274/346/220/255/345/273/272/346/234/215/345/212/241.md +0 -95
  149. package/templates/aitable-handoff/wiki/faq-support/17-/345/205/254/345/221/212/AI/350/241/250/346/240/274-/346/216/222/347/211/210/346/211/223/345/215/260/345/215/207/347/272/247/350/257/264/346/230/216.md +0 -40
  150. package/templates/aitable-handoff/wiki/faq-support/17-/345/205/254/345/221/212/AI/350/241/250/346/240/274-/347/211/210/346/234/254/345/215/207/347/272/247/351/200/232/347/237/245.md +0 -21
  151. package/templates/aitable-handoff/wiki/faq-support/17-/345/205/254/345/221/212//350/267/250AI/350/241/250/346/240/274/346/225/260/346/215/256/345/220/214/346/255/245/350/260/203/346/225/264/350/257/264/346/230/216.md +0 -55
  152. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI /350/241/250/346/240/274/346/217/222/344/273/266 - /344/274/201/344/270/232/345/206/205/346/217/222/344/273/266/345/217/221/345/270/203/346/214/207/345/215/227.md" +0 -159
  153. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274 AI /345/255/227/346/256/265 /345/274/200/345/217/221/346/214/207/345/215/227/AI/350/241/250/346/240/274 AI /345/255/227/346/256/265/345/274/200/345/217/221/346/214/207/345/215/227/357/274/210FaaS/347/211/210/357/274/211.md" +0 -1362
  154. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274 AI /345/255/227/346/256/265 /345/274/200/345/217/221/346/214/207/345/215/227/AI/350/241/250/346/240/274 AI /345/255/227/346/256/265/345/274/200/345/217/221/346/214/207/345/215/227/357/274/210/345/205/254/345/274/217/347/211/210/357/274/211.md" +0 -556
  155. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274 AI /345/255/227/346/256/265 /345/274/200/345/217/221/346/214/207/345/215/227.md" +0 -15
  156. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/255/227/346/256/265/346/250/241/347/211/210 /344/275/277/347/224/250/346/214/207/345/215/227/AI /350/241/250/346/240/274 AI /345/255/227/346/256/265/345/270/270/350/247/201/346/212/245/351/224/231/350/257/264/346/230/216.md" +0 -649
  157. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/255/227/346/256/265/346/250/241/347/211/210 /344/275/277/347/224/250/346/214/207/345/215/227/Dify/346/231/272/350/203/275/344/275/223.md" +0 -55
  158. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/255/227/346/256/265/346/250/241/347/211/210 /344/275/277/347/224/250/346/214/207/345/215/227/GPTPro /345/255/227/346/256/265/346/215/267/345/276/204 /345/257/206/351/222/245/350/216/267/345/217/226/346/214/207/345/215/227.md" +0 -23
  159. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/255/227/346/256/265/346/250/241/347/211/210 /344/275/277/347/224/250/346/214/207/345/215/227/OpenClaw /345/260/217/351/276/231/350/231/276/345/212/251/346/211/213/351/205/215/347/275/256/346/225/231/347/250/213.md" +0 -27
  160. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/255/227/346/256/265/346/250/241/347/211/210 /344/275/277/347/224/250/346/214/207/345/215/227//345/233/275/345/206/205/345/244/226/345/277/253/351/200/222/347/211/251/346/265/201/344/277/241/346/201/257/346/237/245/350/257/242/344/275/277/347/224/250/346/214/207/345/215/227.md" +0 -907
  161. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/255/227/346/256/265/346/250/241/347/211/210 /344/275/277/347/224/250/346/214/207/345/215/227//345/277/253/351/200/222/347/211/251/346/265/201/346/237/245/350/257/242/345/212/251/346/211/213/344/275/277/347/224/250/346/214/207/345/215/227.md" +0 -1
  162. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/AI/350/241/250/346/240/274JSAPI /347/261/273/345/236/213/346/217/217/350/277/260.xlsx +0 -0
  163. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Base /346/250/241/345/235/227.md" +0 -391
  164. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/AttachmentField /351/231/204/344/273/266/345/255/227/346/256/265.md" +0 -200
  165. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/AutoNumberField /350/207/252/345/212/250/347/274/226/345/217/267/345/255/227/346/256/265.md" +0 -75
  166. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/BarcodeField /346/235/241/347/240/201/345/255/227/346/256/265.md" +0 -95
  167. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/BidirectionalLinkField /345/217/214/345/220/221/345/205/263/350/201/224/345/255/227/346/256/265.md" +0 -294
  168. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/CheckboxField /345/244/215/351/200/211/346/241/206/345/255/227/346/256/265.md" +0 -95
  169. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/CreatedTimeField /345/210/233/345/273/272/346/227/266/351/227/264/345/255/227/346/256/265.md" +0 -134
  170. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/CurrencyField /350/264/247/345/270/201/345/255/227/346/256/265.md" +0 -260
  171. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/DateField /346/227/245/346/234/237/345/255/227/346/256/265.md" +0 -183
  172. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/DepartmentField /351/203/250/351/227/250/345/255/227/346/256/265.md" +0 -111
  173. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/EmailField /351/202/256/347/256/261/345/255/227/346/256/265.md" +0 -99
  174. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/FilterUpField /346/237/245/346/211/276/345/274/225/347/224/250/345/255/227/346/256/265.md" +0 -73
  175. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/FormulaField /345/205/254/345/274/217/345/255/227/346/256/265.md" +0 -109
  176. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/GeoLocationField /345/234/260/347/220/206/344/275/215/347/275/256/345/255/227/346/256/265.md" +0 -33
  177. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/GroupField /347/276/244/347/273/204/345/255/227/346/256/265.md" +0 -111
  178. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/LastModifiedTimeField /346/234/200/345/220/216/346/233/264/346/226/260/346/227/266/351/227/264/345/255/227/346/256/265.md" +0 -134
  179. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/LookupField /345/205/263/350/201/224/345/274/225/347/224/250/345/255/227/346/256/265.md" +0 -71
  180. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/MultiSelectField /345/244/232/351/200/211/345/255/227/346/256/265.md" +0 -349
  181. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/NumberField /346/225/260/345/255/227/345/255/227/346/256/265.md" +0 -175
  182. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/PrimaryField /344/270/273/351/224/256/346/226/207/346/241/243/345/255/227/346/256/265.md" +0 -91
  183. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/ProgressField /350/277/233/345/272/246/345/255/227/346/256/265.md" +0 -324
  184. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/RatingField /350/257/204/345/210/206/345/255/227/346/256/265.md" +0 -320
  185. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/RichTextField /345/257/214/346/226/207/346/234/254/345/255/227/346/256/265.md" +0 -45
  186. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/SingleSelectField /345/215/225/351/200/211/345/255/227/346/256/265.md" +0 -336
  187. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/TelephoneField /347/224/265/350/257/235/345/255/227/346/256/265.md" +0 -99
  188. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/TextField /346/226/207/346/234/254/345/255/227/346/256/265.md" +0 -93
  189. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/UnidirectionalLinkFields /345/215/225/345/220/221/345/205/263/350/201/224/345/255/227/346/256/265.md" +0 -295
  190. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/UrlField /351/223/276/346/216/245/345/255/227/346/256/265.md" +0 -163
  191. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227/UserField /344/272/272/345/221/230/345/255/227/346/256/265.md" +0 -266
  192. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Field /346/250/241/345/235/227.md" +0 -379
  193. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Record /346/250/241/345/235/227.md" +0 -277
  194. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/Sheet /346/250/241/345/235/227.md" +0 -1013
  195. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/UI /346/250/241/345/235/227.md" +0 -472
  196. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/View /346/250/241/345/235/227/GridView /350/241/250/346/240/274/350/247/206/345/233/276.md" +0 -835
  197. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243/View /346/250/241/345/235/227.md" +0 -203
  198. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243//345/255/227/346/256/265/346/225/260/346/215/256/347/273/223/346/236/204.md +0 -65
  199. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/345/257/271/350/261/241/346/250/241/345/236/213API/345/217/202/350/200/203/346/226/207/346/241/243//350/257/273/345/206/231AI /350/241/250/346/240/274/346/250/241/345/236/213.md" +0 -29
  200. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/346/225/260/346/215/256/346/272/220 /345/274/200/345/217/221/346/214/207/345/215/227.md" +0 -607
  201. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/204/232/346/234/254/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/Base /346/250/241/345/235/227.md" +0 -391
  202. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/204/232/346/234/254/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/Field /346/250/241/345/235/227.md" +0 -379
  203. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/204/232/346/234/254/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/Input/346/250/241/345/235/227.md" +0 -331
  204. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/204/232/346/234/254/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/Output/346/250/241/345/235/227.md" +0 -197
  205. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/204/232/346/234/254/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/Record /346/250/241/345/235/227.md" +0 -277
  206. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/204/232/346/234/254/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/Sheet /346/250/241/345/235/227.md" +0 -1013
  207. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/204/232/346/234/254/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/UI /346/250/241/345/235/227.md" +0 -472
  208. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/204/232/346/234/254/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/View /346/250/241/345/235/227.md" +0 -203
  209. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/204/232/346/234/254/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227//345/255/227/346/256/265/346/225/260/346/215/256/347/273/223/346/236/204.md" +0 -65
  210. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/204/232/346/234/254/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227.md" +0 -142
  211. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/276/271/346/240/217/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/Base /346/250/241/345/235/227.md" +0 -391
  212. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/276/271/346/240/217/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/Event/344/272/213/344/273/266/346/250/241/345/235/227.md" +0 -182
  213. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/276/271/346/240/217/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/Field /346/250/241/345/235/227.md" +0 -379
  214. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/276/271/346/240/217/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/Record /346/250/241/345/235/227.md" +0 -277
  215. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/276/271/346/240/217/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/Sheet /346/250/241/345/235/227.md" +0 -1013
  216. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/276/271/346/240/217/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/UI /346/250/241/345/235/227.md" +0 -472
  217. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/276/271/346/240/217/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227/View /346/250/241/345/235/227.md" +0 -203
  218. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/276/271/346/240/217/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227//345/205/266/344/273/226/346/216/245/345/217/243.md" +0 -146
  219. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/276/271/346/240/217/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227//345/255/227/346/256/265/346/225/260/346/215/256/347/273/223/346/236/204.md" +0 -65
  220. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/276/271/346/240/217/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227//346/240/270/345/277/203/347/237/245/350/257/206.md" +0 -54
  221. package/templates/aitable-handoff/wiki/faq-support/18-/345/274/200/345/217/221/350/200/205/346/214/207/345/215/227/AI/350/241/250/346/240/274/350/276/271/346/240/217/346/217/222/344/273/266 /345/274/200/345/217/221/346/214/207/345/215/227.md" +0 -192
  222. package/templates/aitable-handoff/wiki/faq-support//351/222/211/351/222/211AI/350/241/250/346/240/274FAQ.md +0 -611
  223. package/templates/aitable-handoff/workflows/admin-kb-update/recipes/kb-refine.recipe.ts +0 -131
  224. package/templates/aitable-handoff/workflows/admin-kb-update/recipes/kb_sync_handler.recipe.ts +0 -130
  225. package/templates/aitable-handoff/workflows/admin-kb-update/workflow.yml +0 -125
  226. package/templates/aitable-handoff/workflows/config-sync/recipes/config_sync.recipe.ts +0 -448
  227. package/templates/aitable-handoff/workflows/config-sync/recipes/config_sync_handler.recipe.ts +0 -16
  228. package/templates/aitable-handoff/workflows/config-sync/workflow.yml +0 -73
  229. package/templates/aitable-handoff/workflows/daily-review/recipes/daily_review.recipe.ts +0 -529
  230. package/templates/aitable-handoff/workflows/daily-review/recipes/daily_review_handler.recipe.ts +0 -26
  231. package/templates/aitable-handoff/workflows/daily-review/recipes/memory-events.ts +0 -56
  232. package/templates/aitable-handoff/workflows/daily-review/workflow.yml +0 -92
  233. package/templates/aitable-handoff/workflows/group-qa/error-replies.json +0 -53
  234. package/templates/aitable-handoff/workflows/group-qa/recipes/answer.recipe.ts +0 -197
  235. package/templates/aitable-handoff/workflows/group-qa/recipes/conversation_handler.recipe.ts +0 -294
  236. package/templates/aitable-handoff/workflows/group-qa/recipes/issue-classifier.ts +0 -120
  237. package/templates/aitable-handoff/workflows/group-qa/recipes/known-error-match.recipe.ts +0 -75
  238. package/templates/aitable-handoff/workflows/group-qa/recipes/memory-events.ts +0 -55
  239. package/templates/aitable-handoff/workflows/group-qa/recipes/reply-to-group.recipe.ts +0 -132
  240. package/templates/aitable-handoff/workflows/group-qa/recipes/troubleshoot-issue.recipe.ts +0 -195
  241. package/templates/aitable-handoff/workflows/group-qa/workflow.yml +0 -210
  242. package/templates/aitable-handoff/workspaces/daily-review/AGENTS.md +0 -189
  243. package/templates/aitable-handoff/workspaces/faq-support/AGENTS.md +0 -448
  244. package/templates/aitable-handoff/workspaces/faq-support/contacts.json +0 -14
  245. package/templates/aitable-handoff/workspaces/faq-support/owner-map.json +0 -18
  246. package/templates/aitable-handoff/workspaces/faq-support/skills/bug-triage/SKILL.md +0 -130
  247. package/templates/aitable-handoff/workspaces/faq-troubleshooter/AGENTS.md +0 -53
  248. package/templates/aitable-handoff/workspaces/faq-troubleshooter/skills/troubleshooting/SKILL.md +0 -58
  249. package/templates/aitable-handoff/workspaces/faq-troubleshooter/skills/troubleshooting/aitable-import-troubleshooter/SKILL.md +0 -485
  250. package/templates/aitable-handoff/workspaces/faq-troubleshooter/skills/troubleshooting/aitable-openapi-troubleshooter/SKILL.md +0 -183
  251. package/templates/aitable-handoff/workspaces/faq-troubleshooter/skills/troubleshooting/import-openapi-e2e-troubleshooter/SKILL.md +0 -459
  252. package/templates/aitable-handoff/workspaces/faq-troubleshooter/skills/troubleshooting/notable-datasource-troubleshooter/SKILL.md +0 -1286
  253. package/templates/aitable-handoff/workspaces/faq-troubleshooter/skills/troubleshooting/notable-field-troubleshooter/SKILL.md +0 -673
  254. package/templates/aitable-handoff/workspaces/faq-troubleshooter/skills/troubleshooting/spreadsheet-datasync-troubleshooter/SKILL.md +0 -322
  255. package/templates/aitable-handoff/workspaces/kb-editor/AGENTS.md +0 -32
  256. package/templates/support-qa/lib/assemble-cli.ts +0 -30
  257. package/templates/support-qa/lib/assemble.ts +0 -279
  258. package/templates/support-qa/lib/echo-guard.ts +0 -50
  259. package/templates/support-qa/lib/fastpath.ts +0 -227
  260. package/templates/support-qa/lib/owner-mention.ts +0 -140
  261. package/templates/support-qa/lib/profile-guard.ts +0 -55
  262. package/templates/support-qa/lib/send-failure-guard.ts +0 -59
  263. package/templates/support-qa/lib/troubleshoot.ts +0 -236
@@ -0,0 +1,398 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { parse as parseYaml } from "yaml";
4
+
5
+ /**
6
+ * aitable-workflow — 声明式规则匹配引擎
7
+ *
8
+ * 把「命中哪条规则」从代码里的硬编码正则收敛为 YAML 声明。两个 preset 共用同一内核:
9
+ *
10
+ * loadReplyRules 确定性秒回(命中即固定话术):safety 关键词兜底 + rules[template|contains|regex]
11
+ * loadClassifierRules 问题分类(命中即打标签并抽取证据):classifiers[patterns, require_all, extract]
12
+ *
13
+ * 前者本质是后者的特例(无 require_all、无 extract、命中即回复),故合为一个模块。
14
+ *
15
+ * ─── 硬不变量(务必保留,都是踩过的坑)───
16
+ *
17
+ * 1. **单向匹配**:一律「消息包含/匹配规则模式」,绝不反向(规则模式包含消息)。
18
+ * 双向 includes 会让短消息错误命中长规则——这是早期 known-error-match
19
+ * `errorMessage.includes(k) || k.includes(errorMessage)` 的实际 bug。
20
+ * 2. **只看用户本轮新话**:普通规则匹配前剥离钉钉「引用消息:」块。用户带引用追问时,
21
+ * 引用块里往往完整包含上一轮报错与机器人回复,不剥离就会复读同一段话术。
22
+ * 3. **safety 看全文**:安全兜底必须对含引用的原文匹配,防注入/敏感内容藏在引用块里绕过。
23
+ * 4. **优雅关闭**:未配置、文件缺失、解析失败 → config=null(调用方透传),不阻断主环。
24
+ * 单条规则非法只跳该条并记 issue,不整档失效。
25
+ * 5. **校验单一事实源**:合法性只由本文件的 normalize 逐条判定并产出 issues,
26
+ * 不再另外维护一份 zod schema(两套规则双写必然漂移)。
27
+ */
28
+
29
+ // ─── 匹配条件 ────────────────────────────────────────────
30
+
31
+ export type MatchPattern = {
32
+ contains?: string;
33
+ regex?: string;
34
+ /** 加载期预编译(与校验同一实例),避免逐消息重编 */
35
+ compiledRegex?: RegExp;
36
+ };
37
+
38
+ /** 钉钉「引用消息:」标记:其后内容是被引用的历史消息,不属于用户本轮诉求。
39
+ * 含半角/全角冒号两种变体(不同客户端文案不一致)。 */
40
+ const QUOTE_MARKERS = ["引用消息:", "引用消息:"];
41
+
42
+ /**
43
+ * 剥离引用块,只保留用户本轮新话。
44
+ * 边界:剥离后为空(用户只转发引用、自己没打字)→ 返回原文。
45
+ */
46
+ export function stripQuotedBlock(message: string): string {
47
+ const msg = message ?? "";
48
+ let cut = msg.length;
49
+ for (const marker of QUOTE_MARKERS) {
50
+ const i = msg.indexOf(marker);
51
+ if (i >= 0 && i < cut) cut = i;
52
+ }
53
+ if (cut >= msg.length) return msg;
54
+ const head = msg.slice(0, cut).trim();
55
+ return head || msg;
56
+ }
57
+
58
+ /** 空白归一(template 全等匹配用) */
59
+ function normalizeWs(s: string): string {
60
+ return s.replace(/\s+/g, " ").trim();
61
+ }
62
+
63
+ /** 单向测试:消息包含/匹配该 pattern */
64
+ function testPattern(p: MatchPattern, message: string): boolean {
65
+ if (p.contains !== undefined) return message.includes(p.contains);
66
+ if (p.compiledRegex) return p.compiledRegex.test(message);
67
+ return false;
68
+ }
69
+
70
+ /** 归一化 patterns 列表:每条必须且只能有 contains/regex 之一 */
71
+ function normalizePatterns(raw: unknown, label: string, issues: string[]): MatchPattern[] {
72
+ const out: MatchPattern[] = [];
73
+ for (const p of Array.isArray(raw) ? raw : []) {
74
+ if (!p || typeof p !== "object") continue;
75
+ const rec = p as Record<string, unknown>;
76
+ const hasContains = typeof rec.contains === "string" && rec.contains.trim();
77
+ const hasRegex = typeof rec.regex === "string" && String(rec.regex).trim();
78
+ if (Boolean(hasContains) === Boolean(hasRegex)) {
79
+ issues.push(`${label} 每条 pattern 必须且只能有 contains/regex 之一`);
80
+ continue;
81
+ }
82
+ if (hasContains) {
83
+ out.push({ contains: String(rec.contains) });
84
+ } else {
85
+ const rx = String(rec.regex);
86
+ try {
87
+ out.push({ regex: rx, compiledRegex: new RegExp(rx) });
88
+ } catch {
89
+ issues.push(`${label} 非法正则: ${rx}`);
90
+ }
91
+ }
92
+ }
93
+ return out;
94
+ }
95
+
96
+ /** 按绝对路径缓存加载结果(每种 preset 一张表,避免 key 冲突) */
97
+ function makeLoader<T>(
98
+ subdir: string,
99
+ parse: (raw: Record<string, unknown>, issues: string[]) => T | null,
100
+ labels: { missing: string; parseFail: string },
101
+ ) {
102
+ const cache = new Map<string, { config: T | null; issues: string[] }>();
103
+ return (configDir: string, rel: string | undefined): { config: T | null; issues: string[] } => {
104
+ const trimmed = String(rel ?? "").trim();
105
+ if (!trimmed) return { config: null, issues: [] }; // 未配置 → 关闭
106
+ const abs = path.resolve(configDir, subdir, trimmed);
107
+ const hit = cache.get(abs);
108
+ if (hit) return hit;
109
+
110
+ let res: { config: T | null; issues: string[] };
111
+ if (!existsSync(abs)) {
112
+ // 文件缺失 → 优雅关闭(不阻断主环);preflight 另行告警
113
+ res = { config: null, issues: [`${labels.missing}: ${subdir}/${trimmed}`] };
114
+ } else {
115
+ try {
116
+ const raw = (parseYaml(readFileSync(abs, "utf8")) ?? {}) as Record<string, unknown>;
117
+ const issues: string[] = [];
118
+ res = { config: parse(raw, issues), issues };
119
+ } catch (err) {
120
+ res = {
121
+ config: null,
122
+ issues: [`${labels.parseFail} ${subdir}/${trimmed}: ${err instanceof Error ? err.message : String(err)}`],
123
+ };
124
+ }
125
+ }
126
+ cache.set(abs, res);
127
+ return res;
128
+ };
129
+ }
130
+
131
+ // ─── preset 1:确定性秒回规则 ─────────────────────────────
132
+
133
+ export type ReplyRule = {
134
+ /** 规则标识(报错/日志文案含此 key,便于排障与追溯) */
135
+ key: string;
136
+ template?: string;
137
+ contains?: string;
138
+ regex?: string;
139
+ compiledRegex?: RegExp;
140
+ reply: string;
141
+ };
142
+
143
+ export type SafetyRule = { keywords: string[]; reply: string };
144
+
145
+ export type ReplyRulesConfig = {
146
+ safety?: SafetyRule;
147
+ rules: ReplyRule[];
148
+ };
149
+
150
+ export type ReplyMatch = {
151
+ key: string;
152
+ reply: string;
153
+ kind: "safety" | "template" | "contains" | "regex";
154
+ };
155
+
156
+ function parseReplyRules(raw: Record<string, unknown>, issues: string[]): ReplyRulesConfig {
157
+ const rules: ReplyRule[] = [];
158
+ const rawRules = Array.isArray(raw.rules) ? raw.rules : [];
159
+ for (let i = 0; i < rawRules.length; i++) {
160
+ const r = rawRules[i] as Record<string, unknown> | null;
161
+ if (!r || typeof r !== "object") {
162
+ issues.push(`rules[${i}] 不是对象`);
163
+ continue;
164
+ }
165
+ const key = String(r.key ?? "").trim();
166
+ const reply = String(r.reply ?? "").trim();
167
+ if (!key) {
168
+ issues.push(`rules[${i}] 缺少 key`);
169
+ continue;
170
+ }
171
+ if (!reply) {
172
+ issues.push(`rules[${key}] 缺少 reply`);
173
+ continue;
174
+ }
175
+ const present = (["template", "contains", "regex"] as const).filter(
176
+ (k) => typeof r[k] === "string" && String(r[k]).trim(),
177
+ );
178
+ if (present.length !== 1) {
179
+ issues.push(`rules[${key}] 必须且只能有 template/contains/regex 之一(当前 ${present.length} 个)`);
180
+ continue;
181
+ }
182
+ const rule: ReplyRule = { key, reply };
183
+ if (typeof r.template === "string") rule.template = r.template;
184
+ if (typeof r.contains === "string") rule.contains = r.contains;
185
+ if (typeof r.regex === "string") {
186
+ try {
187
+ rule.compiledRegex = new RegExp(r.regex);
188
+ } catch {
189
+ issues.push(`rules[${key}] 非法正则: ${r.regex}`);
190
+ continue;
191
+ }
192
+ rule.regex = r.regex;
193
+ }
194
+ rules.push(rule);
195
+ }
196
+
197
+ let safety: SafetyRule | undefined;
198
+ const rawSafety = raw.safety as Record<string, unknown> | undefined;
199
+ if (rawSafety && typeof rawSafety === "object") {
200
+ const keywords = Array.isArray(rawSafety.keywords)
201
+ ? rawSafety.keywords.map((k) => String(k)).filter(Boolean)
202
+ : [];
203
+ const reply = String(rawSafety.reply ?? "").trim();
204
+ if (keywords.length > 0 && reply) safety = { keywords, reply };
205
+ else issues.push("safety 需同时提供非空 keywords 与 reply(否则忽略)");
206
+ }
207
+
208
+ return { safety, rules };
209
+ }
210
+
211
+ /** 加载秒回规则(相对 `<configDir>/profile/` 解析),按绝对路径缓存 */
212
+ export const loadReplyRules = makeLoader<ReplyRulesConfig>(
213
+ "profile",
214
+ parseReplyRules,
215
+ { missing: "规则文件不存在", parseFail: "规则解析失败" },
216
+ );
217
+
218
+ /**
219
+ * 匹配秒回规则(单向):安全兜底优先,其次规则按声明顺序。
220
+ *
221
+ * safety 看全文(敏感内容/注入藏在引用块里也要拦);普通规则只看剥离引用后的用户新话。
222
+ */
223
+ export function matchReplyRules(config: ReplyRulesConfig | null, message: string): ReplyMatch | null {
224
+ if (!config) return null;
225
+ const msg = message ?? "";
226
+ if (!msg.trim()) return null;
227
+
228
+ if (config.safety) {
229
+ for (const kw of config.safety.keywords) {
230
+ if (kw && msg.includes(kw)) return { key: "safety", reply: config.safety.reply, kind: "safety" };
231
+ }
232
+ }
233
+
234
+ const own = stripQuotedBlock(msg);
235
+ if (!own.trim()) return null;
236
+
237
+ for (const rule of config.rules) {
238
+ if (rule.template !== undefined) {
239
+ if (normalizeWs(own) === normalizeWs(rule.template)) {
240
+ return { key: rule.key, reply: rule.reply, kind: "template" };
241
+ }
242
+ } else if (rule.contains !== undefined) {
243
+ if (own.includes(rule.contains)) return { key: rule.key, reply: rule.reply, kind: "contains" }; // 单向
244
+ } else if (rule.regex !== undefined) {
245
+ if (rule.compiledRegex?.test(own)) return { key: rule.key, reply: rule.reply, kind: "regex" };
246
+ }
247
+ }
248
+ return null;
249
+ }
250
+
251
+ // ─── preset 2:问题分类器 ─────────────────────────────────
252
+
253
+ export type ClassifierRule = {
254
+ issueType: string;
255
+ /** 可选:命中时透传的路由模块名 */
256
+ module?: string;
257
+ reason: string;
258
+ patterns: MatchPattern[];
259
+ /** 默认 false(任一命中);true 时需全部命中 */
260
+ requireAll: boolean;
261
+ /** 字段名 → 正则(取第一个捕获组);未命中该字段填 null */
262
+ extract: Record<string, string>;
263
+ };
264
+
265
+ export type ClassifierRulesConfig = { classifiers: ClassifierRule[] };
266
+
267
+ export type ClassifyMatch = {
268
+ issueType: string;
269
+ module?: string;
270
+ reason: string;
271
+ extracted: Record<string, string | null>;
272
+ };
273
+
274
+ function parseClassifierRules(raw: Record<string, unknown>, issues: string[]): ClassifierRulesConfig | null {
275
+ const out: ClassifierRule[] = [];
276
+ const rawList = Array.isArray(raw.classifiers) ? raw.classifiers : [];
277
+ for (let i = 0; i < rawList.length; i++) {
278
+ const c = rawList[i] as Record<string, unknown> | null;
279
+ if (!c || typeof c !== "object") {
280
+ issues.push(`classifiers[${i}] 不是对象`);
281
+ continue;
282
+ }
283
+ const issueType = String(c.issueType ?? "").trim();
284
+ if (!issueType) {
285
+ issues.push(`classifiers[${i}] 缺少 issueType`);
286
+ continue;
287
+ }
288
+ const patterns = normalizePatterns(c.patterns, `classifiers[${issueType}]`, issues);
289
+ if (patterns.length === 0) {
290
+ issues.push(`classifiers[${issueType}] 无有效 patterns`);
291
+ continue;
292
+ }
293
+ const extract: Record<string, string> = {};
294
+ const rawExtract = c.extract as Record<string, unknown> | undefined;
295
+ if (rawExtract && typeof rawExtract === "object") {
296
+ for (const [field, rx] of Object.entries(rawExtract)) {
297
+ const pattern = String(rx ?? "");
298
+ try {
299
+ new RegExp(pattern);
300
+ extract[field] = pattern;
301
+ } catch {
302
+ issues.push(`classifiers[${issueType}].extract.${field} 非法正则: ${pattern}`);
303
+ }
304
+ }
305
+ }
306
+ out.push({
307
+ issueType,
308
+ ...(String(c.module ?? "").trim() ? { module: String(c.module).trim() } : {}),
309
+ reason: String(c.reason ?? `命中 ${issueType} 分类规则`).trim(),
310
+ patterns,
311
+ requireAll: c.require_all === true,
312
+ extract,
313
+ });
314
+ }
315
+ // 无有效分类器 = 关闭(交给下游语义处理)
316
+ return out.length > 0 ? { classifiers: out } : null;
317
+ }
318
+
319
+ /** 加载分类器(相对 `<configDir>/profile/` 解析),按绝对路径缓存 */
320
+ export const loadClassifierRules = makeLoader<ClassifierRulesConfig>(
321
+ "profile",
322
+ parseClassifierRules,
323
+ { missing: "分类器文件不存在", parseFail: "分类器解析失败" },
324
+ );
325
+
326
+ function extractFields(extract: Record<string, string>, message: string): Record<string, string | null> {
327
+ const out: Record<string, string | null> = {};
328
+ for (const [field, rx] of Object.entries(extract)) {
329
+ try {
330
+ const m = message.match(new RegExp(rx));
331
+ out[field] = m?.[1] ?? m?.[0] ?? null;
332
+ } catch {
333
+ out[field] = null;
334
+ }
335
+ }
336
+ return out;
337
+ }
338
+
339
+ /**
340
+ * 分类当前消息:按声明顺序返回第一个满足的分类器
341
+ * (require_all → 全部 pattern 命中;否则任一命中)。无命中返回 null。
342
+ */
343
+ export function classifyMessage(config: ClassifierRulesConfig | null, message: string): ClassifyMatch | null {
344
+ if (!config) return null;
345
+ const msg = message ?? "";
346
+ if (!msg.trim()) return null;
347
+ for (const c of config.classifiers) {
348
+ const ok = c.requireAll
349
+ ? c.patterns.every((p) => testPattern(p, msg))
350
+ : c.patterns.some((p) => testPattern(p, msg));
351
+ if (ok) {
352
+ return {
353
+ issueType: c.issueType,
354
+ ...(c.module ? { module: c.module } : {}),
355
+ reason: c.reason,
356
+ extracted: extractFields(c.extract, msg),
357
+ };
358
+ }
359
+ }
360
+ return null;
361
+ }
362
+
363
+ // ─── 整档 / 按群开关 ─────────────────────────────────────
364
+
365
+ /**
366
+ * 某个可选能力是否整档启用:所需目录(如 skills_dir)已配置且存在。
367
+ * 未配置或目录缺失 → 关闭。路径相对实例根解析。
368
+ */
369
+ export function isCapabilityEnabled(configDir: string, dirRel: string | undefined): boolean {
370
+ const rel = String(dirRel ?? "").trim();
371
+ if (!rel) return false;
372
+ return existsSync(path.resolve(configDir, rel));
373
+ }
374
+
375
+ type GroupToggleRow = Record<string, unknown>;
376
+ const TRUE_VALUES = new Set(["true", "1", "yes", "on", "是", "开启", "启用", "已勾选"]);
377
+
378
+ function explicitTrue(value: unknown): boolean {
379
+ if (value === true || value === 1) return true;
380
+ return typeof value === "string" && TRUE_VALUES.has(value.trim().toLowerCase());
381
+ }
382
+
383
+ /**
384
+ * 按群开关:仅当群配置快照里该群的开关字段**明确为真**才启用。
385
+ * 群缺失、字段缺失、未知值一律关闭(宁可不做,不可乱做)。
386
+ */
387
+ export function isGroupToggleEnabled(
388
+ raw: unknown,
389
+ conversationId: string,
390
+ field: string,
391
+ idField = "groupId",
392
+ ): boolean {
393
+ if (!conversationId || !Array.isArray(raw)) return false;
394
+ const group = (raw as GroupToggleRow[]).find(
395
+ (g) => String(g?.[idField] ?? "").trim() === conversationId,
396
+ );
397
+ return explicitTrue(group?.[field]);
398
+ }
@@ -0,0 +1,151 @@
1
+ import { DwsClient, logger } from "aitable-workflow-core";
2
+
3
+ /**
4
+ * aitable-workflow — 钉钉群成员在群判定(能不能真实 @ 到这个人)
5
+ *
6
+ * 用途:升级找人时要在群里 @ 负责人,但负责人未必在该群。@ 一个不在群的人钉钉不会
7
+ * 真正提醒到他,还会在消息里留下无意义的数字工号。故发送前先判定:
8
+ * - 在群 → { mode: "at", userId },由发送层配合 mentionUserIds 真实 @;
9
+ * - 判不了 → { mode: "name" },调用方只渲染花名,绝不写假 @、绝不出数字 uid。
10
+ *
11
+ * 硬不变量:**任何失败都降级为 `{ mode: "name" }`,绝不向主流程抛错。**
12
+ * 参数缺失、命令失败、超时、响应解析失败、人不在群——一律 name。找人是加分项,
13
+ * 不能因为它挂掉而让整条答疑链路失败。
14
+ *
15
+ * 命令统一走 DwsClient(而非自建 spawn):拿到退避重试(消化 dws 后端偶发 TIMEOUT /
16
+ * 伪 AUTH_PERMISSION_DENIED)与连续失败升级告警。降级时打一条 debug/warn,不再无声失败。
17
+ *
18
+ * 结果按 (conversationId, userId, openDingTalkId) 缓存:TTL 10 分钟、上限 500 条、
19
+ * Map 插入顺序作轻量 LRU。群成员变动不频繁,缓存显著削减 dws 调用。
20
+ */
21
+
22
+ export type GroupMention =
23
+ | { mode: "at"; userId: string }
24
+ | { mode: "name" };
25
+
26
+ /** 待判定的联系人:userId 用于真实 @,openDingTalkId 用于群成员查询 */
27
+ export type MentionCandidate = {
28
+ userId: string;
29
+ openDingTalkId?: string;
30
+ };
31
+
32
+ export type GroupMembershipDeps = {
33
+ /** 注入 dws 执行器(测试用);缺省新建 DwsClient */
34
+ dws?: Pick<DwsClient, "runJson">;
35
+ /** dws 可执行文件名(对齐 settings.tracker.dws_bin),缺省 "dws" */
36
+ dwsBin?: string;
37
+ /** 注入时钟(测试用) */
38
+ now?: () => number;
39
+ };
40
+
41
+ type CacheEntry = { value: GroupMention; expiresAt: number };
42
+
43
+ const DWS_TIMEOUT_MS = 8_000;
44
+ const CACHE_TTL_MS = 10 * 60_000;
45
+ const CACHE_MAX = 500;
46
+
47
+ const memberCache = new Map<string, CacheEntry>();
48
+
49
+ function getCached(key: string, now: number): GroupMention | undefined {
50
+ const hit = memberCache.get(key);
51
+ if (!hit) return undefined;
52
+ if (hit.expiresAt <= now) {
53
+ memberCache.delete(key);
54
+ return undefined;
55
+ }
56
+ // Map 插入顺序作为轻量 LRU;命中后移到队尾
57
+ memberCache.delete(key);
58
+ memberCache.set(key, hit);
59
+ return hit.value;
60
+ }
61
+
62
+ function setCached(key: string, value: GroupMention, expiresAt: number): void {
63
+ memberCache.delete(key);
64
+ memberCache.set(key, { value, expiresAt });
65
+ while (memberCache.size > CACHE_MAX) {
66
+ const oldest = memberCache.keys().next().value as string | undefined;
67
+ if (oldest === undefined) break;
68
+ memberCache.delete(oldest);
69
+ }
70
+ }
71
+
72
+ /** 从 dws 响应里取 result.members 数组;结构不符一律视为空 */
73
+ function memberList(payload: unknown): Array<Record<string, unknown>> {
74
+ if (!payload || typeof payload !== "object") return [];
75
+ const result = (payload as Record<string, unknown>).result;
76
+ if (!result || typeof result !== "object" || Array.isArray(result)) return [];
77
+ const members = (result as Record<string, unknown>).members;
78
+ return Array.isArray(members)
79
+ ? members.filter(
80
+ (item): item is Record<string, unknown> =>
81
+ Boolean(item) && typeof item === "object" && !Array.isArray(item),
82
+ )
83
+ : [];
84
+ }
85
+
86
+ /** 兼容两种大小写拼写(不同 dws 版本返回不一致) */
87
+ function readOpenDingTalkId(item: Record<string, unknown>): string {
88
+ const value = item.openDingTalkId ?? item.openDingtalkId;
89
+ return typeof value === "string" ? value.trim() : "";
90
+ }
91
+
92
+ /**
93
+ * 判定某联系人能否在目标群被真实 @。
94
+ *
95
+ * userId / openDingTalkId 由调用方从自己的联系人快照传入(本函数不做联系人解析),
96
+ * 这里只做「在不在这个群」的校验。
97
+ */
98
+ export async function resolveGroupMention(
99
+ conversationId: string,
100
+ candidate: MentionCandidate,
101
+ deps: GroupMembershipDeps = {},
102
+ ): Promise<GroupMention> {
103
+ const cid = String(conversationId ?? "").trim();
104
+ const userId = String(candidate?.userId ?? "").trim();
105
+ const openDingTalkId = String(candidate?.openDingTalkId ?? "").trim();
106
+ const fallback: GroupMention = { mode: "name" };
107
+
108
+ if (!cid || !userId || !openDingTalkId) {
109
+ logger.debug("group-membership", "参数不足,降级为花名", {
110
+ hasCid: Boolean(cid), hasUserId: Boolean(userId), hasOpenId: Boolean(openDingTalkId),
111
+ });
112
+ return fallback;
113
+ }
114
+
115
+ const now = (deps.now ?? Date.now)();
116
+ const cacheKey = `${cid}\u0000${userId}\u0000${openDingTalkId}`;
117
+ const cached = getCached(cacheKey, now);
118
+ if (cached !== undefined) return cached;
119
+
120
+ const dws = deps.dws ?? new DwsClient({ bin: deps.dwsBin ?? "dws", timeoutMs: DWS_TIMEOUT_MS });
121
+
122
+ let result: GroupMention = fallback;
123
+ try {
124
+ // DwsClient.runJson 自动追加 --format json,这里不再手写
125
+ const payload = await dws.runJson(
126
+ ["chat", "group", "members", "list-by-ids", "--id", cid, "--users", openDingTalkId],
127
+ { timeoutMs: DWS_TIMEOUT_MS },
128
+ );
129
+ const matched = memberList(payload).some((m) => readOpenDingTalkId(m) === openDingTalkId);
130
+ if (matched) {
131
+ result = { mode: "at", userId };
132
+ } else {
133
+ logger.debug("group-membership", "联系人不在该群,降级为花名", { conversationId: cid });
134
+ }
135
+ } catch (error) {
136
+ // 找人是加分项:查询失败不影响主流程,但要留痕(此前是完全静默)
137
+ logger.warn("group-membership", "群成员查询失败,降级为花名", {
138
+ conversationId: cid,
139
+ error: error instanceof Error ? error.message : String(error),
140
+ });
141
+ result = fallback;
142
+ }
143
+
144
+ setCached(cacheKey, result, now + CACHE_TTL_MS);
145
+ return result;
146
+ }
147
+
148
+ /** 仅供单测隔离模块级缓存 */
149
+ export function resetGroupMembershipCache(): void {
150
+ memberCache.clear();
151
+ }
@@ -0,0 +1,18 @@
1
+ import { createFingerprintWindow } from "aitable-workflow-core";
2
+
3
+ /**
4
+ * support-qa 出站回声防护(echo guard)
5
+ *
6
+ * 背景:webhook 发出的机器人回复可能被 dws 轮询以"某个真人"的名义重新拉回
7
+ * (真实案例:机器人答案以创建者名义回流,身份匹配失效,被当新消息判定建行)。
8
+ * 方案:reply 发送成功后发布内容指纹;conversation_handler 同步比对,
9
+ * 命中即按机器人消息处理(只记历史,不建单)。
10
+ */
11
+
12
+ /** 出站内容指纹窗口:单 part = 回复正文(截断 300) */
13
+ export const echoWindow = createFingerprintWindow({
14
+ key: "sent_reply_fingerprints",
15
+ ttlMs: 10 * 60 * 1000,
16
+ capacity: 50,
17
+ maxPartLength: 300,
18
+ });
@@ -1,12 +1,64 @@
1
1
  import type { MemoryEntry, MemoryScope } from "aitable-workflow-core";
2
2
 
3
3
  /**
4
- * support-qa 记忆事件词表(场景层单一事实源)
4
+ * support-qa 记忆事件词表 + 工厂(场景层单一事实源)
5
5
  *
6
6
  * 写入方:conversation_handler(user/admin 消息)、answer(agent 决策)、reply(发送结果)。
7
7
  * 读取方:answer(长期记忆注入)、daily-review(复盘/学习提炼)。
8
8
  */
9
9
 
10
+ // ─── 记忆事件工厂(从 core 下沉)────────────────────────────
11
+
12
+ type MemoryEventsOptions = {
13
+ scenario: string;
14
+ channel: string;
15
+ questionKeyLength?: number;
16
+ summaryContentLength?: number;
17
+ };
18
+
19
+ type MemoryEntryArgs<Kind extends string = string, Role extends string = string> = {
20
+ kind: Kind;
21
+ content: string;
22
+ sender: string;
23
+ role: Role;
24
+ conversationId: string;
25
+ timestamp?: string;
26
+ summary?: string;
27
+ meta?: Record<string, unknown>;
28
+ };
29
+
30
+ type MemoryEvents<Kind extends string = string, Role extends string = string> = {
31
+ scope: (conversationId?: string) => MemoryScope;
32
+ entry: (args: MemoryEntryArgs<Kind, Role>) => MemoryEntry;
33
+ questionKey: (content: string) => string;
34
+ };
35
+
36
+ function createMemoryEvents<Kind extends string = string, Role extends string = string>(
37
+ options: MemoryEventsOptions,
38
+ ): MemoryEvents<Kind, Role> {
39
+ const { scenario, channel } = options;
40
+ const questionKeyLength = options.questionKeyLength ?? 120;
41
+ const summaryContentLength = options.summaryContentLength ?? 80;
42
+
43
+ return {
44
+ scope(conversationId?: string): MemoryScope {
45
+ return { channel, scenario, ...(conversationId ? { conversationId } : {}) };
46
+ },
47
+ entry(args: MemoryEntryArgs<Kind, Role>): MemoryEntry {
48
+ return {
49
+ timestamp: args.timestamp ?? new Date().toISOString(),
50
+ kind: args.kind,
51
+ content: args.content,
52
+ summary: args.summary ?? `${args.sender}: ${args.content.slice(0, summaryContentLength)}`,
53
+ meta: { sender: args.sender, role: args.role, conversationId: args.conversationId, ...args.meta },
54
+ };
55
+ },
56
+ questionKey(content: string): string {
57
+ return content.replace(/\s+/g, " ").trim().slice(0, questionKeyLength);
58
+ },
59
+ };
60
+ }
61
+
10
62
  export const SUPPORT_SCENARIO = "support-qa";
11
63
  export const SUPPORT_CHANNEL = "dingtalk";
12
64
 
@@ -51,44 +103,11 @@ export const SUPPORT_DECISION_CONTENT = {
51
103
  silent: "(静默)",
52
104
  } as const;
53
105
 
54
- /**
55
- * 问答关联键:把原始提问正文归一化成短期记忆事件之间的配对锚点。
56
- *
57
- * agent 侧事件(决策/发送事实/发送失败/失败兜底)都带 meta.question 回指提问,
58
- * 复盘据此配对首次响应时长;没有它就只能按时序 FIFO 猜,一旦有问题被静默或回复乱序就错位。
59
- */
60
- export function questionKey(content: string): string {
61
- return content.replace(/\s+/g, " ").trim().slice(0, 120);
62
- }
106
+ const events = createMemoryEvents<SupportMemoryKind, SupportMemoryRole>({
107
+ scenario: SUPPORT_SCENARIO,
108
+ channel: SUPPORT_CHANNEL,
109
+ });
63
110
 
64
- export function supportScope(conversationId?: string): MemoryScope {
65
- return {
66
- channel: SUPPORT_CHANNEL,
67
- scenario: SUPPORT_SCENARIO,
68
- ...(conversationId ? { conversationId } : {}),
69
- };
70
- }
71
-
72
- export function supportEntry(args: {
73
- kind: SupportMemoryKind;
74
- content: string;
75
- sender: string;
76
- role: SupportMemoryRole;
77
- conversationId: string;
78
- timestamp?: string;
79
- summary?: string;
80
- meta?: Record<string, unknown>;
81
- }): MemoryEntry {
82
- return {
83
- timestamp: args.timestamp ?? new Date().toISOString(),
84
- kind: args.kind,
85
- content: args.content,
86
- summary: args.summary ?? `${args.sender}: ${args.content.slice(0, 80)}`,
87
- meta: {
88
- sender: args.sender,
89
- role: args.role,
90
- conversationId: args.conversationId,
91
- ...args.meta,
92
- },
93
- };
94
- }
111
+ export const supportScope = events.scope;
112
+ export const supportEntry = events.entry;
113
+ export const questionKey = events.questionKey;