sophhub 0.2.1 → 0.2.2

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 (187) hide show
  1. package/package.json +1 -1
  2. package/skills/compact-context/skill.json +20 -0
  3. package/skills/compact-context/src/SKILL.md +133 -0
  4. package/skills/compact-context/src/scripts/check.sh +381 -0
  5. package/skills/compact-context/src/scripts/set-keep-recent.mjs +1337 -0
  6. package/skills/compact-context/src/scripts/setup.sh +96 -0
  7. package/skills/feishu-notes-assistant-universal/skill.json +20 -0
  8. package/skills/feishu-notes-assistant-universal/src/README.md +55 -0
  9. package/skills/feishu-notes-assistant-universal/src/SKILL.md +159 -0
  10. package/skills/feishu-notes-assistant-universal/src/bin/linux-amd64/lark-cli-openclaw +0 -0
  11. package/skills/feishu-notes-assistant-universal/src/bin/linux-arm64/lark-cli-openclaw +0 -0
  12. package/skills/feishu-notes-assistant-universal/src/scripts/_resolve_lark_cli.py +58 -0
  13. package/skills/feishu-notes-assistant-universal/src/scripts/openclaw_meeting_minutes.py +462 -0
  14. package/skills/feishu-notes-assistant-universal/src/scripts/openclaw_notes_crud.py +547 -0
  15. package/skills/feishu-notes-assistant-universal/src/scripts/openclaw_notes_crud_test.py +181 -0
  16. package/skills/feishu-notes-assistant-universal/src/scripts/run_meeting_minutes.py +80 -0
  17. package/skills/feishu-notes-assistant-universal/src/scripts/run_meeting_minutes.sh +5 -0
  18. package/skills/feishu-notes-assistant-universal/src/scripts/run_note_crud.py +32 -0
  19. package/skills/feishu-notes-assistant-universal/src/scripts/run_note_crud.sh +5 -0
  20. package/skills/image-classify/skill.json +5 -5
  21. package/skills/image-classify/src/SKILL.md +60 -67
  22. package/skills/image-classify/src/scripts/face_search.py +400 -15
  23. package/skills/image-classify/src/scripts/send_dm_message.py +332 -0
  24. package/skills/md2pdf-converter/skill.json +20 -0
  25. package/skills/md2pdf-converter/src/SKILL.md +244 -0
  26. package/skills/md2pdf-converter/src/_meta.json +6 -0
  27. package/skills/md2pdf-converter/src/scripts/generate_emoji_mapping.py +74 -0
  28. package/skills/md2pdf-converter/src/scripts/md2pdf-local.sh +291 -0
  29. package/skills/sophnet-bot-client/skill.json +20 -0
  30. package/skills/sophnet-bot-client/src/SKILL.md +255 -0
  31. package/skills/sophnet-bot-client/src/pyproject.toml +13 -0
  32. package/skills/sophnet-bot-client/src/scripts/__init__.py +0 -0
  33. package/skills/sophnet-bot-client/src/scripts/bot_client_proxy.py +165 -0
  34. package/skills/sophnet-bot-client/src/scripts/bot_client_safe.sh +29 -0
  35. package/skills/sophnet-bot-client/src/scripts/bot_client_setup.py +502 -0
  36. package/skills/sophnet-bot-client/src/tests/__init__.py +0 -0
  37. package/skills/sophnet-bot-client/src/tests/test_bot_client_proxy.py +255 -0
  38. package/skills/sophnet-bot-client/src/tests/test_bot_client_setup.py +679 -0
  39. package/skills/sophnet-bot-client/src/uv.lock +8 -0
  40. package/skills/sophnet-docx/skill.json +20 -0
  41. package/skills/sophnet-docx/src/SKILL.md +463 -0
  42. package/skills/sophnet-docx/src/package-lock.json +208 -0
  43. package/skills/sophnet-docx/src/package.json +16 -0
  44. package/skills/sophnet-docx/src/pyproject.toml +11 -0
  45. package/skills/sophnet-docx/src/scripts/__init__.py +1 -0
  46. package/skills/sophnet-docx/src/scripts/accept_changes.py +135 -0
  47. package/skills/sophnet-docx/src/scripts/comment.py +318 -0
  48. package/skills/sophnet-docx/src/scripts/ensure_uv_env.sh +68 -0
  49. package/skills/sophnet-docx/src/scripts/office/helpers/__init__.py +0 -0
  50. package/skills/sophnet-docx/src/scripts/office/helpers/merge_runs.py +199 -0
  51. package/skills/sophnet-docx/src/scripts/office/helpers/simplify_redlines.py +197 -0
  52. package/skills/sophnet-docx/src/scripts/office/pack.py +159 -0
  53. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  54. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  55. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  56. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  57. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  58. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  59. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  60. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  61. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  62. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  63. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  64. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  65. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  66. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  67. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  68. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  69. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  70. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  71. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  72. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  73. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  74. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  75. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  76. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  77. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  78. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  79. package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  80. package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  81. package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  82. package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  83. package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  84. package/skills/sophnet-docx/src/scripts/office/schemas/mce/mc.xsd +75 -0
  85. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
  86. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
  87. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
  88. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
  89. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
  90. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  91. package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
  92. package/skills/sophnet-docx/src/scripts/office/soffice.py +183 -0
  93. package/skills/sophnet-docx/src/scripts/office/unpack.py +132 -0
  94. package/skills/sophnet-docx/src/scripts/office/validate.py +111 -0
  95. package/skills/sophnet-docx/src/scripts/office/validators/__init__.py +15 -0
  96. package/skills/sophnet-docx/src/scripts/office/validators/base.py +847 -0
  97. package/skills/sophnet-docx/src/scripts/office/validators/docx.py +446 -0
  98. package/skills/sophnet-docx/src/scripts/office/validators/pptx.py +275 -0
  99. package/skills/sophnet-docx/src/scripts/office/validators/redlining.py +247 -0
  100. package/skills/sophnet-docx/src/scripts/templates/comments.xml +3 -0
  101. package/skills/sophnet-docx/src/scripts/templates/commentsExtended.xml +3 -0
  102. package/skills/sophnet-docx/src/scripts/templates/commentsExtensible.xml +3 -0
  103. package/skills/sophnet-docx/src/scripts/templates/commentsIds.xml +3 -0
  104. package/skills/sophnet-docx/src/scripts/templates/people.xml +3 -0
  105. package/skills/sophnet-docx/src/scripts/upload_file.sh +96 -0
  106. package/skills/sophnet-docx/src/uv.lock +320 -0
  107. package/skills/sophnet-pdf/skill.json +20 -0
  108. package/skills/sophnet-pdf/src/SKILL.md +413 -0
  109. package/skills/sophnet-pdf/src/forms.md +297 -0
  110. package/skills/sophnet-pdf/src/pyproject.toml +14 -0
  111. package/skills/sophnet-pdf/src/reference.md +612 -0
  112. package/skills/sophnet-pdf/src/scripts/check_bounding_boxes.py +65 -0
  113. package/skills/sophnet-pdf/src/scripts/check_fillable_fields.py +11 -0
  114. package/skills/sophnet-pdf/src/scripts/convert_pdf_to_images.py +33 -0
  115. package/skills/sophnet-pdf/src/scripts/create_validation_image.py +37 -0
  116. package/skills/sophnet-pdf/src/scripts/enhance_tutorial.py +558 -0
  117. package/skills/sophnet-pdf/src/scripts/ensure_uv_env.sh +68 -0
  118. package/skills/sophnet-pdf/src/scripts/extract_form_field_info.py +122 -0
  119. package/skills/sophnet-pdf/src/scripts/extract_form_structure.py +115 -0
  120. package/skills/sophnet-pdf/src/scripts/extract_pdf_content.py +35 -0
  121. package/skills/sophnet-pdf/src/scripts/fill_fillable_fields.py +98 -0
  122. package/skills/sophnet-pdf/src/scripts/fill_pdf_form_with_annotations.py +107 -0
  123. package/skills/sophnet-pdf/src/scripts/upload_file.sh +88 -0
  124. package/skills/sophnet-pdf/src/uv.lock +537 -0
  125. package/skills/sophnet-xlsx/skill.json +20 -0
  126. package/skills/sophnet-xlsx/src/SKILL.md +399 -0
  127. package/skills/sophnet-xlsx/src/pyproject.toml +11 -0
  128. package/skills/sophnet-xlsx/src/scripts/ensure_uv_env.sh +68 -0
  129. package/skills/sophnet-xlsx/src/scripts/office/helpers/__init__.py +0 -0
  130. package/skills/sophnet-xlsx/src/scripts/office/helpers/merge_runs.py +199 -0
  131. package/skills/sophnet-xlsx/src/scripts/office/helpers/simplify_redlines.py +197 -0
  132. package/skills/sophnet-xlsx/src/scripts/office/pack.py +159 -0
  133. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  134. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  135. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  136. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  137. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  138. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  139. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  140. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  141. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  142. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  143. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  144. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  145. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  146. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  147. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  148. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  149. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  150. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  151. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  152. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  153. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  154. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  155. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  156. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  157. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  158. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  159. package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  160. package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  161. package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  162. package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  163. package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  164. package/skills/sophnet-xlsx/src/scripts/office/schemas/mce/mc.xsd +75 -0
  165. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
  166. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
  167. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
  168. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
  169. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
  170. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  171. package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
  172. package/skills/sophnet-xlsx/src/scripts/office/soffice.py +183 -0
  173. package/skills/sophnet-xlsx/src/scripts/office/unpack.py +132 -0
  174. package/skills/sophnet-xlsx/src/scripts/office/validate.py +111 -0
  175. package/skills/sophnet-xlsx/src/scripts/office/validators/__init__.py +15 -0
  176. package/skills/sophnet-xlsx/src/scripts/office/validators/base.py +847 -0
  177. package/skills/sophnet-xlsx/src/scripts/office/validators/docx.py +446 -0
  178. package/skills/sophnet-xlsx/src/scripts/office/validators/pptx.py +275 -0
  179. package/skills/sophnet-xlsx/src/scripts/office/validators/redlining.py +247 -0
  180. package/skills/sophnet-xlsx/src/scripts/recalc.py +184 -0
  181. package/skills/sophnet-xlsx/src/scripts/upload_file.sh +96 -0
  182. package/skills/sophnet-xlsx/src/uv.lock +319 -0
  183. package/skills/wechat-article-publisher/skill.json +20 -0
  184. package/skills/wechat-article-publisher/src/SKILL.md +60 -0
  185. package/skills/wechat-article-publisher/src/config.json +7 -0
  186. package/skills/wechat-article-publisher/src/pyproject.toml +12 -0
  187. package/skills/wechat-article-publisher/src/scripts/publish_wechat.py +825 -0
