jfox-cli 0.7.2__tar.gz → 0.8.0__tar.gz

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 (171) hide show
  1. jfox_cli-0.8.0/.claude-plugin/marketplace.json +20 -0
  2. jfox_cli-0.8.0/.claude-plugin/plugin.json +22 -0
  3. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/AGENTS.md +111 -34
  4. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/CHANGELOG.md +11 -0
  5. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/PKG-INFO +1 -1
  6. jfox_cli-0.8.0/commands/jfox-common.md +6 -0
  7. jfox_cli-0.8.0/commands/jfox-ingest.md +6 -0
  8. jfox_cli-0.8.0/commands/jfox-organize.md +6 -0
  9. jfox_cli-0.8.0/commands/jfox-search.md +6 -0
  10. jfox_cli-0.8.0/commands/jfox-session-summary.md +6 -0
  11. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/__init__.py +1 -1
  12. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/cli.py +44 -16
  13. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/config.py +1 -0
  14. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/kb_manager.py +2 -2
  15. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/models.py +10 -1
  16. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/note.py +2 -0
  17. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/template.py +21 -0
  18. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/template_cli.py +1 -1
  19. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/pyproject.toml +1 -1
  20. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/skills-recommend/claude-code/jfox-session-summary/SKILL.md +8 -5
  21. jfox_cli-0.8.0/skills-recommend/kimi-cli/jfox-session-summary/SKILL.md +122 -0
  22. jfox_cli-0.8.0/tests/unit/test_session_note.py +231 -0
  23. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/uv.lock +1 -1
  24. jfox_cli-0.7.2/skills-recommend/kimi-cli/jfox-session-summary/SKILL.md +0 -122
  25. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/.claude/settings.local.json +0 -0
  26. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/.claude/skills/ci/SKILL.md +0 -0
  27. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/.claude/skills/release/SKILL.md +0 -0
  28. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/.claude/skills/release/release_helper.py +0 -0
  29. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/.githooks/pre-push +0 -0
  30. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/.github/workflows/integration-test.yml +0 -0
  31. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/.github/workflows/publish.yml +0 -0
  32. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/.gitignore +0 -0
  33. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/.python-version +0 -0
  34. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/CLAUDE.md +0 -0
  35. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/DEVELOPMENT_PLAN.md +0 -0
  36. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/README.md +0 -0
  37. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/SESSION.md +0 -0
  38. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/SESSION_SUMMARY.md +0 -0
  39. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/installation.md +0 -0
  40. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-11-bulk-import-bm25-fix.md +0 -0
  41. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-11-edit-command.md +0 -0
  42. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-11-unify-format-option.md +0 -0
  43. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-12-ci-coverage-optimization.md +0 -0
  44. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-12-edit-content-file.md +0 -0
  45. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-12-fix-index-rebuild-clear.md +0 -0
  46. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-12-fix-index-verify-id-mismatch.md +0 -0
  47. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-12-fix-jfox-health-skill-kb-param.md +0 -0
  48. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-12-index-kb-param.md +0 -0
  49. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-12-lazy-import-perf.md +0 -0
  50. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-12-skill-redesign.md +0 -0
  51. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-13-add-content-file.md +0 -0
  52. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-13-bulk-import-vectorstore-init.md +0 -0
  53. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-13-ingest-log-command.md +0 -0
  54. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-13-ingest-skill-sync.md +0 -0
  55. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-13-suppress-third-party-logging.md +0 -0
  56. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-13-sync-skills-with-cli.md +0 -0
  57. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-14-sync-docs-daemon-show.md +0 -0
  58. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-15-gpu-embedding.md +0 -0
  59. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-15-make-daemon-deps-required.md +0 -0
  60. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-15-session-summary-confirmation.md +0 -0
  61. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-16-fix-windows-daemon-console-window.md +0 -0
  62. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-18-daemon-timeout-and-index-rebuild.md +0 -0
  63. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-22-release-skill.md +0 -0
  64. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-26-fix-daemon-deprecation-warnings.md +0 -0
  65. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-27-intranet-model-download.md +0 -0
  66. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-28-tag-filtering.md +0 -0
  67. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-04-29-daemon-stop-fix.md +0 -0
  68. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-05-03-jfox-check.md +0 -0
  69. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-05-03-list-notes-skip-summary.md +0 -0
  70. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-05-03-log-level-fix.md +0 -0
  71. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/plans/2026-05-04-list-notes-index.md +0 -0
  72. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-04-03-bugfixes-design.md +0 -0
  73. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-04-12-skill-redesign-design.md +0 -0
  74. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-04-13-pr-auto-code-review-design.md +0 -0
  75. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-04-14-show-command-design.md +0 -0
  76. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-04-15-gpu-embedding-design.md +0 -0
  77. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-04-15-session-summary-confirmation-design.md +0 -0
  78. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-04-21-release-skill-design.md +0 -0
  79. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-04-26-fix-daemon-deprecation-warnings-design.md +0 -0
  80. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-04-27-intranet-model-download-design.md +0 -0
  81. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-04-28-tag-filtering-design.md +0 -0
  82. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-04-29-daemon-stop-fix-design.md +0 -0
  83. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-04-30-jfox-kb-env-var-design.md +0 -0
  84. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-05-03-jfox-check-design.md +0 -0
  85. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-05-03-list-notes-skip-summary-design.md +0 -0
  86. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-05-03-log-level-fix-design.md +0 -0
  87. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/superpowers/specs/2026-05-04-list-notes-index-design.md +0 -0
  88. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/docs/troubleshooting.md +0 -0
  89. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jessica-jones-static-cable.md +0 -0
  90. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/__main__.py +0 -0
  91. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/bm25_index.py +0 -0
  92. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/daemon/__init__.py +0 -0
  93. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/daemon/__main__.py +0 -0
  94. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/daemon/client.py +0 -0
  95. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/daemon/process.py +0 -0
  96. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/daemon/server.py +0 -0
  97. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/embedding_backend.py +0 -0
  98. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/formatters.py +0 -0
  99. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/git_extractor.py +0 -0
  100. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/global_config.py +0 -0
  101. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/graph.py +0 -0
  102. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/indexer.py +0 -0
  103. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/model_downloader.py +0 -0
  104. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/note_index.py +0 -0
  105. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/performance.py +0 -0
  106. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/search_engine.py +0 -0
  107. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/jfox/vector_store.py +0 -0
  108. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/pytest.ini +0 -0
  109. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/run_full_test.ps1 +0 -0
  110. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/scripts/download-model-intranet.sh +0 -0
  111. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/skills-recommend/README.md +0 -0
  112. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/skills-recommend/claude-code/jfox-common/SKILL.md +0 -0
  113. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/skills-recommend/claude-code/jfox-ingest/SKILL.md +0 -0
  114. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/skills-recommend/claude-code/jfox-organize/SKILL.md +0 -0
  115. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/skills-recommend/claude-code/jfox-search/SKILL.md +0 -0
  116. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/skills-recommend/kimi-cli/jfox-common/SKILL.md +0 -0
  117. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/skills-recommend/kimi-cli/jfox-ingest/SKILL.md +0 -0
  118. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/skills-recommend/kimi-cli/jfox-organize/SKILL.md +0 -0
  119. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/skills-recommend/kimi-cli/jfox-search/SKILL.md +0 -0
  120. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/COVERAGE_PLAN.md +0 -0
  121. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/MIGRATION.md +0 -0
  122. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/TESTS.md +0 -0
  123. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/conftest.py +0 -0
  124. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/integration/__init__.py +0 -0
  125. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/integration/test_backlinks.py +0 -0
  126. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/integration/test_model_download.py +0 -0
  127. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/integration/test_tag_filter_cli.py +0 -0
  128. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/performance/__init__.py +0 -0
  129. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/performance/test_performance.py +0 -0
  130. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/test_advanced_features.py +0 -0
  131. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/test_cli_format.py +0 -0
  132. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/test_config_set_unit.py +0 -0
  133. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/test_config_unit.py +0 -0
  134. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/test_core_workflow.py +0 -0
  135. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/test_embedding_device.py +0 -0
  136. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/test_hybrid_search.py +0 -0
  137. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/test_integration.py +0 -0
  138. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/test_kb_current.py +0 -0
  139. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/test_suggest_links.py +0 -0
  140. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/__init__.py +0 -0
  141. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_atomic_write.py +0 -0
  142. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_bm25_batch.py +0 -0
  143. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_check.py +0 -0
  144. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_content_file.py +0 -0
  145. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_daemon_process.py +0 -0
  146. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_edit.py +0 -0
  147. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_format_unify.py +0 -0
  148. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_formatters.py +0 -0
  149. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_git_extractor.py +0 -0
  150. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_global_config.py +0 -0
  151. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_index_kb_param.py +0 -0
  152. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_indexer_clear_before_rebuild.py +0 -0
  153. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_indexer_verify.py +0 -0
  154. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_kb_manager.py +0 -0
  155. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_lazy_import.py +0 -0
  156. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_list_notes_skip.py +0 -0
  157. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_logging_config.py +0 -0
  158. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_model_downloader.py +0 -0
  159. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_note_index.py +0 -0
  160. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_release_helper.py +0 -0
  161. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_show.py +0 -0
  162. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_tag_filter.py +0 -0
  163. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_template.py +0 -0
  164. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_template_cli.py +0 -0
  165. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_use_kb_env_var.py +0 -0
  166. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/unit/test_vector_store_clear.py +0 -0
  167. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/utils/__init__.py +0 -0
  168. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/utils/assertions.py +0 -0
  169. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/utils/jfox_cli.py +0 -0
  170. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/utils/note_generator.py +0 -0
  171. {jfox_cli-0.7.2 → jfox_cli-0.8.0}/tests/utils/temp_kb.py +0 -0
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "jfox-skills",
3
+ "id": "jfox-skills",
4
+ "owner": { "name": "zhuxixi" },
5
+ "metadata": {
6
+ "description": "JFox Zettelkasten 知识管理工具的 Claude Code 集成",
7
+ "version": "0.1.0"
8
+ },
9
+ "plugins": [
10
+ {
11
+ "name": "jfox",
12
+ "source": "./",
13
+ "description": "JFox 知识管理 CLI 的 Claude Code 集成——搜索、导入、整理、会话总结",
14
+ "version": "0.1.0",
15
+ "author": { "name": "zhuxixi" },
16
+ "keywords": ["zettelkasten", "knowledge-management"],
17
+ "category": "workflow"
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "jfox",
3
+ "description": "JFox 知识管理 CLI 的 Claude Code 集成——搜索、导入、整理、会话总结",
4
+ "version": "0.1.0",
5
+ "author": { "name": "zhuxixi" },
6
+ "license": "MIT",
7
+ "keywords": ["zettelkasten", "knowledge-management", "cli"],
8
+ "skills": [
9
+ "./skills-recommend/claude-code/jfox-common",
10
+ "./skills-recommend/claude-code/jfox-ingest",
11
+ "./skills-recommend/claude-code/jfox-organize",
12
+ "./skills-recommend/claude-code/jfox-search",
13
+ "./skills-recommend/claude-code/jfox-session-summary"
14
+ ],
15
+ "commands": [
16
+ "./commands/jfox-common",
17
+ "./commands/jfox-ingest",
18
+ "./commands/jfox-organize",
19
+ "./commands/jfox-search",
20
+ "./commands/jfox-session-summary"
21
+ ]
22
+ }
@@ -38,21 +38,25 @@ jfox/
38
38
  ├── jfox/ # 主包
39
39
  │ ├── __init__.py
40
40
  │ ├── __main__.py # 入口点
41
- │ ├── cli.py # CLI 主程序(所有命令)
41
+ │ ├── cli.py # CLI 主程序(所有命令,~2900 行)
42
42
  │ ├── models.py # 数据模型(Note, NoteType)
43
43
  │ ├── config.py # 配置管理(ZKConfig, use_kb)
44
44
  │ ├── global_config.py # 全局配置管理(多知识库)
45
45
  │ ├── note.py # 笔记 CRUD 操作
46
46
  │ ├── kb_manager.py # 知识库管理器
47
- │ ├── embedding_backend.py # 嵌入模型后端
47
+ │ ├── embedding_backend.py # 嵌入模型后端(支持 daemon 代理)
48
+ │ ├── daemon/ # Embedding 模型 HTTP 守护进程
48
49
  │ ├── vector_store.py # ChromaDB 向量存储
49
50
  │ ├── bm25_index.py # BM25 关键词索引
50
51
  │ ├── search_engine.py # 混合搜索引擎(RRF 融合)
51
52
  │ ├── graph.py # 知识图谱(NetworkX)
52
- │ ├── indexer.py # 文件监控和索引
53
+ │ ├── indexer.py # 文件监控和增量索引
53
54
  │ ├── formatters.py # 多格式输出(JSON/CSV/YAML/Tree)
54
55
  │ ├── template.py # 模板系统
55
56
  │ ├── template_cli.py # 模板 CLI 子命令
57
+ │ ├── git_extractor.py # Git 仓库数据提取器(ingest 功能)
58
+ │ ├── model_downloader.py # 嵌入模型下载与缓存管理
59
+ │ ├── note_index.py # 笔记索引管理(文件名↔ID 映射)
56
60
  │ └── performance.py # 性能优化工具
57
61
  ├── tests/ # 测试目录
58
62
  │ ├── conftest.py # pytest 配置和 fixtures
@@ -81,30 +85,32 @@ jfox/
81
85
  ### 安装开发环境
82
86
 
83
87
  ```bash
84
- # 创建虚拟环境(推荐)
85
- python -m venv .venv
86
- source .venv/bin/activate # Linux/Mac
87
- .venv\Scripts\activate # Windows
88
-
89
- # 开发模式安装
88
+ # 安装(使用 uv,推荐)
90
89
  uv sync --extra dev
90
+
91
+ # 安装(legacy pip fallback)
92
+ pip install -e ".[dev]"
91
93
  ```
92
94
 
93
95
  ### 运行测试
94
96
 
95
97
  ```bash
96
98
  # 运行所有测试
97
- pytest tests/ -v
99
+ uv run pytest tests/ -v
98
100
 
99
101
  # 运行特定测试文件
100
- pytest tests/test_core_workflow.py -v
102
+ uv run pytest tests/test_core_workflow.py -v
101
103
 
102
104
  # 运行带标记的测试
103
- pytest tests/ -m "not slow" # 排除慢测试
104
- pytest tests/ -m "integration" # 仅运行集成测试
105
+ uv run pytest tests/ -m "not slow" # 排除慢测试
106
+ uv run pytest tests/ -m "not embedding and not slow" # 快速测试(不加载模型)
107
+ uv run pytest tests/ -m "integration" # 仅运行集成测试
105
108
 
106
109
  # 保留测试数据(用于调试)
107
- pytest tests/ --keep-data
110
+ uv run pytest tests/ --keep-data
111
+
112
+ # 覆盖率
113
+ uv run pytest tests/ --cov=jfox --cov-report=html
108
114
 
109
115
  # Windows 全量测试(清理 + 测试)
110
116
  .\run_full_test.ps1
@@ -117,21 +123,21 @@ pytest tests/ --keep-data
117
123
 
118
124
  ```bash
119
125
  # 使用 black 格式化
120
- black jfox/ tests/
126
+ uv run black jfox/ tests/
121
127
 
122
128
  # 使用 ruff 检查
123
- ruff check jfox/ tests/
129
+ uv run ruff check jfox/ tests/
124
130
  ```
125
131
 
126
- ### 本地安装和验证
132
+ ### 构建和验证
127
133
 
128
134
  ```bash
129
- # 安装到本地
130
- pip install -e .
135
+ # 构建
136
+ uv build
131
137
 
132
- # 验证安装
133
- jfox --help
134
- jfox --version
138
+ # 验证 CLI
139
+ uv run jfox --help
140
+ uv run jfox --version
135
141
  ```
136
142
 
137
143
  ## 代码组织
@@ -140,16 +146,21 @@ jfox --version
140
146
 
141
147
  | 模块 | 职责 |
142
148
  |------|------|
143
- | `cli.py` | 所有 CLI 命令定义和实现(~1000 行) |
149
+ | `cli.py` | 所有 CLI 命令定义和实现(~2900 行) |
144
150
  | `models.py` | Note 数据类、NoteType 枚举、Markdown 序列化/反序列化 |
145
151
  | `config.py` | ZKConfig 配置类、use_kb 上下文管理器(多知识库切换) |
146
152
  | `global_config.py` | GlobalConfigManager,管理 ~/.zk_config.json |
147
153
  | `note.py` | 笔记 CRUD:create_note, save_note, load_note, delete_note |
148
154
  | `kb_manager.py` | KnowledgeBaseManager,知识库生命周期管理 |
149
- | `search_engine.py` | HybridSearchEngine,支持 HYBRID/SEMANTIC/KEYWORD 模式 |
155
+ | `search_engine.py` | HybridSearchEngine,支持 HYBRID/SEMANTIC/KEYWORD 模式,RRF 融合 |
150
156
  | `bm25_index.py` | BM25Index,本地文件存储的关键词索引 |
151
157
  | `vector_store.py` | VectorStore,ChromaDB 封装 |
152
158
  | `graph.py` | KnowledgeGraph,NetworkX 图分析和可视化 |
159
+ | `git_extractor.py` | Git 仓库数据提取器(ingest 功能) |
160
+ | `model_downloader.py` | 嵌入模型下载与缓存管理 |
161
+ | `note_index.py` | 笔记索引管理(文件名↔ID 映射) |
162
+ | `indexer.py` | 文件监控(watchdog)+ 增量索引 |
163
+ | `daemon/` | Embedding 模型 HTTP 守护进程(server/client/process) |
153
164
 
154
165
  ### 笔记类型
155
166
 
@@ -158,8 +169,14 @@ class NoteType(Enum):
158
169
  FLEETING = "fleeting" # 闪念笔记 - 快速捕捉
159
170
  LITERATURE = "literature" # 文献笔记 - 读书笔记
160
171
  PERMANENT = "permanent" # 永久笔记 - 整理后的知识
172
+ SESSION = "session" # AI Agent 会话记录
161
173
  ```
162
174
 
175
+ 各类型文件名格式:
176
+ - `fleeting`: `YYYYMMDD-HHMMSS.md`
177
+ - `literature`: `YYYYMMDDHHMMSS-{slug}.md`
178
+ - `permanent`: `YYYYMMDDHHMMSS-{slug}.md`
179
+
163
180
  ### 笔记文件格式
164
181
 
165
182
  每个笔记是一个 Markdown 文件,包含 YAML frontmatter:
@@ -174,6 +191,7 @@ updated: '2026-03-21T01:15:28'
174
191
  tags: [tag1, tag2]
175
192
  links: ['20260321011546'] # 正向链接
176
193
  backlinks: ['20260321011550'] # 反向链接(自动生成)
194
+ topic: null # 会话主题(仅 session 类型)
177
195
  ---
178
196
 
179
197
  # 笔记标题
@@ -184,8 +202,8 @@ backlinks: ['20260321011550'] # 反向链接(自动生成)
184
202
  ### 多知识库支持
185
203
 
186
204
  - 全局配置存储在 `~/.zk_config.json`
187
- - 默认知识库路径:`~/.zettelkasten`
188
- - 命名知识库路径:`~/.zettelkasten-{name}`
205
+ - 默认知识库路径:`~/.zettelkasten/default/`
206
+ - 命名知识库路径:`~/.zettelkasten/<name>/`
189
207
  - 使用 `use_kb()` 上下文管理器临时切换知识库
190
208
 
191
209
  ## 代码风格指南
@@ -224,6 +242,13 @@ backlinks: ['20260321011550'] # 反向链接(自动生成)
224
242
  2. **集成测试**: 测试完整工作流
225
243
  3. **性能测试**: 标记为 `@pytest.mark.performance`
226
244
 
245
+ ### 测试目录结构
246
+
247
+ - `tests/unit/` — 纯逻辑单元测试(约 25 个文件)
248
+ - `tests/integration/` — 跨模块集成测试
249
+ - `tests/performance/` — 性能基准测试
250
+ - 根级遗留:`test_config_unit.py`、`test_config_set_unit.py`(与 unit 目录中测试内容不同)
251
+
227
252
  ### 测试工具
228
253
 
229
254
  - **临时知识库**: `tests/utils/temp_kb.py`
@@ -235,34 +260,49 @@ backlinks: ['20260321011550'] # 反向链接(自动生成)
235
260
  ```python
236
261
  # conftest.py 中定义的主要 fixtures
237
262
 
238
- def test_example(temp_kb, cli, generator):
263
+ def test_example(temp_kb, cli, cli_fast, generator, mock_embedding_backend):
239
264
  """
240
265
  temp_kb: 临时知识库路径
241
266
  cli: 已初始化的 ZKCLI 实例
267
+ cli_fast: ZKCLI with mocked embeddings(快速,不加载模型)
242
268
  generator: NoteGenerator 数据生成器
269
+ mock_embedding_backend: mock 嵌入后端
243
270
  """
244
271
  pass
245
272
  ```
246
273
 
274
+ ### 测试标记(Markers)
275
+
276
+ | 标记 | 含义 |
277
+ |------|------|
278
+ | `slow` | 慢测试 |
279
+ | `performance` | 性能基准 |
280
+ | `integration` | 集成测试 |
281
+ | `embedding` | 涉及模型加载 |
282
+ | `workflow` | 工作流测试 |
283
+ | `bulk` | 批量操作测试 |
284
+
285
+ ### 测试运行规则
286
+
287
+ - **全量/集成测试(~50min)不要自主运行**,提供命令让用户手动执行
288
+ - **快速单元测试(几秒内)可以自主运行**,如单个模块的纯逻辑测试,不涉及 embedding 或 ChromaDB
289
+ - `pytest.ini` 配置:`timeout=120`、`--strict-markers`、`-ra`
290
+ - 测试以单进程运行,避免 ChromaDB/模型加载冲突
291
+
247
292
  ### 编写新测试的模板
248
293
 
249
294
  ```python
250
295
  # tests/test_feature.py
251
296
 
252
297
  import pytest
253
- from tests.utils.temp_kb import temp_knowledge_base
254
- from tests.utils.jfox_cli import ZKCLI
255
298
 
256
299
 
257
300
  class TestFeatureName:
258
301
  """测试功能名称"""
259
302
 
260
- def test_basic_functionality(self, temp_kb):
303
+ def test_basic_functionality(self, temp_kb, cli):
261
304
  """测试基本功能"""
262
- cli = ZKCLI(temp_kb)
263
- cli.init()
264
-
265
- # 测试代码
305
+ # 使用 fixture 自动初始化的临时知识库和 CLI 实例
266
306
  result = cli.add("测试内容", title="测试笔记")
267
307
 
268
308
  assert result.success
@@ -343,6 +383,37 @@ def new_command(
343
383
  | 图谱构建 | <1s (1000笔记) |
344
384
  | 文件监控 | 实时 (<1s 延迟) |
345
385
 
386
+ ## CI(GitHub Actions)
387
+
388
+ `.github/workflows/integration-test.yml` 包含四个 job:
389
+
390
+ - **Fast**(PR/push 触发):`not embedding and not slow`,Python 3.11,Ubuntu + Windows
391
+ - **Core**(main 分支推送):Core workflow 测试,使用真实 embedding,Python 3.10 + 3.12
392
+ - **Full**(手动触发):所有测试、所有 OS、所有 Python 版本
393
+ - **Coverage**(Fast 完成后):运行覆盖率,上传 HTML/XML 产物
394
+
395
+ **Release** 工作流(`.github/workflows/publish.yml`):在 GitHub Release 发布时自动推送到 PyPI。
396
+
397
+ ## Windows 注意事项
398
+
399
+ - `robocopy` 参数会被 bash 误解析,应使用 `cmd.exe /c "robocopy source dest /E"`
400
+ - 设置 `PYTHONUTF8=1` 和 `chcp 65001` 避免编码问题
401
+ - HuggingFace 国内镜像:`export HF_ENDPOINT=https://hf-mirror.com`
402
+
403
+ ## 分支规则
404
+
405
+ - **main 是保护分支**,不能直接 commit 或 push
406
+ - 所有改动必须通过**新分支 + PR** 合入
407
+
408
+ ## 发版规则
409
+
410
+ - 发版时必须同时修改三处版本号:
411
+ 1. `pyproject.toml`
412
+ 2. `jfox/__init__.py`
413
+ 3. `uv.lock`
414
+ - 操作顺序:先改 `pyproject.toml` 和 `__init__.py`,再跑 `uv lock` 更新 lock 文件
415
+ - (曾有 #88 遗漏 `__init__.py` 的教训)
416
+
346
417
  ## 相关资源
347
418
 
348
419
  - **详细 CLI 文档**: `README.md`
@@ -384,6 +455,12 @@ class OutputFormatter:
384
455
  # 4. 添加测试
385
456
  ```
386
457
 
458
+ ## 常见陷阱(Gotchas)
459
+
460
+ - `pytest.ini` 的 `addopts` 已包含 `-v`,手动再加 `-v` 是冗余的
461
+ - 测试目录重组已基本完成,根级 `test_config_unit.py` 和 `test_config_set_unit.py` 与 `tests/unit/` 中对应文件测试内容不同,不是重复
462
+ - `jfox show <id_or_title>` 复用 `find_note_id_by_title_or_id` 定位笔记,只读输出完整 Markdown
463
+
387
464
  ---
388
465
 
389
466
  ## Session History
@@ -2,6 +2,17 @@
2
2
 
3
3
  All notable changes to jfox-cli will be documented in this file.
4
4
 
5
+ ## [0.8.0] - 2026-05-10
6
+
7
+ ### Features
8
+ - add Claude Code plugin packaging for jfox skills (#209) (#210)
9
+ - 新增 session 笔记类型,专存 AI Agent 会话记录 (#202)
10
+
11
+ ### Changes
12
+ - sync AGENTS.md with CLAUDE.md and current codebase (#208)
13
+
14
+ [0.8.0]: https://github.com/zhuxixi/jfox/compare/v0.7.2...v0.8.0
15
+
5
16
  ## [0.7.2] - 2026-05-07
6
17
 
7
18
  ### Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jfox-cli
3
- Version: 0.7.2
3
+ Version: 0.8.0
4
4
  Summary: JFox - Zettelkasten 知识管理 CLI 工具
5
5
  Project-URL: Homepage, https://github.com/zhuxixi/jfox
6
6
  Project-URL: Repository, https://github.com/zhuxixi/jfox
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: jfox-common
3
+ description: 管理知识库(创建、切换、健康检查)和笔记 CRUD
4
+ ---
5
+
6
+ 请调用 jfox-common skill 来完成用户的请求。传递用户提供的参数。
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: jfox-ingest
3
+ description: 从 Git 仓库导入数据(git log、PR、Issues)为 fleeting 笔记
4
+ ---
5
+
6
+ 请调用 jfox-ingest skill 来完成用户的请求。传递用户提供的参数。
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: jfox-organize
3
+ description: 整理知识库、提炼 fleeting 笔记为 permanent、生成 wiki links
4
+ ---
5
+
6
+ 请调用 jfox-organize skill 来完成用户的请求。传递用户提供的参数。
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: jfox-search
3
+ description: 搜索笔记、图谱查询、链接推荐
4
+ ---
5
+
6
+ 请调用 jfox-search skill 来完成用户的请求。传递用户提供的参数。
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: jfox-session-summary
3
+ description: 保存会话总结到知识库作为 fleeting 笔记
4
+ ---
5
+
6
+ 请调用 jfox-session-summary skill 来完成用户的请求。传递用户提供的参数。
@@ -1,5 +1,5 @@
1
1
  """JFox - Zettelkasten 知识管理工具"""
2
2
 
3
- __version__ = "0.7.2"
3
+ __version__ = "0.8.0"
4
4
  __author__ = "User"
5
5
  __email__ = "user@example.com"
@@ -292,6 +292,7 @@ def _add_note_impl(
292
292
  source: Optional[str],
293
293
  output_format: str,
294
294
  template: Optional[str] = None,
295
+ topic: Optional[str] = None,
295
296
  ):
296
297
  """添加笔记的内部实现"""
297
298
  # 如果指定了模板,使用模板渲染
@@ -305,6 +306,7 @@ def _add_note_impl(
305
306
  "title": title or "",
306
307
  "content": content,
307
308
  "source": source or "",
309
+ "topic": topic or "",
308
310
  }
309
311
 
310
312
  # 渲染模板
@@ -331,7 +333,13 @@ def _add_note_impl(
331
333
  try:
332
334
  nt = NoteType(note_type.lower())
333
335
  except ValueError:
334
- raise ValueError(f"Invalid note type: {note_type}. Use: fleeting, literature, permanent")
336
+ raise ValueError(
337
+ f"Invalid note type: {note_type}. Use: fleeting, literature, permanent, session"
338
+ )
339
+
340
+ # session 类型必须提供 --topic
341
+ if nt == NoteType.SESSION and not topic:
342
+ raise ValueError("--type session 需要 --topic 参数")
335
343
 
336
344
  # 从内容中提取维基链接
337
345
  wiki_links = extract_wiki_links(content)
@@ -353,6 +361,7 @@ def _add_note_impl(
353
361
  tags=tags or [],
354
362
  links=resolved_links,
355
363
  source=source,
364
+ topic=topic,
356
365
  )
357
366
 
358
367
  # 保存笔记
@@ -410,7 +419,7 @@ def add(
410
419
  content: Optional[str] = typer.Argument(None, help="笔记内容(支持 [[笔记标题]] 格式链接)"),
411
420
  title: Optional[str] = typer.Option(None, "--title", "-t", help="笔记标题"),
412
421
  note_type: str = typer.Option(
413
- "fleeting", "--type", help="笔记类型 (fleeting/literature/permanent)"
422
+ "fleeting", "--type", help="笔记类型 (fleeting/literature/permanent/session)"
414
423
  ),
415
424
  tags: Optional[List[str]] = typer.Option(None, "--tag", help="标签(可多次使用)"),
416
425
  source: Optional[str] = typer.Option(None, "--source", "-s", help="来源(文献笔记)"),
@@ -420,6 +429,7 @@ def add(
420
429
  content_file: Optional[str] = typer.Option(
421
430
  None, "--content-file", help="从文件读取内容(用 - 表示 stdin)"
422
431
  ),
432
+ topic: Optional[str] = typer.Option(None, "--topic", help="会话主题(session 类型必填)"),
423
433
  kb: Optional[str] = typer.Option(None, "--kb", "-k", help="目标知识库名称"),
424
434
  output_format: str = typer.Option("table", "--format", "-f", help="输出格式: json, table"),
425
435
  json_output: bool = typer.Option(
@@ -447,7 +457,7 @@ def add(
447
457
  from .config import use_kb
448
458
 
449
459
  with use_kb(kb):
450
- _add_note_impl(content, title, note_type, tags, source, output_format, template)
460
+ _add_note_impl(content, title, note_type, tags, source, output_format, template, topic)
451
461
 
452
462
  except typer.Exit:
453
463
  raise
@@ -783,7 +793,9 @@ def _list_impl(
783
793
  try:
784
794
  nt = NoteType(note_type.lower())
785
795
  except ValueError:
786
- raise ValueError(f"Invalid note type: {note_type}")
796
+ raise ValueError(
797
+ f"Invalid note type: {note_type}. Use: fleeting, literature, permanent, session"
798
+ )
787
799
 
788
800
  notes = note.list_notes(note_type=nt, tags=tags, limit=limit)
789
801
  data = [n.to_dict() for n in notes]
@@ -1195,6 +1207,7 @@ def _edit_impl(
1195
1207
  note_type: Optional[str],
1196
1208
  source: Optional[str],
1197
1209
  output_format: str,
1210
+ topic: Optional[str] = None,
1198
1211
  ):
1199
1212
  """编辑笔记的内部实现"""
1200
1213
  # 验证:--content 和 --content-file 互斥
@@ -1206,10 +1219,10 @@ def _edit_impl(
1206
1219
  content = _read_content_file(content_file)
1207
1220
 
1208
1221
  # 验证:至少指定一个编辑字段
1209
- if all(v is None for v in [content, title, tags, note_type, source]):
1222
+ if all(v is None for v in [content, title, tags, note_type, source, topic]):
1210
1223
  raise ValueError(
1211
1224
  "至少指定一个要编辑的字段 "
1212
- "(--content, --content-file, --title, --tags, --type, --source)"
1225
+ "(--content, --content-file, --title, --tags, --type, --source, --topic)"
1213
1226
  )
1214
1227
 
1215
1228
  # 加载笔记
@@ -1234,9 +1247,15 @@ def _edit_impl(
1234
1247
  new_type = NoteType(note_type.lower())
1235
1248
  except ValueError:
1236
1249
  raise ValueError(
1237
- f"Invalid note type: {note_type}. Use: fleeting, literature, permanent"
1250
+ f"Invalid note type: {note_type}. Use: fleeting, literature, permanent, session"
1238
1251
  )
1239
1252
  n.type = new_type
1253
+ # 改为 session 类型时,笔记必须已有 topic 或通过 --topic 设置
1254
+ if new_type == NoteType.SESSION and not n.topic and not topic:
1255
+ raise ValueError("改为 session 类型时需要 --topic 参数")
1256
+
1257
+ if topic is not None:
1258
+ n.topic = topic
1240
1259
 
1241
1260
  # 如果内容被更新,解析 wiki links
1242
1261
  if content is not None:
@@ -1333,9 +1352,10 @@ def edit(
1333
1352
  title: Optional[str] = typer.Option(None, "--title", "-t", help="新标题"),
1334
1353
  tags: Optional[List[str]] = typer.Option(None, "--tag", help="新标签(替换全部)"),
1335
1354
  note_type: Optional[str] = typer.Option(
1336
- None, "--type", help="新类型 (fleeting/literature/permanent)"
1355
+ None, "--type", help="新类型 (fleeting/literature/permanent/session)"
1337
1356
  ),
1338
1357
  source: Optional[str] = typer.Option(None, "--source", "-s", help="新来源"),
1358
+ topic: Optional[str] = typer.Option(None, "--topic", help="会话主题(session 类型)"),
1339
1359
  kb: Optional[str] = typer.Option(None, "--kb", "-k", help="目标知识库名称"),
1340
1360
  output_format: str = typer.Option("table", "--format", "-f", help="输出格式: json, table"),
1341
1361
  json_output: bool = typer.Option(
@@ -1352,7 +1372,7 @@ def edit(
1352
1372
 
1353
1373
  with use_kb(kb):
1354
1374
  _edit_impl(
1355
- note_id, content, content_file, title, tags, note_type, source, output_format
1375
+ note_id, content, content_file, title, tags, note_type, source, output_format, topic
1356
1376
  )
1357
1377
  except typer.Exit:
1358
1378
  raise
@@ -1684,28 +1704,36 @@ def _inbox_impl(
1684
1704
  from .note_index import get_note_index
1685
1705
 
1686
1706
  idx = get_note_index()
1687
- fleeting_notes = idx.list_meta(note_type=NoteType.FLEETING, limit=limit)
1707
+ # 查询 fleeting 和 session 类型笔记(不传 limit,合并后再截断)
1708
+ fleeting_notes = idx.list_meta(note_type=NoteType.FLEETING)
1709
+ session_notes = idx.list_meta(note_type=NoteType.SESSION)
1710
+ all_notes = fleeting_notes + session_notes
1711
+ # Sort by created descending
1712
+ all_notes.sort(key=lambda m: m.created or "", reverse=True)
1713
+ all_notes = all_notes[:limit]
1688
1714
 
1689
1715
  result = {
1690
- "total": len(fleeting_notes),
1716
+ "total": len(all_notes),
1691
1717
  "notes": [
1692
1718
  {
1693
1719
  "id": m.id,
1694
1720
  "title": m.title,
1721
+ "type": m.type.value,
1695
1722
  "created": m.created,
1696
1723
  "filepath": m.filepath if m.filepath else None,
1697
1724
  }
1698
- for m in fleeting_notes
1725
+ for m in all_notes
1699
1726
  ],
1700
1727
  }
1701
1728
 
1702
1729
  if output_format == "json":
1703
1730
  print(output_json(result))
1704
1731
  else:
1705
- console.print(f"[bold]Fleeting Notes ({len(fleeting_notes)}):[/bold]\n")
1706
- for m in fleeting_notes:
1732
+ console.print(f"[bold]Inbox ({len(all_notes)}):[/bold]\n")
1733
+ for m in all_notes:
1707
1734
  time_str = m.created[11:16] if m.created and len(m.created) >= 16 else ""
1708
- console.print(f"- [{time_str}] {m.title}")
1735
+ type_badge = {"fleeting": "fl", "session": "se"}.get(m.type.value, "??")
1736
+ console.print(f"- [{time_str}] [{type_badge}] {m.title}")
1709
1737
 
1710
1738
 
1711
1739
  def _suggest_links_impl(
@@ -1795,7 +1823,7 @@ def inbox(
1795
1823
  False, "--json", help="JSON 输出(快捷方式,等同于 --format json)"
1796
1824
  ),
1797
1825
  ):
1798
- """查看临时笔记 (Fleeting Notes)"""
1826
+ """查看临时笔记和会话记录 (Fleeting + Session Notes)"""
1799
1827
  try:
1800
1828
  # 处理 --json 快捷方式
1801
1829
  if json_output:
@@ -58,6 +58,7 @@ class ZKConfig:
58
58
  self.notes_dir / "fleeting",
59
59
  self.notes_dir / "literature",
60
60
  self.notes_dir / "permanent",
61
+ self.notes_dir / "session",
61
62
  self.zk_dir,
62
63
  self.chroma_dir,
63
64
  self.zk_dir / "cache",
@@ -249,12 +249,12 @@ class KnowledgeBaseManager:
249
249
 
250
250
  # 统计笔记数量
251
251
  total = 0
252
- by_type = {"fleeting": 0, "literature": 0, "permanent": 0}
252
+ by_type = {"fleeting": 0, "literature": 0, "permanent": 0, "session": 0}
253
253
 
254
254
  if path.exists():
255
255
  notes_dir = path / "notes"
256
256
  if notes_dir.exists():
257
- for note_type in ["fleeting", "literature", "permanent"]:
257
+ for note_type in ["fleeting", "literature", "permanent", "session"]:
258
258
  type_dir = notes_dir / note_type
259
259
  if type_dir.exists():
260
260
  count = len(list(type_dir.glob("*.md")))
@@ -16,6 +16,7 @@ class NoteType(Enum):
16
16
  FLEETING = "fleeting" # 闪念笔记
17
17
  LITERATURE = "literature" # 文献笔记
18
18
  PERMANENT = "permanent" # 永久笔记
19
+ SESSION = "session" # AI Agent 会话记录
19
20
 
20
21
 
21
22
  @dataclass
@@ -32,6 +33,7 @@ class Note:
32
33
  links: List[str] = field(default_factory=list) # 正向链接
33
34
  backlinks: List[str] = field(default_factory=list) # 反向链接
34
35
  source: Optional[str] = None # 来源(文献笔记)
36
+ topic: Optional[str] = None # 会话主题(session 类型)
35
37
 
36
38
  # 运行时字段(不持久化到 frontmatter)
37
39
  embedding: Optional[List[float]] = None # 向量
@@ -48,9 +50,12 @@ class Note:
48
50
  """生成文件名"""
49
51
  if self.type == NoteType.FLEETING:
50
52
  return f"{self.id[:8]}-{self.id[8:]}.md"
53
+ elif self.type == NoteType.SESSION:
54
+ source = self.topic or self.title or "untitled"
55
+ slug = re.sub(r"[^\w\-]", "", source.lower().replace(" ", "-"))[:50]
56
+ return f"{self.id}-{slug}.md"
51
57
  else:
52
58
  slug = self.title.lower().replace(" ", "-")[:50]
53
- # 移除特殊字符
54
59
  slug = re.sub(r"[^\w\-]", "", slug)
55
60
  return f"{self.id}-{slug}.md"
56
61
 
@@ -80,6 +85,8 @@ class Note:
80
85
  }
81
86
  if self.source:
82
87
  frontmatter["source"] = self.source
88
+ if self.topic:
89
+ frontmatter["topic"] = self.topic
83
90
 
84
91
  fm_yaml = yaml.dump(frontmatter, allow_unicode=True, sort_keys=False)
85
92
 
@@ -128,6 +135,7 @@ class Note:
128
135
  links=fm.get("links", []),
129
136
  backlinks=fm.get("backlinks", []),
130
137
  source=fm.get("source"),
138
+ topic=fm.get("topic"),
131
139
  )
132
140
 
133
141
  def to_dict(self) -> Dict[str, Any]:
@@ -144,4 +152,5 @@ class Note:
144
152
  "filepath": str(self.filepath),
145
153
  "score": self.score,
146
154
  "hop": self.hop,
155
+ "topic": self.topic,
147
156
  }