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.
- package/package.json +1 -1
- package/skills/compact-context/skill.json +20 -0
- package/skills/compact-context/src/SKILL.md +133 -0
- package/skills/compact-context/src/scripts/check.sh +381 -0
- package/skills/compact-context/src/scripts/set-keep-recent.mjs +1337 -0
- package/skills/compact-context/src/scripts/setup.sh +96 -0
- package/skills/feishu-notes-assistant-universal/skill.json +20 -0
- package/skills/feishu-notes-assistant-universal/src/README.md +55 -0
- package/skills/feishu-notes-assistant-universal/src/SKILL.md +159 -0
- package/skills/feishu-notes-assistant-universal/src/bin/linux-amd64/lark-cli-openclaw +0 -0
- package/skills/feishu-notes-assistant-universal/src/bin/linux-arm64/lark-cli-openclaw +0 -0
- package/skills/feishu-notes-assistant-universal/src/scripts/_resolve_lark_cli.py +58 -0
- package/skills/feishu-notes-assistant-universal/src/scripts/openclaw_meeting_minutes.py +462 -0
- package/skills/feishu-notes-assistant-universal/src/scripts/openclaw_notes_crud.py +547 -0
- package/skills/feishu-notes-assistant-universal/src/scripts/openclaw_notes_crud_test.py +181 -0
- package/skills/feishu-notes-assistant-universal/src/scripts/run_meeting_minutes.py +80 -0
- package/skills/feishu-notes-assistant-universal/src/scripts/run_meeting_minutes.sh +5 -0
- package/skills/feishu-notes-assistant-universal/src/scripts/run_note_crud.py +32 -0
- package/skills/feishu-notes-assistant-universal/src/scripts/run_note_crud.sh +5 -0
- package/skills/image-classify/skill.json +5 -5
- package/skills/image-classify/src/SKILL.md +60 -67
- package/skills/image-classify/src/scripts/face_search.py +400 -15
- package/skills/image-classify/src/scripts/send_dm_message.py +332 -0
- package/skills/md2pdf-converter/skill.json +20 -0
- package/skills/md2pdf-converter/src/SKILL.md +244 -0
- package/skills/md2pdf-converter/src/_meta.json +6 -0
- package/skills/md2pdf-converter/src/scripts/generate_emoji_mapping.py +74 -0
- package/skills/md2pdf-converter/src/scripts/md2pdf-local.sh +291 -0
- package/skills/sophnet-bot-client/skill.json +20 -0
- package/skills/sophnet-bot-client/src/SKILL.md +255 -0
- package/skills/sophnet-bot-client/src/pyproject.toml +13 -0
- package/skills/sophnet-bot-client/src/scripts/__init__.py +0 -0
- package/skills/sophnet-bot-client/src/scripts/bot_client_proxy.py +165 -0
- package/skills/sophnet-bot-client/src/scripts/bot_client_safe.sh +29 -0
- package/skills/sophnet-bot-client/src/scripts/bot_client_setup.py +502 -0
- package/skills/sophnet-bot-client/src/tests/__init__.py +0 -0
- package/skills/sophnet-bot-client/src/tests/test_bot_client_proxy.py +255 -0
- package/skills/sophnet-bot-client/src/tests/test_bot_client_setup.py +679 -0
- package/skills/sophnet-bot-client/src/uv.lock +8 -0
- package/skills/sophnet-docx/skill.json +20 -0
- package/skills/sophnet-docx/src/SKILL.md +463 -0
- package/skills/sophnet-docx/src/package-lock.json +208 -0
- package/skills/sophnet-docx/src/package.json +16 -0
- package/skills/sophnet-docx/src/pyproject.toml +11 -0
- package/skills/sophnet-docx/src/scripts/__init__.py +1 -0
- package/skills/sophnet-docx/src/scripts/accept_changes.py +135 -0
- package/skills/sophnet-docx/src/scripts/comment.py +318 -0
- package/skills/sophnet-docx/src/scripts/ensure_uv_env.sh +68 -0
- package/skills/sophnet-docx/src/scripts/office/helpers/__init__.py +0 -0
- package/skills/sophnet-docx/src/scripts/office/helpers/merge_runs.py +199 -0
- package/skills/sophnet-docx/src/scripts/office/helpers/simplify_redlines.py +197 -0
- package/skills/sophnet-docx/src/scripts/office/pack.py +159 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills/sophnet-docx/src/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills/sophnet-docx/src/scripts/office/soffice.py +183 -0
- package/skills/sophnet-docx/src/scripts/office/unpack.py +132 -0
- package/skills/sophnet-docx/src/scripts/office/validate.py +111 -0
- package/skills/sophnet-docx/src/scripts/office/validators/__init__.py +15 -0
- package/skills/sophnet-docx/src/scripts/office/validators/base.py +847 -0
- package/skills/sophnet-docx/src/scripts/office/validators/docx.py +446 -0
- package/skills/sophnet-docx/src/scripts/office/validators/pptx.py +275 -0
- package/skills/sophnet-docx/src/scripts/office/validators/redlining.py +247 -0
- package/skills/sophnet-docx/src/scripts/templates/comments.xml +3 -0
- package/skills/sophnet-docx/src/scripts/templates/commentsExtended.xml +3 -0
- package/skills/sophnet-docx/src/scripts/templates/commentsExtensible.xml +3 -0
- package/skills/sophnet-docx/src/scripts/templates/commentsIds.xml +3 -0
- package/skills/sophnet-docx/src/scripts/templates/people.xml +3 -0
- package/skills/sophnet-docx/src/scripts/upload_file.sh +96 -0
- package/skills/sophnet-docx/src/uv.lock +320 -0
- package/skills/sophnet-pdf/skill.json +20 -0
- package/skills/sophnet-pdf/src/SKILL.md +413 -0
- package/skills/sophnet-pdf/src/forms.md +297 -0
- package/skills/sophnet-pdf/src/pyproject.toml +14 -0
- package/skills/sophnet-pdf/src/reference.md +612 -0
- package/skills/sophnet-pdf/src/scripts/check_bounding_boxes.py +65 -0
- package/skills/sophnet-pdf/src/scripts/check_fillable_fields.py +11 -0
- package/skills/sophnet-pdf/src/scripts/convert_pdf_to_images.py +33 -0
- package/skills/sophnet-pdf/src/scripts/create_validation_image.py +37 -0
- package/skills/sophnet-pdf/src/scripts/enhance_tutorial.py +558 -0
- package/skills/sophnet-pdf/src/scripts/ensure_uv_env.sh +68 -0
- package/skills/sophnet-pdf/src/scripts/extract_form_field_info.py +122 -0
- package/skills/sophnet-pdf/src/scripts/extract_form_structure.py +115 -0
- package/skills/sophnet-pdf/src/scripts/extract_pdf_content.py +35 -0
- package/skills/sophnet-pdf/src/scripts/fill_fillable_fields.py +98 -0
- package/skills/sophnet-pdf/src/scripts/fill_pdf_form_with_annotations.py +107 -0
- package/skills/sophnet-pdf/src/scripts/upload_file.sh +88 -0
- package/skills/sophnet-pdf/src/uv.lock +537 -0
- package/skills/sophnet-xlsx/skill.json +20 -0
- package/skills/sophnet-xlsx/src/SKILL.md +399 -0
- package/skills/sophnet-xlsx/src/pyproject.toml +11 -0
- package/skills/sophnet-xlsx/src/scripts/ensure_uv_env.sh +68 -0
- package/skills/sophnet-xlsx/src/scripts/office/helpers/__init__.py +0 -0
- package/skills/sophnet-xlsx/src/scripts/office/helpers/merge_runs.py +199 -0
- package/skills/sophnet-xlsx/src/scripts/office/helpers/simplify_redlines.py +197 -0
- package/skills/sophnet-xlsx/src/scripts/office/pack.py +159 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/mce/mc.xsd +75 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/skills/sophnet-xlsx/src/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/skills/sophnet-xlsx/src/scripts/office/soffice.py +183 -0
- package/skills/sophnet-xlsx/src/scripts/office/unpack.py +132 -0
- package/skills/sophnet-xlsx/src/scripts/office/validate.py +111 -0
- package/skills/sophnet-xlsx/src/scripts/office/validators/__init__.py +15 -0
- package/skills/sophnet-xlsx/src/scripts/office/validators/base.py +847 -0
- package/skills/sophnet-xlsx/src/scripts/office/validators/docx.py +446 -0
- package/skills/sophnet-xlsx/src/scripts/office/validators/pptx.py +275 -0
- package/skills/sophnet-xlsx/src/scripts/office/validators/redlining.py +247 -0
- package/skills/sophnet-xlsx/src/scripts/recalc.py +184 -0
- package/skills/sophnet-xlsx/src/scripts/upload_file.sh +96 -0
- package/skills/sophnet-xlsx/src/uv.lock +319 -0
- package/skills/wechat-article-publisher/skill.json +20 -0
- package/skills/wechat-article-publisher/src/SKILL.md +60 -0
- package/skills/wechat-article-publisher/src/config.json +7 -0
- package/skills/wechat-article-publisher/src/pyproject.toml +12 -0
- package/skills/wechat-article-publisher/src/scripts/publish_wechat.py +825 -0
package/package.json
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "compact-context",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"types": [
|
|
5
|
+
"store"
|
|
6
|
+
],
|
|
7
|
+
"displayName": "局部上下文压缩",
|
|
8
|
+
"description": "在保留最近对话轮次的前提下压缩会话上下文,适用于局部 compact、释放上下文但不影响当前聊天连续性的场景。",
|
|
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,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: compact-context
|
|
3
|
+
description: Help the user compact their session while keeping recent conversation turns intact. Use when the user asks to compact, says "局部compact", wants to free up context, or says "压缩一下但别把最近的聊天压掉". When invoked, silently run the steps below and only show the user the friendly messages marked with >.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 局部压缩助手
|
|
7
|
+
|
|
8
|
+
**执行规则:所有操作静默完成,只把 > 引用块的内容说给用户。不提及脚本、命令、路径。必须严格绑定当前聊天线程;拿不到当前 session 时直接报错,不允许退化到“最近更新的会话”。**
|
|
9
|
+
|
|
10
|
+
本 SKILL.md 所在目录下有 `scripts/set-keep-recent.mjs`。用以下方式定位脚本(赋值给变量后使用,不展示给用户):
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
_S=$({
|
|
14
|
+
find . -maxdepth 8 -name "set-keep-recent.mjs" 2>/dev/null
|
|
15
|
+
find "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/skills" -maxdepth 4 -name "set-keep-recent.mjs" 2>/dev/null
|
|
16
|
+
find /home/node/.openclaw/skills -maxdepth 4 -name "set-keep-recent.mjs" 2>/dev/null
|
|
17
|
+
for _d in /home/node/.openclaw/*/skills; do find "$_d" -maxdepth 4 -name "set-keep-recent.mjs" 2>/dev/null; done
|
|
18
|
+
} | head -1)
|
|
19
|
+
[ -z "$_S" ] && echo "ERROR: set-keep-recent.mjs not found" && exit 1
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
静默拼出当前线程的 selector 参数(优先 key,其次 id):
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
_SESSION_ARGS=()
|
|
26
|
+
if [ -n "${OPENCLAW_TASK_SESSION_KEY:-}" ]; then
|
|
27
|
+
_SESSION_ARGS=(--session-key "$OPENCLAW_TASK_SESSION_KEY")
|
|
28
|
+
elif [ -n "${OPENCLAW_TASK_SESSION_ID:-}" ]; then
|
|
29
|
+
_SESSION_ARGS=(--session-id "$OPENCLAW_TASK_SESSION_ID")
|
|
30
|
+
else
|
|
31
|
+
echo "ERROR: current session selector missing" && exit 1
|
|
32
|
+
fi
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 步骤零:首次使用检测(每次调用时静默检查)
|
|
38
|
+
|
|
39
|
+
静默检查 `~/.agents/AGENTS.md` 是否包含 `## Session Startup`:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
grep -q "## Session Startup" "$HOME/.agents/AGENTS.md" 2>/dev/null
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**如果不存在**,先找到 `setup.sh` 并静默运行:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
_SH=$({
|
|
49
|
+
find . -maxdepth 8 -name "setup.sh" -path "*/compact-context/*" 2>/dev/null
|
|
50
|
+
find "${OPENCLAW_STATE_DIR:-$HOME/.openclaw}/skills" -maxdepth 5 -name "setup.sh" 2>/dev/null
|
|
51
|
+
find /home/node/.openclaw/skills -maxdepth 5 -name "setup.sh" 2>/dev/null
|
|
52
|
+
} | head -1)
|
|
53
|
+
[ -n "$_SH" ] && bash "$_SH" >/dev/null 2>&1
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
运行完后对用户说:
|
|
57
|
+
|
|
58
|
+
> 🛡️ 已自动开启压缩恢复保护(首次配置):压缩后会先补读任务上下文,再继续回复。
|
|
59
|
+
|
|
60
|
+
**如果已存在**,跳过此步骤,直接进入步骤一。
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 步骤一
|
|
65
|
+
|
|
66
|
+
静默执行 `node "$_S" --info --require-current-session "${_SESSION_ARGS[@]}"`,从输出解析 `turns=X used_pct=Y source=S`。
|
|
67
|
+
|
|
68
|
+
**如果 `source=native`**,对用户说:
|
|
69
|
+
|
|
70
|
+
> 📊 当前对话概况:
|
|
71
|
+
> - 总共聊了 **X 轮**
|
|
72
|
+
> - 占用了约 **Y%** 的上下文空间
|
|
73
|
+
>
|
|
74
|
+
> 你想尽量完整保留最近几轮?(比如"最近3轮"或"最近5轮")
|
|
75
|
+
> 底层会按 token 预算保留最近几轮,其余更早内容会压缩成摘要。
|
|
76
|
+
> 先说明一下:压缩后系统提示里的 token 数字,表示保留下来的**消息估算体积**;真实 prompt 通常会更高,并以下一次真实调用 usage 为准。
|
|
77
|
+
|
|
78
|
+
**如果 `source=assistant-usage` 或 `source=transcript-estimate`**,对用户说:
|
|
79
|
+
|
|
80
|
+
> 📊 当前对话概况(估算):
|
|
81
|
+
> - 当前可解析到约 **X 轮** 对话
|
|
82
|
+
> - 当前上下文占用约 **Y%**
|
|
83
|
+
>
|
|
84
|
+
> 暂时没拿到原生上下文统计,以上是按当前会话估算的结果。
|
|
85
|
+
> 先说明一下:压缩后系统提示里的 token 数字,表示保留下来的**消息估算体积**;真实 prompt 通常会更高,并以下一次真实调用 usage 为准。
|
|
86
|
+
> 你想尽量完整保留最近几轮?(比如"最近3轮"或"最近5轮")
|
|
87
|
+
> 底层会按 token 预算保留最近几轮,其余更早内容会压缩成摘要。
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 步骤二
|
|
92
|
+
|
|
93
|
+
用户说"最近 N 轮"后,静默执行 `node "$_S" --turns <N> --require-current-session "${_SESSION_ARGS[@]}"`。脚本内部会额外补偿当前交互带来的 2 轮占位,但这是内部实现细节;对用户展示时始终用用户请求的 N 轮。从输出解析 `display_keep_turns`、`display_compress_turns`、`source`,然后对用户说:
|
|
94
|
+
|
|
95
|
+
> ✅ 准备就绪!
|
|
96
|
+
>
|
|
97
|
+
> 压缩后的效果:
|
|
98
|
+
> - 🗜️ **前 {display_compress_turns} 轮** → 压缩成一段摘要(保留关键信息)
|
|
99
|
+
> - 📌 **最近 {display_keep_turns} 轮** → 尽量完整保留
|
|
100
|
+
> - 📏 这次保留部分的**消息估算体积**会按脚本计算;真实 prompt 大小会在下一次实际调用后更新
|
|
101
|
+
>
|
|
102
|
+
> 局部压缩模式已设置好,现在请发送 `/compact` 触发执行。
|
|
103
|
+
> 这次的 /compact 是**局部压缩**,不是全量——发出去就会按上面的方案执行。
|
|
104
|
+
> (如果有特别想保留的信息,可以在后面加说明,比如 `/compact 重点保留XXX任务的进展`)
|
|
105
|
+
|
|
106
|
+
如果当前 `source` 不是 `native`,再补一句:
|
|
107
|
+
|
|
108
|
+
> 这次保留范围是按当前会话估算的 token 预算计算出来的;显示的消息估算和后续 session/store 里的真实 prompt 数字不是同一口径,不能直接对比。
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 步骤三
|
|
113
|
+
|
|
114
|
+
用户收到 `⚙️ Compacted ...` 后,静默执行 `node "$_S" --restore --require-current-session "${_SESSION_ARGS[@]}"`,然后对用户说:
|
|
115
|
+
|
|
116
|
+
> (已压缩)
|
|
117
|
+
> - 前 {display_compress_turns} 轮对话已压缩为摘要
|
|
118
|
+
> - 最近 {display_keep_turns} 轮已按预算保留
|
|
119
|
+
> - 本次压缩后保留消息估算约为 **{message_estimate_after}**
|
|
120
|
+
> - 真实 prompt 大小会在下一次实际调用后更新,届时 session/store 数字才有参考意义
|
|
121
|
+
> - 上下文空间已释放,可以继续工作了 ✓
|
|
122
|
+
|
|
123
|
+
如果拿不到 `{message_estimate_after}`,改为:
|
|
124
|
+
|
|
125
|
+
> (已压缩)
|
|
126
|
+
> - 前 {display_compress_turns} 轮对话已压缩为摘要
|
|
127
|
+
> - 最近 {display_keep_turns} 轮已按预算保留
|
|
128
|
+
> - 系统刚显示的 token 数字表示保留下来的消息估算体积;真实 prompt 仍以下一次实际调用 usage 为准
|
|
129
|
+
> - 上下文空间已释放,可以继续工作了 ✓
|
|
130
|
+
|
|
131
|
+
如果 `--restore` 返回 session mismatch,改为对用户说:
|
|
132
|
+
|
|
133
|
+
> 当前线程和之前设置局部压缩时的线程对不上,我没有自动还原设置,避免误改到别的会话。
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Diagnose compact context state for the current workspace.
|
|
3
|
+
# Usage: bash check.sh [workspace_dir]
|
|
4
|
+
|
|
5
|
+
WORKSPACE="${1:-$(pwd)}"
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
SET_KEEP_SCRIPT="$SCRIPT_DIR/set-keep-recent.mjs"
|
|
8
|
+
SETTINGS_FILE="$WORKSPACE/.pi/settings.json"
|
|
9
|
+
AGENTS_MD="$WORKSPACE/AGENTS.md"
|
|
10
|
+
PERSONAL_AGENTS="$HOME/.agents/AGENTS.md"
|
|
11
|
+
OPENCLAW_CFG="${OPENCLAW_CONFIG_PATH:-$HOME/.openclaw/openclaw.json}"
|
|
12
|
+
STATE_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}"
|
|
13
|
+
BACKUP_KEY="__compactContextSkillBackup"
|
|
14
|
+
LAST_RUN_KEY="__compactContextSkillLastRun"
|
|
15
|
+
LAST_RESTORE_KEY="__compactContextSkillLastRestore"
|
|
16
|
+
|
|
17
|
+
RED='\033[0;31m'
|
|
18
|
+
GREEN='\033[0;32m'
|
|
19
|
+
YELLOW='\033[1;33m'
|
|
20
|
+
CYAN='\033[0;36m'
|
|
21
|
+
BOLD='\033[1m'
|
|
22
|
+
RESET='\033[0m'
|
|
23
|
+
|
|
24
|
+
echo ""
|
|
25
|
+
echo -e "${BOLD}━━━ Compact Context Diagnostics ━━━${RESET}"
|
|
26
|
+
echo ""
|
|
27
|
+
|
|
28
|
+
# ── 0. Current session selector ───────────────────────────────────────────────
|
|
29
|
+
echo -e "${BOLD}Current session selector:${RESET}"
|
|
30
|
+
if [ -n "${OPENCLAW_TASK_SESSION_KEY:-}" ]; then
|
|
31
|
+
echo " session_key=$OPENCLAW_TASK_SESSION_KEY"
|
|
32
|
+
elif [ -n "${OPENCLAW_TASK_SESSION_ID:-}" ]; then
|
|
33
|
+
echo " session_id=$OPENCLAW_TASK_SESSION_ID"
|
|
34
|
+
else
|
|
35
|
+
echo -e " ${YELLOW}○ No OPENCLAW_TASK_SESSION_KEY / OPENCLAW_TASK_SESSION_ID in this shell${RESET}"
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# ── 1. Compact history from agent session stores ──────────────────────────────
|
|
39
|
+
echo -e "${BOLD}Compact history:${RESET}"
|
|
40
|
+
if [ -d "$STATE_DIR/agents" ]; then
|
|
41
|
+
python3 - "$STATE_DIR" <<'PY'
|
|
42
|
+
import json
|
|
43
|
+
import os
|
|
44
|
+
import sys
|
|
45
|
+
|
|
46
|
+
state_dir = sys.argv[1]
|
|
47
|
+
total = 0
|
|
48
|
+
sessions = 0
|
|
49
|
+
stores = 0
|
|
50
|
+
|
|
51
|
+
agents_dir = os.path.join(state_dir, "agents")
|
|
52
|
+
for agent_id in os.listdir(agents_dir):
|
|
53
|
+
store = os.path.join(agents_dir, agent_id, "sessions", "sessions.json")
|
|
54
|
+
if not os.path.exists(store):
|
|
55
|
+
continue
|
|
56
|
+
stores += 1
|
|
57
|
+
try:
|
|
58
|
+
with open(store, "r", encoding="utf-8") as handle:
|
|
59
|
+
data = json.load(handle)
|
|
60
|
+
except Exception as exc:
|
|
61
|
+
print(f" unable to parse {store}: {exc}")
|
|
62
|
+
continue
|
|
63
|
+
for key, value in data.items():
|
|
64
|
+
if key in {"global", "unknown"} or not isinstance(value, dict):
|
|
65
|
+
continue
|
|
66
|
+
count = value.get("compactionCount", 0) or 0
|
|
67
|
+
total += count
|
|
68
|
+
if count > 0:
|
|
69
|
+
sessions += 1
|
|
70
|
+
|
|
71
|
+
print(f" stores={stores} total_compactions={total} sessions_with_compactions={sessions}")
|
|
72
|
+
PY
|
|
73
|
+
else
|
|
74
|
+
echo -e " ${YELLOW}○ No agent session stores found under${RESET} $STATE_DIR"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# ── 2. OpenClaw sessions CLI availability ─────────────────────────────────────
|
|
78
|
+
echo ""
|
|
79
|
+
echo -e "${BOLD}Native session CLI:${RESET}"
|
|
80
|
+
if command -v openclaw >/dev/null 2>&1; then
|
|
81
|
+
CLI_OUTPUT="$(openclaw sessions --json 2>&1 || true)"
|
|
82
|
+
CLI_STATUS=$(CLI_OUTPUT="$CLI_OUTPUT" python3 - <<'PY'
|
|
83
|
+
import json
|
|
84
|
+
import os
|
|
85
|
+
|
|
86
|
+
text = os.environ.get("CLI_OUTPUT", "")
|
|
87
|
+
payload = None
|
|
88
|
+
for start, start_char in enumerate(text):
|
|
89
|
+
if start_char not in "{[":
|
|
90
|
+
continue
|
|
91
|
+
stack = []
|
|
92
|
+
in_string = False
|
|
93
|
+
escaped = False
|
|
94
|
+
json_text = None
|
|
95
|
+
for index in range(start, len(text)):
|
|
96
|
+
char = text[index]
|
|
97
|
+
if in_string:
|
|
98
|
+
if escaped:
|
|
99
|
+
escaped = False
|
|
100
|
+
elif char == "\\":
|
|
101
|
+
escaped = True
|
|
102
|
+
elif char == '"':
|
|
103
|
+
in_string = False
|
|
104
|
+
continue
|
|
105
|
+
if char == '"':
|
|
106
|
+
in_string = True
|
|
107
|
+
continue
|
|
108
|
+
if char in "{[":
|
|
109
|
+
stack.append("}" if char == "{" else "]")
|
|
110
|
+
continue
|
|
111
|
+
if char in "}]":
|
|
112
|
+
if not stack or stack.pop() != char:
|
|
113
|
+
json_text = None
|
|
114
|
+
break
|
|
115
|
+
if not stack:
|
|
116
|
+
json_text = text[start:index + 1]
|
|
117
|
+
break
|
|
118
|
+
if json_text is None:
|
|
119
|
+
continue
|
|
120
|
+
try:
|
|
121
|
+
candidate = json.loads(json_text)
|
|
122
|
+
except Exception:
|
|
123
|
+
continue
|
|
124
|
+
if isinstance(candidate, dict) and ("sessions" in candidate or "path" in candidate):
|
|
125
|
+
payload = candidate
|
|
126
|
+
break
|
|
127
|
+
|
|
128
|
+
if payload is None:
|
|
129
|
+
print("unavailable")
|
|
130
|
+
raise SystemExit(0)
|
|
131
|
+
|
|
132
|
+
sessions = payload.get("sessions") or []
|
|
133
|
+
path = payload.get("path") or "unknown"
|
|
134
|
+
print(f"available path={path} sessions={len(sessions)}")
|
|
135
|
+
PY
|
|
136
|
+
)
|
|
137
|
+
if [[ "$CLI_STATUS" == available* ]]; then
|
|
138
|
+
echo -e " ${GREEN}✔${RESET} $CLI_STATUS"
|
|
139
|
+
else
|
|
140
|
+
echo -e " ${RED}✘${RESET} openclaw sessions --json unavailable"
|
|
141
|
+
fi
|
|
142
|
+
else
|
|
143
|
+
echo -e " ${RED}✘${RESET} openclaw command not found"
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
# ── 3. Session alignment / token accounting ───────────────────────────────────
|
|
147
|
+
echo ""
|
|
148
|
+
echo -e "${BOLD}Current session alignment:${RESET}"
|
|
149
|
+
if [ -f "$SET_KEEP_SCRIPT" ]; then
|
|
150
|
+
INFO_OUTPUT="$(node "$SET_KEEP_SCRIPT" --info --workspace "$WORKSPACE" --allow-latest-updated --debug 2>&1 || true)"
|
|
151
|
+
if [[ -n "$INFO_OUTPUT" ]]; then
|
|
152
|
+
INFO_REPORT=$(INFO_OUTPUT="$INFO_OUTPUT" python3 - <<'PY'
|
|
153
|
+
import os
|
|
154
|
+
import re
|
|
155
|
+
|
|
156
|
+
text = os.environ.get("INFO_OUTPUT", "")
|
|
157
|
+
pairs = dict(re.findall(r'([A-Za-z_]+)=([^\s]+)', text))
|
|
158
|
+
|
|
159
|
+
def num(name):
|
|
160
|
+
value = pairs.get(name)
|
|
161
|
+
if value in (None, "unknown", "none"):
|
|
162
|
+
return None
|
|
163
|
+
try:
|
|
164
|
+
return float(value)
|
|
165
|
+
except ValueError:
|
|
166
|
+
return None
|
|
167
|
+
|
|
168
|
+
native = num("native_total_tokens")
|
|
169
|
+
estimate = num("transcript_total_estimate")
|
|
170
|
+
bias = None
|
|
171
|
+
ratio = None
|
|
172
|
+
if native is not None and estimate is not None and native != 0:
|
|
173
|
+
bias = estimate - native
|
|
174
|
+
ratio = estimate / native
|
|
175
|
+
|
|
176
|
+
lines = [
|
|
177
|
+
f"source={pairs.get('source', 'unknown')}",
|
|
178
|
+
f"estimation_mode={pairs.get('estimation_mode', 'unknown')}",
|
|
179
|
+
f"source_label={pairs.get('source_label', 'unknown')}",
|
|
180
|
+
f"display_label={pairs.get('display_label', 'unknown')}",
|
|
181
|
+
f"prompt_truth_source={pairs.get('prompt_truth_source', 'unknown')}",
|
|
182
|
+
f"resolved_by={pairs.get('resolved_by', 'unknown')}",
|
|
183
|
+
f"session_key={pairs.get('resolved_session_key', 'unknown')}",
|
|
184
|
+
f"session_id={pairs.get('resolved_session_id', 'unknown')}",
|
|
185
|
+
f"session_file={pairs.get('resolved_session_file', 'unknown')}",
|
|
186
|
+
f"turns={pairs.get('turns', 'unknown')}",
|
|
187
|
+
f"total_tokens={pairs.get('total_tokens', 'unknown')}",
|
|
188
|
+
f"message_estimate_before={pairs.get('message_estimate_before', 'unknown')}",
|
|
189
|
+
f"message_estimate_after={pairs.get('message_estimate_after', 'unknown')}",
|
|
190
|
+
f"context_tokens={pairs.get('context_tokens', 'unknown')}",
|
|
191
|
+
f"used_pct={pairs.get('used_pct', 'unknown')}",
|
|
192
|
+
f"snapshot_status={pairs.get('snapshot_status', 'unknown')}",
|
|
193
|
+
f"native_total_tokens={pairs.get('native_total_tokens', 'unknown')}",
|
|
194
|
+
f"transcript_total_estimate={pairs.get('transcript_total_estimate', 'unknown')}",
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
if bias is not None and ratio is not None:
|
|
198
|
+
lines.append(f"estimate_bias={bias:.0f}")
|
|
199
|
+
lines.append(f"estimate_ratio={ratio:.3f}")
|
|
200
|
+
|
|
201
|
+
print("\n".join(lines))
|
|
202
|
+
PY
|
|
203
|
+
)
|
|
204
|
+
while IFS= read -r line; do
|
|
205
|
+
[ -n "$line" ] && echo " $line"
|
|
206
|
+
done <<< "$INFO_REPORT"
|
|
207
|
+
else
|
|
208
|
+
echo -e " ${RED}✘${RESET} set-keep-recent --info produced no output"
|
|
209
|
+
fi
|
|
210
|
+
else
|
|
211
|
+
echo -e " ${RED}✘${RESET} set-keep-recent.mjs not found"
|
|
212
|
+
fi
|
|
213
|
+
|
|
214
|
+
# ── 4. Backup / workspace settings ────────────────────────────────────────────
|
|
215
|
+
echo ""
|
|
216
|
+
echo -e "${BOLD}Workspace settings:${RESET} $SETTINGS_FILE"
|
|
217
|
+
if [ -f "$SETTINGS_FILE" ]; then
|
|
218
|
+
python3 - "$SETTINGS_FILE" <<'PY'
|
|
219
|
+
import json
|
|
220
|
+
import sys
|
|
221
|
+
|
|
222
|
+
settings_file = sys.argv[1]
|
|
223
|
+
with open(settings_file, "r", encoding="utf-8") as handle:
|
|
224
|
+
data = json.load(handle)
|
|
225
|
+
|
|
226
|
+
compaction = data.get("compaction") or {}
|
|
227
|
+
keep_recent = compaction.get("keepRecentTokens", "not set")
|
|
228
|
+
backup = compaction.get("__compactContextSkillBackup")
|
|
229
|
+
last_run = compaction.get("__compactContextSkillLastRun")
|
|
230
|
+
last_restore = compaction.get("__compactContextSkillLastRestore")
|
|
231
|
+
|
|
232
|
+
print(f" keepRecentTokens={keep_recent}")
|
|
233
|
+
if isinstance(backup, dict):
|
|
234
|
+
print(" backup=present")
|
|
235
|
+
print(f" backup.sessionKey={backup.get('sessionKey', 'unknown')}")
|
|
236
|
+
print(f" backup.sessionId={backup.get('sessionId', 'unknown')}")
|
|
237
|
+
print(f" backup.source={backup.get('source', 'unknown')}")
|
|
238
|
+
print(f" backup.appliedKeepRecentTokens={backup.get('appliedKeepRecentTokens', 'unknown')}")
|
|
239
|
+
else:
|
|
240
|
+
print(" backup=absent")
|
|
241
|
+
|
|
242
|
+
if isinstance(last_run, dict):
|
|
243
|
+
print(" last_run=present")
|
|
244
|
+
print(f" last_run.source={last_run.get('source', 'unknown')}")
|
|
245
|
+
print(f" last_run.sessionKey={last_run.get('sessionKey', 'unknown')}")
|
|
246
|
+
print(f" last_run.totalTokensBefore={last_run.get('totalTokensBefore', 'unknown')}")
|
|
247
|
+
print(f" last_run.usedPctBefore={last_run.get('usedPctBefore', 'unknown')}")
|
|
248
|
+
print(f" last_run.keepRecentTokens={last_run.get('keepRecentTokens', 'unknown')}")
|
|
249
|
+
print(f" last_run.messageEstimateBefore={last_run.get('messageEstimateBefore', 'unknown')}")
|
|
250
|
+
print(f" last_run.messageEstimateAfter={last_run.get('messageEstimateAfter', 'unknown')}")
|
|
251
|
+
print(f" last_run.promptTruthSource={last_run.get('promptTruthSource', 'unknown')}")
|
|
252
|
+
else:
|
|
253
|
+
print(" last_run=absent")
|
|
254
|
+
|
|
255
|
+
if isinstance(last_restore, dict):
|
|
256
|
+
print(" last_restore=present")
|
|
257
|
+
print(f" last_restore.restoreStatus={last_restore.get('restoreStatus', 'unknown')}")
|
|
258
|
+
print(f" last_restore.restoredKeepRecentTokens={last_restore.get('restoredKeepRecentTokens', 'unknown')}")
|
|
259
|
+
else:
|
|
260
|
+
print(" last_restore=absent")
|
|
261
|
+
PY
|
|
262
|
+
else
|
|
263
|
+
echo -e " ${YELLOW}○ settings.json not found${RESET}"
|
|
264
|
+
fi
|
|
265
|
+
|
|
266
|
+
# ── 5. Workspace / personal AGENTS.md ─────────────────────────────────────────
|
|
267
|
+
echo ""
|
|
268
|
+
echo -e "${BOLD}Workspace AGENTS.md:${RESET} $AGENTS_MD"
|
|
269
|
+
if [ -f "$AGENTS_MD" ]; then
|
|
270
|
+
if grep -q "## Session Startup" "$AGENTS_MD" 2>/dev/null; then
|
|
271
|
+
if grep -q "Start your reply with:" "$AGENTS_MD" 2>/dev/null || grep -q "(已压缩,从摘要恢复)" "$AGENTS_MD" 2>/dev/null; then
|
|
272
|
+
echo -e " ${YELLOW}○ ## Session Startup${RESET} — legacy (fixed-prefix rule detected)"
|
|
273
|
+
else
|
|
274
|
+
echo -e " ${GREEN}✔ ## Session Startup${RESET} — safe"
|
|
275
|
+
fi
|
|
276
|
+
else
|
|
277
|
+
echo -e " ${RED}✘ ## Session Startup${RESET} — missing"
|
|
278
|
+
fi
|
|
279
|
+
else
|
|
280
|
+
echo -e " ${YELLOW}○ AGENTS.md not found in workspace${RESET}"
|
|
281
|
+
fi
|
|
282
|
+
|
|
283
|
+
echo ""
|
|
284
|
+
echo -e "${BOLD}Personal AGENTS.md:${RESET} $PERSONAL_AGENTS"
|
|
285
|
+
if [ -f "$PERSONAL_AGENTS" ]; then
|
|
286
|
+
if grep -q "## Session Startup" "$PERSONAL_AGENTS" 2>/dev/null; then
|
|
287
|
+
if grep -q "Start your reply with:" "$PERSONAL_AGENTS" 2>/dev/null || grep -q "(已压缩,从摘要恢复)" "$PERSONAL_AGENTS" 2>/dev/null; then
|
|
288
|
+
echo -e " ${YELLOW}○ ## Session Startup${RESET} — legacy (fixed-prefix rule detected)"
|
|
289
|
+
else
|
|
290
|
+
echo -e " ${GREEN}✔ ## Session Startup${RESET} — safe"
|
|
291
|
+
fi
|
|
292
|
+
else
|
|
293
|
+
echo -e " ${RED}✘ ## Session Startup${RESET} — missing"
|
|
294
|
+
fi
|
|
295
|
+
else
|
|
296
|
+
echo -e " ${YELLOW}○ personal AGENTS.md not found${RESET}"
|
|
297
|
+
fi
|
|
298
|
+
|
|
299
|
+
# ── 6. memoryFlush config ─────────────────────────────────────────────────────
|
|
300
|
+
echo ""
|
|
301
|
+
echo -e "${BOLD}memoryFlush config:${RESET}"
|
|
302
|
+
if [ -f "$OPENCLAW_CFG" ]; then
|
|
303
|
+
python3 - "$OPENCLAW_CFG" <<'PY'
|
|
304
|
+
import json
|
|
305
|
+
import sys
|
|
306
|
+
|
|
307
|
+
cfg_path = sys.argv[1]
|
|
308
|
+
with open(cfg_path, "r", encoding="utf-8") as handle:
|
|
309
|
+
cfg = json.load(handle)
|
|
310
|
+
|
|
311
|
+
memory_flush = cfg.get("agents", {}).get("defaults", {}).get("compaction", {}).get("memoryFlush", {})
|
|
312
|
+
if memory_flush:
|
|
313
|
+
print(f" enabled={memory_flush.get('enabled', True)} softThresholdTokens={memory_flush.get('softThresholdTokens', 'not set')}")
|
|
314
|
+
else:
|
|
315
|
+
print(" not configured")
|
|
316
|
+
PY
|
|
317
|
+
else
|
|
318
|
+
echo -e " ${YELLOW}○ openclaw.json not found${RESET}"
|
|
319
|
+
fi
|
|
320
|
+
|
|
321
|
+
# ── 7. Summary ────────────────────────────────────────────────────────────────
|
|
322
|
+
echo ""
|
|
323
|
+
echo -e "${BOLD}━━━ Summary ━━━${RESET}"
|
|
324
|
+
|
|
325
|
+
ISSUES=0
|
|
326
|
+
|
|
327
|
+
if ! command -v openclaw >/dev/null 2>&1; then
|
|
328
|
+
echo -e "${RED}✘ Native OpenClaw CLI unavailable.${RESET}"
|
|
329
|
+
ISSUES=$((ISSUES + 1))
|
|
330
|
+
fi
|
|
331
|
+
|
|
332
|
+
if [ -z "${OPENCLAW_TASK_SESSION_KEY:-}" ] && [ -z "${OPENCLAW_TASK_SESSION_ID:-}" ]; then
|
|
333
|
+
echo -e "${YELLOW}○ Current shell is missing a bound session selector.${RESET}"
|
|
334
|
+
echo -e " ${YELLOW}→ Strict skill mode will refuse to run here until the live thread exports it.${RESET}"
|
|
335
|
+
ISSUES=$((ISSUES + 1))
|
|
336
|
+
fi
|
|
337
|
+
|
|
338
|
+
if [ -f "$SETTINGS_FILE" ] && grep -q "\"$BACKUP_KEY\"" "$SETTINGS_FILE" 2>/dev/null; then
|
|
339
|
+
echo -e "${CYAN}○${RESET} Workspace currently contains a compact-context backup entry."
|
|
340
|
+
fi
|
|
341
|
+
|
|
342
|
+
if [ -f "$SETTINGS_FILE" ] && grep -q "\"$LAST_RUN_KEY\"" "$SETTINGS_FILE" 2>/dev/null; then
|
|
343
|
+
echo -e "${CYAN}○${RESET} Workspace contains a last-run snapshot for compaction diagnostics."
|
|
344
|
+
fi
|
|
345
|
+
|
|
346
|
+
if [ -f "$AGENTS_MD" ] && grep -q "## Session Startup" "$AGENTS_MD" 2>/dev/null; then
|
|
347
|
+
STARTUP_OK=1
|
|
348
|
+
else
|
|
349
|
+
STARTUP_OK=0
|
|
350
|
+
fi
|
|
351
|
+
|
|
352
|
+
if [ -f "$PERSONAL_AGENTS" ] && grep -q "## Session Startup" "$PERSONAL_AGENTS" 2>/dev/null; then
|
|
353
|
+
PERSONAL_OK=1
|
|
354
|
+
else
|
|
355
|
+
PERSONAL_OK=0
|
|
356
|
+
fi
|
|
357
|
+
|
|
358
|
+
if ([ -f "$AGENTS_MD" ] && (grep -q "Start your reply with:" "$AGENTS_MD" 2>/dev/null || grep -q "(已压缩,从摘要恢复)" "$AGENTS_MD" 2>/dev/null)) \
|
|
359
|
+
|| ([ -f "$PERSONAL_AGENTS" ] && (grep -q "Start your reply with:" "$PERSONAL_AGENTS" 2>/dev/null || grep -q "(已压缩,从摘要恢复)" "$PERSONAL_AGENTS" 2>/dev/null)); then
|
|
360
|
+
echo -e "${YELLOW}○ Legacy startup rules detected.${RESET}"
|
|
361
|
+
echo -e " ${YELLOW}→ Run: bash setup.sh${RESET}"
|
|
362
|
+
fi
|
|
363
|
+
|
|
364
|
+
if [ "$STARTUP_OK" -gt 0 ] || [ "$PERSONAL_OK" -gt 0 ]; then
|
|
365
|
+
echo -e "${GREEN}✔ Post-compaction re-injection is set up.${RESET}"
|
|
366
|
+
else
|
|
367
|
+
echo -e "${RED}✘ Post-compaction re-injection is NOT set up.${RESET}"
|
|
368
|
+
echo -e " ${YELLOW}→ Run: bash setup.sh${RESET}"
|
|
369
|
+
ISSUES=$((ISSUES + 1))
|
|
370
|
+
fi
|
|
371
|
+
|
|
372
|
+
echo -e "${CYAN}○${RESET} Token accounting note: skill messageEstimate* / keepRecentTokens are display-side compaction estimates;"
|
|
373
|
+
echo -e " ${CYAN}sessions.json totalTokens${RESET} reflects runtime prompt/cache usage and should be treated as authoritative only after the next real model call."
|
|
374
|
+
|
|
375
|
+
if printf '%s' "$INFO_OUTPUT" | grep -q "source=transcript-estimate" 2>/dev/null; then
|
|
376
|
+
echo -e "${YELLOW}○ Current token accounting is using transcript-estimate fallback.${RESET}"
|
|
377
|
+
fi
|
|
378
|
+
|
|
379
|
+
echo ""
|
|
380
|
+
[ "$ISSUES" -eq 0 ] && echo -e "${GREEN}All checks passed.${RESET}" || echo -e "${YELLOW}$ISSUES issue(s) found — see above.${RESET}"
|
|
381
|
+
echo ""
|