@@ -0,0 +1,291 @@
1
+ #!/bin/bash
2
+
3
+ # ==============================================================================
4
+ # md2pdf-local.sh
5
+ # 描述: 离线版 Markdown 转 PDF (完整版 Emoji + 本地缓存)
6
+ # 版本: 2.0 (Twemoji 完整版)
7
+ # 核心: Pandoc + WeasyPrint + Local Emoji Cache (Twemoji 完整版)
8
+ # ==============================================================================
9
+
10
+ set -e
11
+
12
+ # --- 配置项 ---
13
+ CACHE_DIR="$HOME/.cache/md2pdf"
14
+ EMOJI_DIR="$CACHE_DIR/emojis"
15
+ EMOJI_MAPPING="$CACHE_DIR/emoji_mapping.json"
16
+ # 使用 Twemoji 14.0.0 完整版 (彩色 PNG, 3660个文件)
17
+ TWEMOJI_VERSION="14.0.0"
18
+ TWEMOJI_URL="https://github.com/twitter/twemoji/archive/refs/tags/v${TWEMOJI_VERSION}.tar.gz"
19
+
20
+ # --- 检查参数 ---
21
+ if [ "$#" -ne 2 ]; then
22
+ echo "用法: $0 <input.md> <output.pdf>"
23
+ exit 1
24
+ fi
25
+
26
+ INPUT_FILE="$1"
27
+ OUTPUT_FILE="$2"
28
+ TEMP_DIR=$(mktemp -d)
29
+ HTML_TEMP="$TEMP_DIR/temp.html"
30
+ LUA_FILTER="$TEMP_DIR/emoji_twemoji.lua"
31
+ CSS_STYLE="$TEMP_DIR/style.css"
32
+ EMOJI_JS="$TEMP_DIR/emoji_data.js"
33
+
34
+ # --- 清理函数 ---
35
+ cleanup() {
36
+ rm -rf "$TEMP_DIR"
37
+ }
38
+ trap cleanup EXIT
39
+
40
+ # --- 1. 检查并下载 Twemoji 完整版 (只需执行一次) ---
41
+ ensure_twemoji() {
42
+ if [ -f "$EMOJI_MAPPING" ]; then
43
+ echo "✅ Twemoji 资源已缓存: $EMOJI_DIR"
44
+ echo " 映射表: $EMOJI_MAPPING"
45
+ return 0
46
+ fi
47
+
48
+ echo "🚧 正在设置 Twemoji ${TWEMOJI_VERSION}..."
49
+ mkdir -p "$CACHE_DIR"
50
+
51
+ # 下载 GitHub 的 tar.gz 包
52
+ echo " 下载 Twemoji..."
53
+ wget -q --show-progress -O "$CACHE_DIR/twemoji.tar.gz" "$TWEMOJI_URL"
54
+
55
+ # 解压 Twemoji
56
+ echo " 解压 Twemoji..."
57
+ tar -xzf "$CACHE_DIR/twemoji.tar.gz" -C "$CACHE_DIR"
58
+
59
+ # Twemoji 目录结构: twemoji-14.0.0/assets/72x72/
60
+ # 移动到最终目录
61
+ mv "$CACHE_DIR/twemoji-${TWEMOJI_VERSION}/assets/72x72" "$EMOJI_DIR"
62
+
63
+ # 清理
64
+ rm -rf "$CACHE_DIR/twemoji-${TWEMOJI_VERSION}" "$CACHE_DIR/twemoji.tar.gz"
65
+
66
+ echo " Twemoji 已缓存至: $EMOJI_DIR"
67
+
68
+ # 生成 emoji 映射表
69
+ echo " 生成 emoji 映射表..."
70
+ python3 /home/ltx/.openclaw/workspace/skills/md2pdf-converter/scripts/generate_emoji_mapping.py
71
+
72
+ echo "✅ Twemoji 完整版已准备就绪"
73
+ }
74
+
75
+ ensure_twemoji
76
+
77
+ # --- 2. 生成 Lua Filter (使用 emoji 映射表) ---
78
+ cat << 'EOF' > "$LUA_FILTER"
79
+ -- 使用 emoji 映射表的 Lua Filter
80
+
81
+ -- 读取 emoji 映射表
82
+ local emoji_mapping = {}
83
+ local mapping_file = io.open("EMOJI_MAPPING_PLACEHOLDER", "r")
84
+
85
+ if mapping_file then
86
+ local json_str = mapping_file:read("*all")
87
+ mapping_file:close()
88
+
89
+ -- 解析 JSON (使用简单的正则表达式提取)
90
+ for k, v in json_str:gmatch('"([^"]*)"%s*:%s*"([^"]*)"') do
91
+ emoji_mapping[k] = v
92
+ end
93
+ end
94
+
95
+ function Str(el)
96
+ local text = el.text
97
+ if #text == 0 then
98
+ return nil
99
+ end
100
+
101
+ -- 检查文本是否包含 emoji
102
+ local contains_emoji = false
103
+ for p, c in utf8.codes(text) do
104
+ -- Emoji 范围检测 (更全面)
105
+ if (c >= 0x1F600 and c <= 0x1F64F) or -- Emoticons
106
+ (c >= 0x1F300 and c <= 0x1F5FF) or -- Misc Symbols and Pictographs
107
+ (c >= 0x1F680 and c <= 0x1F6FF) or -- Transport and Map
108
+ (c >= 0x1F900 and c <= 0x1F9FF) or -- Supplemental Symbols and Pictographs
109
+ (c >= 0x2600 and c <= 0x26FF) or -- Misc Symbols
110
+ (c >= 0x2700 and c <= 0x27BF) or -- Dingbats
111
+ (c >= 0x1F1E0 and c <= 0x1F1FF) or -- Regional Indicator Symbols
112
+ (c >= 0x1F200 and c <= 0x1F2FF) or -- Enclosed Alphanumerics
113
+ (c >= 0x2B50 and c <= 0x2BFF) or -- Glagolitic Supplement
114
+ (c >= 0x1F004 and c <= 0x1F0FF) or -- Mahjong Tiles
115
+ (c >= 0x1F0C0 and c <= 0x1F0FF) or -- Domino Tiles
116
+ (c >= 0x0FE0 and c <= 0x0FE0) or -- Variation Selectors
117
+ (c >= 0x1F300 and c <= 0x1F5FF) or -- Misc Symbols
118
+ (c >= 0x1F680 and c <= 0x1F6FF) then -- Transport and Map
119
+ contains_emoji = true
120
+ break
121
+ end
122
+ end
123
+
124
+ -- 如果不包含 emoji,直接返回 nil
125
+ if not contains_emoji then
126
+ return nil
127
+ end
128
+
129
+ -- 如果包含 emoji,逐字符处理
130
+ local new_inlines = {}
131
+ local emoji_dir = "EMOJI_DIR_PLACEHOLDER"
132
+
133
+ for p, c in utf8.codes(text) do
134
+ local emoji_char = utf8.char(c)
135
+ local is_emoji = false
136
+
137
+ -- 检测 emoji
138
+ if (c >= 0x1F600 and c <= 0x1F64F) or -- Emoticons
139
+ (c >= 0x1F300 and c <= 0x1F5FF) or -- Misc Symbols and Pictographs
140
+ (c >= 0x1F680 and c <= 0x1F6FF) or -- Transport and Map
141
+ (c >= 0x1F900 and c <= 0x1F9FF) or -- Supplemental Symbols and Pictographs
142
+ (c >= 0x2600 and c <= 0x26FF) or -- Misc Symbols
143
+ (c >= 0x2700 and c <= 0x27BF) or -- Dingbats
144
+ (c >= 0x1F1E0 and c <= 0x1F1FF) or -- Regional Indicator Symbols
145
+ (c >= 0x1F200 and c <= 0x1F2FF) or -- Enclosed Alphanumerics
146
+ (c >= 0x2B50 and c <= 0x2BFF) or -- Glagolitic Supplement
147
+ (c >= 0x1F004 and c <= 0x1F0FF) or -- Mahjong Tiles
148
+ (c >= 0x1F0C0 and c <= 0x1F0FF) or -- Domino Tiles
149
+ (c >= 0x0FE0 and c <= 0x0FE0) or -- Variation Selectors
150
+ (c >= 0x1F300 and c <= 0x1F5FF) or -- Misc Symbols
151
+ (c >= 0x1F680 and c <= 0x1F6FF) then -- Transport and Map
152
+ is_emoji = true
153
+ end
154
+
155
+ if is_emoji then
156
+ -- 查找对应的文件名
157
+ local filename = emoji_mapping[emoji_char]
158
+
159
+ if filename then
160
+ -- 构建本地 file:// 路径
161
+ local url = "file://" .. emoji_dir .. "/" .. filename
162
+
163
+ -- 生成 HTML img 标签
164
+ local img_html = string.format(
165
+ '<img src="%s" class="emoji" alt="%s" style="height:1.1em;width:1.1em;vertical-align:-0.2em;display:inline-block;margin:0 0.05em;">',
166
+ url,
167
+ emoji_char
168
+ )
169
+
170
+ table.insert(new_inlines, pandoc.RawInline('html', img_html))
171
+ else
172
+ -- 如果找不到对应的文件,保持原字符
173
+ table.insert(new_inlines, pandoc.Str(emoji_char))
174
+ end
175
+ else
176
+ table.insert(new_inlines, pandoc.Str(emoji_char))
177
+ end
178
+ end
179
+
180
+ if #new_inlines > 0 then
181
+ return new_inlines
182
+ else
183
+ return nil
184
+ end
185
+ end
186
+ EOF
187
+
188
+ # 替换 Lua 模板中的路径占位符
189
+ sed -e "s|EMOJI_DIR_PLACEHOLDER|$EMOJI_DIR|g; s|EMOJI_MAPPING_PLACEHOLDER|$EMOJI_MAPPING|g" "$LUA_FILTER" > "${LUA_FILTER}.tmp"
190
+ mv "${LUA_FILTER}.tmp" "$LUA_FILTER"
191
+
192
+ # --- 3. 生成 CSS 样式 ---
193
+ cat << 'EOF' > "$CSS_STYLE"
194
+ @page {
195
+ size: A4;
196
+ margin: 2.5cm;
197
+ @bottom-center {
198
+ content: "Page " counter(page);
199
+ font-family: "AR PL UMing CN", "Noto Sans SC", sans-serif;
200
+ font-size: 9pt;
201
+ color: #888;
202
+ }
203
+ }
204
+
205
+ body {
206
+ font-family: "AR PL UMing CN", "AR PL SungtiL GB", "AR PL KaitiM GB", "Noto Sans SC", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif;
207
+ line-height: 1.6;
208
+ font-size: 11pt;
209
+ color: #333;
210
+ }
211
+
212
+ /* Emoji 样式:确保彩色 PNG 正确显示 */
213
+ img.emoji {
214
+ height: 1.1em;
215
+ width: 1.1em;
216
+ vertical-align: -0.2em;
217
+ display: inline-block;
218
+ margin: 0 0.05em;
219
+ /* 强制彩色显示 */
220
+ image-rendering: auto;
221
+ }
222
+
223
+ h1, h2, h3 {
224
+ font-family: "AR PL UMing CN", "AR PL SungtiL GB", "AR PL KaitiM GB", "Noto Sans SC", sans-serif;
225
+ font-weight: bold;
226
+ color: #2c3e50;
227
+ }
228
+
229
+ h1 {
230
+ border-bottom: 2px solid #eee;
231
+ padding-bottom: 0.3em;
232
+ }
233
+
234
+ code {
235
+ background-color: #f5f5f5;
236
+ padding: 2px 4px;
237
+ border-radius: 3px;
238
+ font-family: "Menlo", "Monaco", monospace;
239
+ }
240
+
241
+ pre {
242
+ background-color: #f5f5f5;
243
+ padding: 1em;
244
+ border-radius: 5px;
245
+ overflow-x: auto;
246
+ }
247
+
248
+ blockquote {
249
+ border-left: 4px solid #ddd;
250
+ padding-left: 1em;
251
+ color: #777;
252
+ font-style: italic;
253
+ }
254
+
255
+ table {
256
+ border-collapse: collapse;
257
+ width: 100%;
258
+ margin: 1em 0;
259
+ }
260
+
261
+ th, td {
262
+ border: 1px solid #ddd;
263
+ padding: 8px;
264
+ text-align: left;
265
+ }
266
+
267
+ th {
268
+ background-color: #f8f9fa;
269
+ }
270
+ EOF
271
+
272
+ # --- 4. 执行转换 ---
273
+
274
+ echo "📝 正在处理 Markdown (使用 Twemoji 完整版 ${TWEMOJI_VERSION})..."
275
+ pandoc "$INPUT_FILE" \
276
+ --lua-filter="$LUA_FILTER" \
277
+ --css="$CSS_STYLE" \
278
+ --metadata title=" " \
279
+ --standalone \
280
+ -o "$HTML_TEMP"
281
+
282
+ echo "🖨️ 正在生成 PDF..."
283
+ weasyprint "$HTML_TEMP" "$OUTPUT_FILE"
284
+
285
+ echo "✨ 转换成功: $OUTPUT_FILE"
286
+ echo ""
287
+ echo "📊 Emoji 信息:"
288
+ echo " - 版本: Twemoji ${TWEMOJI_VERSION}"
289
+ echo " - 数量: 3660 个彩色 PNG (包含变体)"
290
+ echo " - 大小: 72x72px"
291
+ echo " - 位置: $EMOJI_DIR"
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "sophnet-bot-client",
3
+ "version": "1.0.0",
4
+ "types": [
5
+ "store"
6
+ ],
7
+ "displayName": "远程BotAPI连接器",
8
+ "description": "为代理配置远程 Bot API 连接,支持 raw 与 proxy 两种模式,并提供连接配置与移除能力。",
9
+ "changelog": [
10
+ {
11
+ "version": "1.0.0",
12
+ "date": "2026-04-13",
13
+ "changes": [
14
+ "初次提交"
15
+ ]
16
+ }
17
+ ],
18
+ "createdAt": "2026-04-13",
19
+ "updatedAt": "2026-04-13"
20
+ }
@@ -0,0 +1,255 @@
1
+ ---
2
+ name: sophnet-bot-client
3
+ description: |
4
+ 为代理配置远程 Bot API 连接。支持两种模式:
5
+ - raw: 注入 curl 模板(无权限强制)
6
+ - proxy: 注入权限代理,程序化权限检查(推荐)
7
+ commands:
8
+ - /bot-client setup — 配置远程连接
9
+ - /bot-client remove — 移除远程连接
10
+ metadata:
11
+ openclaw:
12
+ emoji: "🔗"
13
+ requires:
14
+ bins: ["uv"]
15
+ env: []
16
+ ---
17
+
18
+ # Bot API Client Skill
19
+
20
+ 为代理注入远程协作能力。
21
+
22
+ **两种模式:**
23
+
24
+ - **raw**(旧模式):将 curl 模板 + 凭据路径写入 AGENTS.md,代理直接用 curl 对话。权限仅靠 LLM 文本约束。
25
+ - **proxy**(推荐):通过 `bot_client_safe.sh` → `bot_client_proxy.py` 代理链路,**程序化检查权限后**再转发请求。凭据对代理不可见。
26
+
27
+ ## 强制要求:工作目录
28
+
29
+ **所有命令必须在本 skill 目录下执行:**
30
+
31
+ ```bash
32
+ SKILL_DIR="<本skill的sophnet-bot-client目录绝对路径>"
33
+ cd "$SKILL_DIR"
34
+ ```
35
+
36
+ ## Python 运行环境(uv)
37
+
38
+ **所有 Python 执行必须使用 `uv run --project .`,禁止直接使用 `python` 或 `pip install`。**
39
+
40
+ 首次使用需初始化:
41
+
42
+ ```bash
43
+ cd "$SKILL_DIR" && uv sync --project .
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Processing Mode
49
+
50
+ **STRICT SERIAL PROCESSING ONLY** — 按顺序逐步执行,不要拆分子任务或并行处理。
51
+
52
+ ---
53
+
54
+ ## 命令参考
55
+
56
+ ### setup — 配置远程连接
57
+
58
+ **proxy 模式(推荐):**
59
+
60
+ ```bash
61
+ cd "$SKILL_DIR" && uv run --project . python scripts/bot_client_setup.py setup \
62
+ --agent-id "<本地代理 ID>" \
63
+ --url "https://{远端 Sophnet 实例域名}/bot-api/v2/{远端 account_id}/chat" \
64
+ --secret "<远端 api_secret>" \
65
+ --remote-agent-id "<远端 agent ID>" \
66
+ --mode proxy
67
+ ```
68
+
69
+ **raw 模式(旧模式):**
70
+
71
+ ```bash
72
+ cd "$SKILL_DIR" && uv run --project . python scripts/bot_client_setup.py setup \
73
+ --agent-id "<本地代理 ID>" \
74
+ --url "https://{远端 Sophnet 实例域名}/bot-api/v2/{远端 account_id}/chat" \
75
+ --secret "<远端 api_secret>" \
76
+ --remote-agent-id "<远端 agent ID>"
77
+ ```
78
+
79
+ | 参数 | 必填 | 说明 |
80
+ | ------------------- | ---- | ------------------------------------------------------------ |
81
+ | `--agent-id` | 是 | **本地**代理 ID |
82
+ | `--url` | 是 | **远端** Bot API URL,格式为 `https://{远端 Sophnet 实例域名}/bot-api/v2/{远端 account_id}/chat` |
83
+ | `--secret` | 是 | **远端** API Secret(Bearer token) |
84
+ | `--remote-agent-id` | 是 | **远端**目标 agent ID |
85
+ | `--mode` | 否 | `proxy`(默认)或 `raw`(旧模式);**必须用 `proxy`,`raw` 模式下 credentials 写到错误位置,激活检查永远不通过** |
86
+
87
+ **proxy 模式执行逻辑:**
88
+
89
+ 1. 在 admin_dir(`/home/node/.config/sophnet-customer-admin/<agent-id>/`)中保存凭据(对代理不可见)
90
+ 2. 在 AGENTS.md 追加「远程协作」章节(仅包含 `bot_client_safe.sh` 调用模板,无 curl/凭据)
91
+ 3. 将 `bot_client_safe.sh` 添加到 exec 白名单
92
+ 4. 设置 AGENTS.md 为只读(chmod 444)
93
+ 5. 幂等:重复执行会替换已有章节和凭据
94
+
95
+ **raw 模式执行逻辑:**
96
+
97
+ 1. 在代理 workspace 的 `data/bot_credentials.json` 中保存凭据
98
+ 2. 在 AGENTS.md 末尾追加「远程协作」章节(含 curl 模板、会话管理指令)
99
+ 3. 幂等:重复执行会替换已有章节和凭据
100
+
101
+ ### remove — 移除远程连接
102
+
103
+ ```bash
104
+ cd "$SKILL_DIR" && uv run --project . python scripts/bot_client_setup.py remove \
105
+ --agent-id "<本地代理 ID>"
106
+ ```
107
+
108
+ | 参数 | 必填 | 说明 |
109
+ | ------------ | ---- | --------------- |
110
+ | `--agent-id` | 是 | **本地**代理 ID |
111
+
112
+ **执行逻辑:**
113
+
114
+ 1. 从该代理的 AGENTS.md 中删除「远程协作」章节
115
+ 2. 删除该代理的远端凭据文件(workspace/data 和 admin_dir 均清理)
116
+
117
+ ---
118
+
119
+ ## 常见工作流
120
+
121
+ ### 工作流 1:为受管代理开通安全远程对话(推荐)
122
+
123
+ 先用 `agent_manager_cli.py` 创建代理(获得权限记录 + exec 白名单),再用 proxy 模式绑定。
124
+
125
+ **示例:** 本地代理 `vip-reader` 连接到远端实例 `moltbot-xxxx.sophnet.com` 上的 `memory_manager` agent:
126
+
127
+ ```bash
128
+ cd "$SKILL_DIR" && uv run --project . python scripts/bot_client_setup.py setup \
129
+ --agent-id "vip-reader" \
130
+ --url "https://moltbot-xxxx.sophnet.com/bot-api/v2/memory_manager-api/chat" \
131
+ --secret "remote_secret_abc123" \
132
+ --remote-agent-id "memory_manager" \
133
+ --mode proxy
134
+ ```
135
+
136
+ 其中:
137
+ - `vip-reader`:本地已创建的代理
138
+ - `moltbot-xxxx.sophnet.com`:远端 Sophnet 实例域名
139
+ - `memory_manager-api`:远端 Bot-API 的 account_id
140
+ - `remote_secret_abc123`:远端的 API Secret
141
+ - `memory_manager`:远端 agent ID
142
+
143
+ ### 工作流 2:更换远端地址或密钥
144
+
145
+ 直接重新运行 setup,会自动替换:
146
+
147
+ ```bash
148
+ cd "$SKILL_DIR" && uv run --project . python scripts/bot_client_setup.py setup \
149
+ --agent-id "vip-reader" \
150
+ --url "https://moltbot-yyyy.sophnet.com/bot-api/v2/new-account-api/chat" \
151
+ --secret "new_remote_secret_456" \
152
+ --remote-agent-id "new_remote_agent" \
153
+ --mode proxy
154
+ ```
155
+
156
+ ### 工作流 3:断开远程连接
157
+
158
+ ```bash
159
+ cd "$SKILL_DIR" && uv run --project . python scripts/bot_client_setup.py remove \
160
+ --agent-id "vip-reader"
161
+ ```
162
+
163
+ ---
164
+
165
+ ## 输出格式
166
+
167
+ **所有命令输出 JSON 到 stdout。**
168
+
169
+ ### 成功(setup)
170
+
171
+ ```json
172
+ {
173
+ "status": "ok",
174
+ "action": "setup_bot_client",
175
+ "agent_id": "vip-reader",
176
+ "url": "https://moltbot-xxxx.sophnet.com/bot-api/v2/memory_manager-api/chat",
177
+ "remote_agent_id": "memory_manager",
178
+ "workspace": "/home/node/.openclaw/workspace-customer-agents/vip-reader",
179
+ "credentials_file": "/home/node/.config/sophnet-customer-admin/vip-reader/bot_credentials.json"
180
+ }
181
+ ```
182
+
183
+ ### 成功(remove)
184
+
185
+ ```json
186
+ {
187
+ "status": "ok",
188
+ "action": "remove_bot_client",
189
+ "agent_id": "vip-reader",
190
+ "removed_section": true,
191
+ "removed_files": ["bot_credentials.json", "bot_session.txt"],
192
+ "workspace": "/home/node/.openclaw/workspace-customer-agents/vip-reader"
193
+ }
194
+ ```
195
+
196
+ ### 失败
197
+
198
+ ```json
199
+ {
200
+ "status": "error",
201
+ "action": "setup_bot_client",
202
+ "message": "Workspace not found: ...",
203
+ "fix": "请先使用 customer-agent create 创建代理"
204
+ }
205
+ ```
206
+
207
+ ---
208
+
209
+ ## 安全说明
210
+
211
+ ### proxy 模式(推荐)
212
+
213
+ - 凭据存储在 `/home/node/.config/sophnet-customer-admin/<agent-id>/`,对代理完全不可见
214
+ - AGENTS.md 仅包含 `bot_client_safe.sh` 调用模板,无 curl 命令、无凭据路径
215
+ - `bot_client_proxy.py` 在发送前检查 `permissions.json` 中的权限记录
216
+ - 请求 payload 中附带 `senderPermissions`,供服务端/接收方双重校验
217
+ - AGENTS.md 设为只读(chmod 444),防止代理篡改
218
+ - exec 白名单限制代理只能运行 `bot_client_safe.sh`
219
+
220
+ ### raw 模式(旧模式)
221
+
222
+ - Secret 存储在 `data/bot_credentials.json`(代理可见)
223
+ - AGENTS.md 包含 curl 模板和凭据文件路径
224
+ - 权限仅靠 LLM 文本约束,无程序化强制
225
+
226
+ ### 通用
227
+
228
+ - `--remote-agent-id` 必须填写为分发方 agent 的 ID,以确保权限链路正确传递
229
+
230
+ ## 已知问题:Docker 环境下 .sh 脚本无执行权限
231
+
232
+ **现象:** 代理执行 `bot_client_safe.sh` 时报 `Permission denied`(exit code 126)。
233
+
234
+ **原因:** `clawhub` 在 gateway 启动后才安装 skill,`.sh` 脚本可能没有执行权限。
235
+
236
+ **已有的自动修复机制(无需手动操作):**
237
+
238
+ 1. `bot_client_setup.py setup` 在查找 `.sh` 脚本时会自动补上执行权限
239
+ 2. `docker-entrypoint.sh` 后台每 15 秒检测并修复缺少执行权限的 `.sh` 文件(需使用最新版 entrypoint 重新构建镜像)
240
+
241
+ **如果仍遇到此问题(老镜像未重建):**
242
+
243
+ ```bash
244
+ # 在容器内手动执行
245
+ find /home/node/.openclaw/skills -name '*.sh' -exec chmod +x {} \;
246
+ ```
247
+
248
+ ## ⚠️ FORBIDDEN OPERATIONS
249
+
250
+ **Do NOT:**
251
+
252
+ - 直接编辑代理的 AGENTS.md(必须通过本脚本)
253
+ - 将 secret 明文写入 AGENTS.md 或其他非凭据文件中
254
+ - 在未创建代理的情况下执行 setup(必须先用 customer-agent create)
255
+ - 对需要权限约束的场景使用 raw 模式(应使用 proxy 模式)
@@ -0,0 +1,13 @@
1
+ [project]
2
+ name = "sophnet-bot-client"
3
+ version = "0.1.0"
4
+ description = "Bot API client setup — inject remote collaboration instructions into sub-agent AGENTS.md"
5
+ requires-python = ">=3.10"
6
+ dependencies = []
7
+
8
+ [tool.hatch.build.targets.wheel]
9
+ packages = ["scripts"]
10
+
11
+ [build-system]
12
+ requires = ["hatchling"]
13
+ build-backend = "hatchling.build"