diff --git a/AGENTS.md b/AGENTS.md
index 8f58748..8de77e3 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -72,7 +72,7 @@ git push origin develop
2. Docs → Excel:将 Markdown 文档目录还原为 Excel 工作簿
3. Docs → JSONL:将 Markdown 文档转换为 JSONL 格式
4. JSONL → Excel:将 JSONL 转换为 Excel
-5. Excel(JSONL) → JSONL:将内部 JSONL 格式的 Excel 转换为 JSONL 文件
+5. Excel(JSONL) → JSONL:将内部 JSONL 格式的 Excel 转换为 JSONL 目录(每个工作表一个 JSONL 文件)
---
diff --git a/README.md b/README.md
index 79799a4..d153038 100644
--- a/README.md
+++ b/README.md
@@ -335,7 +335,7 @@ Canvas方式:**代码 ⇄ 白板 ⇄ AI ⇄ 人类**,白板成为单一真
* [**胶水编程 (Glue Coding)**](./assets/documents/principles/fundamentals/): 软件工程的圣杯与银弹,Vibe Coding 的终极进化形态。
* [**Chat Vault**](./assets/repo/chat-vault/): AI 聊天记录保存工具,支持 Codex/Kiro/Gemini/Claude CLI。
-* [**prompts-library 工具说明**](./assets/repo/prompts-library/): 支持 Excel 与 Markdown 格式互转,包含数百个精选提示词。
+* [**prompts-library 工具说明**](./assets/repo/prompts-library/): 支持 Excel 与 Markdown 格式互转,并支持将内部 JSONL Excel 按工作表拆分导出为 JSONL 目录。
* [**编程提示词集合**](https://docs.google.com/spreadsheets/d/1Ifk_dLF25ULSxcfGem1hXzJsi7_RBUNAki8SBCuvkJA/edit?gid=1254297203#gid=1254297203): 适用于 Vibe Coding 流程的专用提示词(云端表格)。
* [**系统提示词构建原则**](./assets/documents/principles/fundamentals/系统提示词构建原则.md): 构建高效 AI 系统提示词的综合指南。
* [**开发经验总结**](./assets/documents/principles/fundamentals/开发经验.md): 变量命名、文件结构、编码规范、架构原则等。
@@ -411,7 +411,7 @@ Canvas方式:**代码 ⇄ 白板 ⇄ AI ⇄ 人类**,白板成为单一真
│ │ └── canvas-dev/ # Canvas白板驱动开发
│ └── repo/ # 外部工具与依赖镜像(含 Git submodule)
│ ├── README.md # 外部工具索引
-│ ├── prompts-library/ # Excel ↔ Markdown 互转工具
+│ ├── prompts-library/ # Excel ↔ Markdown 互转工具,含内部 JSONL Excel 拆分导出
│ ├── chat-vault/ # AI 聊天记录保存工具
│ ├── Skill_Seekers-development/ # Skills 制作器
│ ├── html-tools-main/ # HTML 工具集
diff --git a/assets/repo/prompts-library/README.md b/assets/repo/prompts-library/README.md
index d6fc5d5..755898b 100644
--- a/assets/repo/prompts-library/README.md
+++ b/assets/repo/prompts-library/README.md
@@ -171,6 +171,21 @@ python3 scripts/gemini_jsonl_batch.py --input 2 --output 2/prompts.jsonl --model
- 可用 `-v` 查看逐文件处理日志,`--gemini-cmd` 自定义 CLI 可执行路径。
+
+内部 JSONL Excel → JSONL 目录
+
+```bash
+# 将内部 JSONL 格式的 xlsx 按工作表拆分为多个 jsonl 文件
+python3 main.py --select "prompt_excel/prompt_jsonl.xlsx" --mode jsonl_excel2jsonl
+```
+
+- 输出目录格式为 `prompt_jsonl/_/`
+- 每个工作表输出一个独立的 `.jsonl` 文件
+- 文件名格式为 `<序号>_.jsonl`
+- 若工作表中没有标准 JSON 单元格,会对纯文本单元格做 JSONL 兜底转换
+- 自动忽略名为 `说明` 的工作表
+
+
---
diff --git a/assets/repo/prompts-library/main.py b/assets/repo/prompts-library/main.py
index 5f0db1f..38a6ef2 100644
--- a/assets/repo/prompts-library/main.py
+++ b/assets/repo/prompts-library/main.py
@@ -11,7 +11,7 @@ Unified controller for prompt-library conversions.
2. Docs → Excel : 将 Markdown 文档目录还原为 Excel 工作簿
3. Docs → JSONL : 将 Markdown 文档转换为 JSONL 格式(保留完整元信息)
4. JSONL → Excel : 将 JSONL 转换为 Excel(单元格存储 JSON 对象)
-5. Excel(JSONL) → JSONL : 将内部 JSONL 格式的 Excel 转换为 JSONL 文件(自动忽略"说明"工作表)
+5. Excel(JSONL) → JSONL : 将内部 JSONL 格式的 Excel 转换为 JSONL 目录(自动忽略"说明"工作表)
数据格式规范
============
@@ -51,7 +51,7 @@ JSONL → Excel 单元格格式:
- Docs→Excel: ./prompt_excel/prompt_excel_YYYY_MMDD_HHMMSS/rebuilt.xlsx
- Docs→JSONL: ./prompt_jsonl/{docs_name}.jsonl
- JSONL→Excel: ./prompt_excel/{jsonl_name}.xlsx
- - Excel(JSONL)→JSONL: ./prompt_jsonl/{excel_name}.jsonl
+ - Excel(JSONL)→JSONL: ./prompt_jsonl/{excel_name}_{timestamp}/.jsonl
使用示例
========
@@ -253,9 +253,31 @@ def is_jsonl_excel(excel_path: Path) -> bool:
return False
+def sanitize_filename(name: str) -> str:
+ """将工作表名转换为稳定的文件名片段。"""
+ invalid_chars = '<>:"/\\|?*'
+ sanitized = "".join("_" if ch in invalid_chars else ch for ch in name).strip()
+ return sanitized.rstrip(". ") or "sheet"
+
+
+def build_text_record(cat_id: int, cat_name: str, row: int, col: int, text: str) -> dict:
+ """将纯文本单元格兜底转换为 JSONL 记录。"""
+ lines = [line.strip() for line in text.splitlines() if line.strip()]
+ title = lines[0] if lines else text.strip()
+ return {
+ "category_id": cat_id,
+ "category": cat_name,
+ "row": row,
+ "col": col,
+ "title": title[:80],
+ "content": text,
+ }
+
+
def run_jsonl_excel_to_jsonl(excel_path: Path, project_root: Path) -> int:
- """将内部 JSONL 格式的 Excel 转换为 JSONL 文件(忽略"说明"工作表)"""
+ """将内部 JSONL 格式的 Excel 转换为 JSONL 目录(忽略"说明"工作表)"""
import json
+ from datetime import datetime
try:
import pandas as pd
except ImportError:
@@ -263,16 +285,23 @@ def run_jsonl_excel_to_jsonl(excel_path: Path, project_root: Path) -> int:
return 1
xlsx = pd.ExcelFile(excel_path)
- output_lines = []
cat_id = 0
+ total_records = 0
+ written_files = []
- for sheet in xlsx.sheet_names:
+ timestamp = datetime.now().strftime("%Y_%m%d_%H%M%S")
+ output_dir = project_root / "prompt_jsonl" / f"{excel_path.stem}_{timestamp}"
+ output_dir.mkdir(parents=True, exist_ok=True)
+
+ for sheet_index, sheet in enumerate(xlsx.sheet_names, start=1):
if sheet == '说明':
continue
cat_id += 1
cat_name = sheet
df = pd.read_excel(xlsx, sheet_name=sheet, header=None)
+ sheet_lines = []
+ fallback_records = []
# 检查列名是否是 JSON 数据
for col_idx, col_name in enumerate(df.columns):
@@ -281,7 +310,7 @@ def run_jsonl_excel_to_jsonl(excel_path: Path, project_root: Path) -> int:
try:
obj = json.loads(col_str)
if 'title' in obj and 'content' in obj:
- output_lines.append(json.dumps({
+ sheet_lines.append(json.dumps({
"category_id": cat_id,
"category": cat_name,
"row": 1,
@@ -298,11 +327,13 @@ def run_jsonl_excel_to_jsonl(excel_path: Path, project_root: Path) -> int:
if pd.isna(val):
continue
val_str = str(val).strip()
+ if not val_str:
+ continue
if val_str.startswith('{') and val_str.endswith('}'):
try:
obj = json.loads(val_str)
if 'title' in obj and 'content' in obj:
- output_lines.append(json.dumps({
+ sheet_lines.append(json.dumps({
"category_id": cat_id,
"category": cat_name,
"row": row_idx + 2,
@@ -312,22 +343,43 @@ def run_jsonl_excel_to_jsonl(excel_path: Path, project_root: Path) -> int:
}, ensure_ascii=False))
except:
pass
-
- if not output_lines:
+ else:
+ # 跳过常见的顶栏广告/元数据噪声,但保留其他纯文本内容作为兜底记录。
+ if row_idx == 0 and col_idx == 0 and val_str.startswith("广告位"):
+ continue
+ fallback_records.append(
+ build_text_record(
+ cat_id=cat_id,
+ cat_name=cat_name,
+ row=row_idx + 2,
+ col=col_idx + 1,
+ text=val_str,
+ )
+ )
+
+ if not sheet_lines and fallback_records:
+ sheet_lines = [
+ json.dumps(record, ensure_ascii=False)
+ for record in fallback_records
+ ]
+
+ total_records += len(sheet_lines)
+ file_stem = sanitize_filename(cat_name)
+ output_file = output_dir / f"{sheet_index:02d}_{file_stem}.jsonl"
+ with open(output_file, 'w', encoding='utf-8') as f:
+ if sheet_lines:
+ f.write('\n'.join(sheet_lines) + '\n')
+ written_files.append(output_file)
+
+ if not written_files:
print(f"❌ 未找到有效的 JSONL 数据: {excel_path}")
return 1
-
- from datetime import datetime
- timestamp = datetime.now().strftime("%Y_%m%d_%H%M%S")
-
- output_dir = project_root / "prompt_jsonl"
- output_dir.mkdir(parents=True, exist_ok=True)
- output_file = output_dir / f"{excel_path.stem}_{timestamp}.jsonl"
-
- with open(output_file, 'w', encoding='utf-8') as f:
- f.write('\n'.join(output_lines))
-
- print(f"✅ Excel(JSONL)→JSONL OK: {excel_path.name} → {output_file.relative_to(project_root)} ({len(output_lines)} 条记录)")
+
+ print(
+ f"✅ Excel(JSONL)→JSONL OK: {excel_path.name} → "
+ f"{output_dir.relative_to(project_root)} "
+ f"({len(written_files)} 个文件 / {total_records} 条记录)"
+ )
return 0