smartpipe-cli 1.4.0rc3__tar.gz → 1.4.0rc4__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 (253) hide show
  1. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/CHANGELOG.md +97 -13
  2. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/CITATION.cff +1 -1
  3. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/PKG-INFO +5 -5
  4. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/README.md +4 -4
  5. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/scenes/ScaleB.tsx +2 -2
  6. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/comparison.md +2 -2
  7. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/concepts/feeding-smartpipe.md +10 -2
  8. smartpipe_cli-1.4.0rc4/docs/concepts/granularity.md +109 -0
  9. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/concepts/models-and-providers.md +42 -44
  10. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/concepts/output-formats.md +7 -1
  11. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/concepts/structured-output.md +57 -0
  12. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/concepts/the-item.md +15 -2
  13. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/cookbook/live-monitoring.md +2 -2
  14. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/cookbook/visualizing-results.md +2 -2
  15. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/index.md +4 -4
  16. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/inputs/files.md +2 -2
  17. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/install.md +3 -3
  18. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/learn/1-first-pipeline.md +29 -14
  19. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/learn/3-files-and-media.md +6 -1
  20. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/learn/6-pipelines-that-last.md +7 -4
  21. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/privacy.md +5 -5
  22. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/reference/cli.md +69 -27
  23. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/reference/sem-files.md +39 -1
  24. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/troubleshooting.md +13 -9
  25. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/cluster.md +2 -2
  26. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/diff.md +1 -1
  27. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/embed.md +5 -4
  28. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/join.md +7 -2
  29. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/outliers.md +3 -3
  30. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/reduce.md +3 -3
  31. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/sort.md +4 -1
  32. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/summarize.md +5 -0
  33. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/top-k.md +6 -6
  34. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/where.md +5 -1
  35. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/mkdocs.yml +1 -0
  36. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/pyproject.toml +1 -1
  37. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/cluster_cmd.py +4 -1
  38. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/completions.py +23 -1
  39. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/config_cmd.py +147 -104
  40. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/distinct_cmd.py +4 -1
  41. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/doctor_cmd.py +1 -3
  42. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/embed_cmd.py +4 -1
  43. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/extend_cmd.py +4 -1
  44. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/filter_cmd.py +4 -1
  45. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/join_cmd.py +4 -1
  46. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/map_cmd.py +4 -1
  47. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/outliers_cmd.py +5 -2
  48. smartpipe_cli-1.4.0rc4/src/smartpipe/cli/read_cmd.py +124 -0
  49. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/readable_cmd.py +1 -1
  50. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/reduce_cmd.py +4 -1
  51. smartpipe_cli-1.4.0rc4/src/smartpipe/cli/rescue.py +94 -0
  52. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/root.py +36 -19
  53. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/run_cmd.py +28 -4
  54. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/schema_cmd.py +45 -11
  55. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/screens.py +12 -10
  56. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/sem_file.py +55 -10
  57. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/sort_cmd.py +1 -1
  58. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/split_cmd.py +4 -1
  59. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/top_k_cmd.py +5 -2
  60. smartpipe_cli-1.4.0rc4/src/smartpipe/config/bundles.py +186 -0
  61. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/config/display.py +2 -12
  62. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/config/picker.py +1 -1
  63. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/config/store.py +63 -118
  64. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/container.py +11 -7
  65. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/aggregate.py +11 -3
  66. smartpipe_cli-1.4.0rc4/src/smartpipe/engine/fieldpath.py +167 -0
  67. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/predicate.py +26 -3
  68. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/prompts.py +53 -10
  69. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/schema.py +28 -0
  70. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/schema_repl.py +7 -2
  71. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/items.py +13 -1
  72. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/readers.py +53 -21
  73. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/update_check.py +1 -1
  74. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/writers.py +3 -1
  75. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/budget.py +29 -1
  76. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/resolve.py +1 -2
  77. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/chart.py +14 -5
  78. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/cluster.py +17 -1
  79. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/common.py +4 -3
  80. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/convert.py +1 -1
  81. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/diff.py +6 -0
  82. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/filter.py +1 -1
  83. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/join.py +13 -2
  84. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/outliers.py +1 -1
  85. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/reduce.py +49 -9
  86. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/sortverb.py +4 -1
  87. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/summarize.py +3 -1
  88. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/top_k.py +27 -17
  89. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/where.py +5 -2
  90. smartpipe_cli-1.4.0rc3/src/smartpipe/cli/read_cmd.py +0 -68
  91. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/.gitignore +0 -0
  92. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/CONTRIBUTING.md +0 -0
  93. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/LICENSE +0 -0
  94. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/NOTICE +0 -0
  95. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/README.md +0 -0
  96. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/Main.tsx +0 -0
  97. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/Narration.tsx +0 -0
  98. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/Root.tsx +0 -0
  99. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/components/Background.tsx +0 -0
  100. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/components/Caption.tsx +0 -0
  101. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/components/FileGlyph.tsx +0 -0
  102. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/components/SceneFrame.tsx +0 -0
  103. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/components/Terminal.tsx +0 -0
  104. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/components/Wordmark.tsx +0 -0
  105. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/config.ts +0 -0
  106. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/font.ts +0 -0
  107. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/index.ts +0 -0
  108. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/narration/durations.json +0 -0
  109. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/narration/lines.json +0 -0
  110. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/scenes/Close.tsx +0 -0
  111. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/scenes/ColdOpen.tsx +0 -0
  112. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/scenes/CostHonesty.tsx +0 -0
  113. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/scenes/Graph.tsx +0 -0
  114. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/scenes/Hook.tsx +0 -0
  115. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/scenes/Multimodal.tsx +0 -0
  116. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/demo/video/src/scenes/ScaleA.tsx +0 -0
  117. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/assets/demo-thumb.jpg +0 -0
  118. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/assets/graph-hero.png +0 -0
  119. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/concepts/pipes-and-items.md +0 -0
  120. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/cookbook/README.md +0 -0
  121. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/cookbook/contract-extraction.md +0 -0
  122. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/cookbook/customer-feedback.md +0 -0
  123. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/cookbook/invoice-reconciliation.md +0 -0
  124. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/cookbook/knowledge-graph.md +0 -0
  125. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/cookbook/log-triage.md +0 -0
  126. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/cookbook/meeting-digest.md +0 -0
  127. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/cookbook/ranking-documents.md +0 -0
  128. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/cookbook/stream-enrichment.md +0 -0
  129. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/cookbook/training-data-prep.md +0 -0
  130. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/cookbook/video-qa.md +0 -0
  131. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/demo/index.html +0 -0
  132. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/learn/2-structured-data.md +0 -0
  133. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/learn/4-free-verbs.md +0 -0
  134. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/learn/5-scale-and-cost.md +0 -0
  135. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/quickstart.md +0 -0
  136. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/reference/agents.md +0 -0
  137. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/reference/custom-verbs.md +0 -0
  138. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/distinct.md +0 -0
  139. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/extend.md +0 -0
  140. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/filter.md +0 -0
  141. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/getschema.md +0 -0
  142. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/graph.md +0 -0
  143. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/map.md +0 -0
  144. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/readable.md +0 -0
  145. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/sample.md +0 -0
  146. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/docs/verbs/split.md +0 -0
  147. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/qa/README.md +0 -0
  148. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/qa/fixtures/README.md +0 -0
  149. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/__init__.py +0 -0
  150. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/__main__.py +0 -0
  151. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/assets/probe.png +0 -0
  152. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/assets/probe.txt +0 -0
  153. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/assets/probe.wav +0 -0
  154. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/__init__.py +0 -0
  155. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/auth_cmd.py +0 -0
  156. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/cache_cmd.py +0 -0
  157. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/chart_cmd.py +0 -0
  158. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/cite_cmd.py +0 -0
  159. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/diff_cmd.py +0 -0
  160. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/echo_cmd.py +0 -0
  161. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/getschema_cmd.py +0 -0
  162. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/graph_cmd.py +0 -0
  163. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/input_options.py +0 -0
  164. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/interrupts.py +0 -0
  165. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/probe_cmd.py +0 -0
  166. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/sample_cmd.py +0 -0
  167. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/schema_workshop.py +0 -0
  168. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/summarize_cmd.py +0 -0
  169. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/update_cmd.py +0 -0
  170. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/usage_cmd.py +0 -0
  171. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/where_cmd.py +0 -0
  172. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/cli/write_cmd.py +0 -0
  173. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/config/__init__.py +0 -0
  174. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/config/authflow.py +0 -0
  175. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/config/credentials.py +0 -0
  176. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/config/doctor.py +0 -0
  177. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/config/paths.py +0 -0
  178. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/config/state_cache.py +0 -0
  179. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/config/verify.py +0 -0
  180. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/core/__init__.py +0 -0
  181. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/core/errors.py +0 -0
  182. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/core/install_channel.py +0 -0
  183. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/core/jsontools.py +0 -0
  184. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/core/versions.py +0 -0
  185. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/__init__.py +0 -0
  186. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/blocking.py +0 -0
  187. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/chart.py +0 -0
  188. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/chunking.py +0 -0
  189. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/clustering.py +0 -0
  190. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/graphkg.py +0 -0
  191. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/graphout.py +0 -0
  192. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/preview.py +0 -0
  193. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/progressbar.py +0 -0
  194. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/ranking.py +0 -0
  195. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/repair.py +0 -0
  196. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/runner.py +0 -0
  197. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/schema_dsl.py +0 -0
  198. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/tally.py +0 -0
  199. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/temporal.py +0 -0
  200. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/timebin.py +0 -0
  201. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/units.py +0 -0
  202. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/engine/windows.py +0 -0
  203. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/__init__.py +0 -0
  204. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/arrow_menu.py +0 -0
  205. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/csvrows.py +0 -0
  206. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/diagnostics.py +0 -0
  207. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/inputs.py +0 -0
  208. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/leaderboard.py +0 -0
  209. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/metering.py +0 -0
  210. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/preview.py +0 -0
  211. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/progress.py +0 -0
  212. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/render.py +0 -0
  213. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/richui.py +0 -0
  214. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/text.py +0 -0
  215. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/tty.py +0 -0
  216. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/io/usage.py +0 -0
  217. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/__init__.py +0 -0
  218. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/anthropic_adapter.py +0 -0
  219. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/base.py +0 -0
  220. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/cache.py +0 -0
  221. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/catalogs.py +0 -0
  222. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/gemini_native.py +0 -0
  223. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/http_support.py +0 -0
  224. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/jina.py +0 -0
  225. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/keycheck.py +0 -0
  226. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/local_embed.py +0 -0
  227. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/local_ner.py +0 -0
  228. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/ocr.py +0 -0
  229. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/ollama.py +0 -0
  230. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/openai_codex.py +0 -0
  231. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/openai_compat.py +0 -0
  232. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/openai_oauth.py +0 -0
  233. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/retry.py +0 -0
  234. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/stt.py +0 -0
  235. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/models/windows.py +0 -0
  236. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/parsing/__init__.py +0 -0
  237. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/parsing/detect.py +0 -0
  238. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/parsing/extract.py +0 -0
  239. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/py.typed +0 -0
  240. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/__init__.py +0 -0
  241. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/distinct.py +0 -0
  242. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/embed.py +0 -0
  243. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/extend.py +0 -0
  244. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/getschema.py +0 -0
  245. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/graph.py +0 -0
  246. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/graphfull.py +0 -0
  247. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/map.py +0 -0
  248. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/oversize.py +0 -0
  249. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/readable.py +0 -0
  250. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/sample.py +0 -0
  251. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/split.py +0 -0
  252. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/src/smartpipe/verbs/write.py +0 -0
  253. {smartpipe_cli-1.4.0rc3 → smartpipe_cli-1.4.0rc4}/tests/corpus/README.md +0 -0
@@ -53,6 +53,15 @@ The identity release.
53
53
  power path.
54
54
 
55
55
  ### The item — one law for everything in a pipe
56
+ - **Nested field paths, everywhere you read.** `where 'user.plan ==
57
+ "pro"'`, `sort --by metrics.score`, `chart items[0].category`,
58
+ `summarize 'avg(metrics.score) by user.plan'`, and `"Is {user.plan}
59
+ worth it?"` in prompts - one grammar (`a.b.c`, `items[0]`,
60
+ `a.b['weird key']`) across all five surfaces. A column literally
61
+ named `user.plan` always wins over the traversal, so CSV headers
62
+ with dots keep working. Extraction names stay flat - paths are for
63
+ reading, and the error says so.
64
+
56
65
  - **Dates are a type, and they come back ISO.** `{due date}` and
57
66
  `{ts datetime}` join the brace grammar. However the model phrases it
58
67
  ("Jan 15, 2026", "15/01/2026"), the field canonicalizes to
@@ -84,9 +93,20 @@ The identity release.
84
93
  double-underscore namespace that rides every record: `__source` (path plus
85
94
  HOW the item was cut - file, lines, jsonl, pages, minutes, segment index),
86
95
  `__media` (one transport object for bytes crossing a pipe), `__score`
87
- (join), `__invalid`/`__error`/`__raw` (kept failures). Known fields
88
- round-trip through saved files; unknown `__` fields warn once and carry.
89
- User data owns everything up to one leading underscore.
96
+ (top_k and join similarity), `__rank` (top_k), `__snapshot` (top_k
97
+ --stream markers), `__distance` (outliers), `__invalid`/`__error`/`__raw`
98
+ (kept failures). Known fields round-trip through saved files; unknown `__`
99
+ fields warn once and carry. User data owns everything up to one leading
100
+ underscore - which is why the last single-underscore stragglers moved:
101
+ pre-1.4 `top_k`/`outliers` wrote `_score`/`_rank`/`_snapshot`/`_distance`,
102
+ and those spellings stay readable for one release (CSV/TSV still sort them
103
+ into the trailing columns) but are never written again. In the same sweep,
104
+ `cluster --explode` overwriting an existing `cluster` field became a
105
+ disclosed overwrite (one stderr warning) instead of a silent one.
106
+ - **top_k ranks can no longer collide.** Ranking keyed on each item's
107
+ source index, so two page-1 records from different PDFs fought over one
108
+ slot and a result silently vanished. Ranks are now run-scoped ordinals in
109
+ arrival order, in both the embedded and precomputed-vector paths.
90
110
  - **Records in, records out.** A plain-prompt `map` over records now returns
91
111
  a record (`{"result": …}` plus the spine) instead of bare prose - structure
92
112
  and provenance survive transformation. Text lines still leave as text.
@@ -114,6 +134,22 @@ The identity release.
114
134
  `where`/`summarize` report rows that had no fields; `--strict-rows` turns
115
135
  the notes into errors. Multi-line plain output into a pipe warns that
116
136
  line framing is ambiguous (use `--output json`).
137
+ - **`.sem` files are strict about their rows now.** A saved pipeline is a
138
+ program, and a stray plain line in a record stream is a bug, not a
139
+ shrug: `.sem` runs default to `--strict-rows` and fail at ingestion
140
+ naming the exact line, before any spend. Opt out with
141
+ `strict-rows = false` (top-level or per-stage); ad-hoc terminal runs
142
+ keep the permissive census. Eleven verbs that accepted `--strict-rows`
143
+ without actually enforcing it now do, and a text-only `where` predicate
144
+ over a log no longer trips strict mode over "missing fields". A new
145
+ docs page explains the granularity ladder (file → split → lines/rows)
146
+ and when mixing happens.
147
+ - **Synthesized records tell you what they summarize.** join pairs carry
148
+ `__sources` (both parents' refs); reduce windows stamp
149
+ `{"as": "window", "span": [1, 100], "count": 100}`, groups
150
+ `{"as": "group", "group": …, "count": N}`; cluster and diff summary
151
+ rows carry `{"as": "cluster"|"diff", "count": N}`. An audit trail for
152
+ every row that speaks for other rows - and `--bare` strips all of it.
117
153
 
118
154
  ### Judgment you can gate, retry, and keep
119
155
  - **`--keep-invalid`** (map/extend): after the repair retry fails, keep the
@@ -123,6 +159,13 @@ The identity release.
123
159
  `--check FILE` validates rows (exit 0/1), `--example` prints a validating
124
160
  instance, bare stdin mode is a REPL. **`--dry-run`** (map/extend) prints
125
161
  the composed first request and exits before any model resolution.
162
+ - **`schema --check` stopped failing your own pipelines.** The check is
163
+ open-world now: rows from the documented extend workflow (original
164
+ fields kept, spine aboard) pass instead of tripping "additional
165
+ properties are not allowed" on every row, and `?`-marked fields may be
166
+ absent, not just null. Extras earn one dim hint; `--strict` restores
167
+ the closed world for contract enforcement. The schema sent to models
168
+ at extraction time is unchanged.
126
169
  - **Nullability is declared.** `?` on any type (`string?`, `number[]?`, bare
127
170
  `field?`) compiles to a null union; bare fields mean scalar-or-scalar-list
128
171
  and never admit null (D48, shipped earlier in this cycle).
@@ -171,6 +214,19 @@ The identity release.
171
214
  over alphabetical luck (cloud tags compete equally), and speaks in the
172
215
  same color voice as the other commands with a menu of detected local
173
216
  tags and provider-prefixed cloud examples.
217
+ - **Exit 141 is now deliberate, and the -13 flake is dead.** smartpipe used
218
+ to arm the default SIGPIPE handler, so a downstream `| head` killed it by
219
+ raw signal - and, one run in a few hundred, a stray EPIPE on asyncio's
220
+ own self-pipe killed a healthy run mid-teardown, skipping the receipt
221
+ (the CI flake that delayed rc3). SIGPIPE now stays ignored; a closed
222
+ stdout surfaces as BrokenPipeError and exits a silent, deliberate 141
223
+ with every finally honored. (click 8.4's own EPIPE-to-exit-1 trap is
224
+ defused on the way.) One visible delta: `kill -PIPE` no longer
225
+ terminates smartpipe; pipeline behavior is unchanged.
226
+ - **A files-then-stdin wait has a name.** Chaining positional files into a
227
+ stdin read used to end in a silent hang when nothing was piped. All three
228
+ chain paths now say once, on stderr:
229
+ `note: files done - now reading stdin (pipe data or close it; files-only: add < /dev/null)`.
174
230
  - **Docs bug, live-caught: `cluster | chart` drew flat bars.** The summary
175
231
  rows are one-per-cluster, so charting them counts every theme once. The
176
232
  README quick-tour step, the `cluster` help epilog, and the `.sem`
@@ -239,15 +295,24 @@ The identity release.
239
295
 
240
296
  ### Documents parse where they enter, vectors stay honest
241
297
  - **The `ocr-model` role: a document parser at ingestion.** Set
242
- `smartpipe config ocr-model mistral/mistral-ocr-latest` (or
243
- `SMARTPIPE_OCR_MODEL`, or `--ocr-model` per run) and ingested PDFs and
244
- images parse through it - one item per page on the `pages` cut,
245
- markdown as the text, disclosed per row and metered as a paid
246
- conversion. Mistral refs ride the dedicated `/v1/ocr` wire
247
- (live-verified, whole PDFs in one call); any other model ref works as
248
- chat-vision with extract-the-text framing, so `ollama/llava` is a free
249
- local OCR. Parse failures fall back to the local extraction ladder,
250
- disclosed, never fatal. Unset = exactly the old behavior.
298
+ `ocr-model = "mistral/mistral-ocr-latest"` in config.toml (the setup
299
+ flow's OCR stage stamps it; `SMARTPIPE_OCR_MODEL` and `--ocr-model`
300
+ override per run) and ingested PDFs and images parse through it - one
301
+ item per page on the `pages` cut, markdown as the text, disclosed per
302
+ row and metered as a paid conversion. Mistral refs ride the dedicated
303
+ `/v1/ocr` wire (live-verified, whole PDFs in one call); any other
304
+ model ref works as chat-vision with extract-the-text framing, so
305
+ `ollama/llava` is a free local OCR. Parse failures fall back to the
306
+ local extraction ladder, disclosed, never fatal. Unset = exactly the
307
+ old behavior.
308
+ - **Reader mode does what you configured.** `smartpipe scan.pdf` used to
309
+ be pinned "zero model calls" even when you had set an ocr-model - the
310
+ reader now honors the role with the same per-row disclosure, local
311
+ fallback, and `--max-calls` belt as the verbs (plus a preflight note
312
+ when more than 20 files will parse). No ocr-model configured = the
313
+ same free path as always, pinned by a zero-HTTP-calls test. Found en
314
+ route: the mistral OCR wire was never counted by `--max-calls`
315
+ anywhere - it is belted now.
251
316
  - **The `media-embed-model` role: one joint space for pixels and prose.**
252
317
  Text keeps `embed-model`; media routes to the joint-space model
253
318
  (jina-clip-v2 and friends). If a run would mix two vector spaces, the
@@ -321,7 +386,26 @@ The identity release.
321
386
  overwrites one you chose yourself), and one y/N question adds a backup
322
387
  `fallback-model` for provider outages. After a `doctor --probe`,
323
388
  catalog entries carry capability chips (`sees, hears - probed 2d ago`)
324
- - probed facts, never claims. All the setter subcommands still work.
389
+ - probed facts, never claims.
390
+ - **`smartpipe use` - setup is one word now.** `use gemini` (or
391
+ `use claude-opus-4-8`, `use ollama/qwen3:8b`) stamps a coherent bundle
392
+ in one shot: the model, its paired embedder, and the captions posture,
393
+ each line disclosed with a ✓ and a reason. No credential for the named
394
+ provider = a clean refusal that names the exact `auth login` command,
395
+ nothing stamped. Bare `use` opens the interactive flow. `smartpipe
396
+ using` answers "what am I running?" with every setting, its value, and
397
+ WHERE it came from (flag, env, config file, default) in one aligned
398
+ grid. The config.toml you get is signed by its door -
399
+ `# stamped by: smartpipe use (2026-07-10T06:38Z)` - so a mystery
400
+ config explains itself. The old setter subcommands (`config model`,
401
+ `config embed-model`, …) and profiles are gone; an old config with
402
+ profile keys loads with one warning and cleans itself on the next
403
+ save.
404
+ - **The no-model dead end offers a hand.** At a real terminal, the
405
+ no-model error now ends with `run setup now? [Y/n]` - accept, walk the
406
+ same setup flow, and it closes with "saved - rerun your command".
407
+ Scripts and CI see byte-identical output to before (the offer is
408
+ TTY-gated), and the exit code stays honest.
325
409
 
326
410
  ### Getting it and keeping it current
327
411
  - **One-line install on every platform.**
@@ -7,5 +7,5 @@ authors:
7
7
  given-names: Prabal
8
8
  repository-code: "https://github.com/prabal-rje/smartpipe"
9
9
  license: Apache-2.0
10
- version: 1.4.0rc3
10
+ version: 1.4.0rc4
11
11
  date-released: '2026-07-08'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: smartpipe-cli
3
- Version: 1.4.0rc3
3
+ Version: 1.4.0rc4
4
4
  Summary: Semantic pipes and queries for your terminal - PDFs, images, audio, video, and text through Unix verbs that understand.
5
5
  Project-URL: Homepage, https://github.com/prabal-rje/smartpipe
6
6
  Project-URL: Changelog, https://github.com/prabal-rje/smartpipe/blob/main/CHANGELOG.md
@@ -49,7 +49,7 @@ Description-Content-Type: text/markdown
49
49
  Run PDFs, images, audio, video, and text through Unix verbs that understand
50
50
  their input.
51
51
 
52
- [![smartpipe demo - click to play with sound and controls](https://github.com/prabal-rje/smartpipe/releases/download/demo-assets/smartpipe-teaser-v4.gif)](https://prabal-rje.github.io/smartpipe/demo/)
52
+ [![smartpipe demo - click to play with sound and controls](https://github.com/prabal-rje/smartpipe/releases/download/demo-assets/smartpipe-teaser-v5.gif)](https://prabal-rje.github.io/smartpipe/demo/)
53
53
 
54
54
  *[▶ Watch the full 86-second demo](https://prabal-rje.github.io/smartpipe/demo/) - sound, controls, no download.*
55
55
 
@@ -93,7 +93,7 @@ and runs that tool's own upgrade.
93
93
  smartpipe auth login
94
94
  ```
95
95
 
96
- No ChatGPT plan? Use local [Ollama][ollama] or a cloud API key - see
96
+ No ChatGPT plan? Bring a cloud API key, or run local [Ollama][ollama] - see
97
97
  [Models & providers][models].
98
98
 
99
99
  ## Examples
@@ -165,7 +165,7 @@ calls by construction.
165
165
 
166
166
  ```bash
167
167
  # 1. point smartpipe at a model (ChatGPT login, a cloud key, or local Ollama)
168
- smartpipe config
168
+ smartpipe use
169
169
 
170
170
  # 2. ask one question across a folder of mixed documents
171
171
  smartpipe map "What does this say about pricing?" 'docs/*.pdf'
@@ -277,7 +277,7 @@ Full docs: **[prabal-rje.github.io/smartpipe][docs]**.
277
277
  - [Install][install] - packages and platforms
278
278
  - [Working with files & media][files] - PDFs, scans, images, audio, video
279
279
  - [CLI reference][cli] - every flag, format, and exit code
280
- - [Models & providers][models] - local Ollama, cloud keys, ChatGPT login
280
+ - [Models & providers][models] - ChatGPT login, cloud keys, local Ollama
281
281
  - [Privacy & security][privacy]
282
282
 
283
283
  ## How to cite
@@ -11,7 +11,7 @@
11
11
  Run PDFs, images, audio, video, and text through Unix verbs that understand
12
12
  their input.
13
13
 
14
- [![smartpipe demo - click to play with sound and controls](https://github.com/prabal-rje/smartpipe/releases/download/demo-assets/smartpipe-teaser-v4.gif)](https://prabal-rje.github.io/smartpipe/demo/)
14
+ [![smartpipe demo - click to play with sound and controls](https://github.com/prabal-rje/smartpipe/releases/download/demo-assets/smartpipe-teaser-v5.gif)](https://prabal-rje.github.io/smartpipe/demo/)
15
15
 
16
16
  *[▶ Watch the full 86-second demo](https://prabal-rje.github.io/smartpipe/demo/) - sound, controls, no download.*
17
17
 
@@ -55,7 +55,7 @@ and runs that tool's own upgrade.
55
55
  smartpipe auth login
56
56
  ```
57
57
 
58
- No ChatGPT plan? Use local [Ollama][ollama] or a cloud API key - see
58
+ No ChatGPT plan? Bring a cloud API key, or run local [Ollama][ollama] - see
59
59
  [Models & providers][models].
60
60
 
61
61
  ## Examples
@@ -127,7 +127,7 @@ calls by construction.
127
127
 
128
128
  ```bash
129
129
  # 1. point smartpipe at a model (ChatGPT login, a cloud key, or local Ollama)
130
- smartpipe config
130
+ smartpipe use
131
131
 
132
132
  # 2. ask one question across a folder of mixed documents
133
133
  smartpipe map "What does this say about pricing?" 'docs/*.pdf'
@@ -239,7 +239,7 @@ Full docs: **[prabal-rje.github.io/smartpipe][docs]**.
239
239
  - [Install][install] - packages and platforms
240
240
  - [Working with files & media][files] - PDFs, scans, images, audio, video
241
241
  - [CLI reference][cli] - every flag, format, and exit code
242
- - [Models & providers][models] - local Ollama, cloud keys, ChatGPT login
242
+ - [Models & providers][models] - ChatGPT login, cloud keys, local Ollama
243
243
  - [Privacy & security][privacy]
244
244
 
245
245
  ## How to cite
@@ -15,10 +15,10 @@ const LINES: readonly TerminalLine[] = [
15
15
  },
16
16
  { kind: "ord", at: sec(3.2), text: "#1" },
17
17
  { kind: "field", at: sec(3.3), k: "text", v: "Checkout 502 bug …" },
18
- { kind: "field", at: sec(3.4), k: "_score", v: "0.93" },
18
+ { kind: "field", at: sec(3.4), k: "__score", v: "0.93" },
19
19
  { kind: "ord", at: sec(3.9), text: "#2", gap: true },
20
20
  { kind: "field", at: sec(4.0), k: "text", v: "Pay page hangs …" },
21
- { kind: "field", at: sec(4.1), k: "_score", v: "0.88" },
21
+ { kind: "field", at: sec(4.1), k: "__score", v: "0.88" },
22
22
  ];
23
23
 
24
24
  /** Scene 6 — scale B: search the index by meaning. */
@@ -57,8 +57,8 @@ Some tools fit certain jobs better:
57
57
 
58
58
  - **Local model probing, with explicit cloud setup** - if no chat model is configured,
59
59
  smartpipe probes local Ollama first. If it finds no usable model, it stops with
60
- setup instructions. Cloud calls happen only after you choose a cloud model,
61
- profile, or login path.
60
+ setup instructions. Cloud calls happen only after you choose a cloud model or
61
+ login path.
62
62
 
63
63
  - **`grep --color=auto`-style adaptive output** - human view at a terminal, JSONL when piped, with no flag.
64
64
 
@@ -13,8 +13,10 @@ live in [the item](the-item.md); this page is the ingestion mechanics.
13
13
  | ONE binary document (`< report.pdf`) | one whole-document item, spooled and extracted |
14
14
  | an image / audio / video stream | one media item, bytes carried to the model |
15
15
 
16
- Mixed streams are legal; `--strict-rows` (or `SMARTPIPE_STRICT_ROWS=1`) makes
17
- them an error when your pipeline demands one kind.
16
+ Mixed streams are legal in an interactive pipe; `--strict-rows` (or
17
+ `SMARTPIPE_STRICT_ROWS=1`) makes them an error naming the first mixed row,
18
+ and `.sem` runs are strict by default (unattended = loud) - the full story is
19
+ [the granularity ladder](granularity.md).
18
20
 
19
21
  ## Named files
20
22
 
@@ -85,8 +87,14 @@ ingestion made visible, and the front half of the
85
87
  ```bash
86
88
  smartpipe report.pdf | head -1
87
89
  smartpipe notes.txt --as lines | smartpipe write 'copy/{name}'
90
+ # {name} = the source file's name, carried by __source - notes.txt becomes copy/notes.txt
88
91
  ```
89
92
 
93
+ The reader is zero-calls by default. A configured `ocr-model` is the one
94
+ exception: PDFs and images parse through it exactly as the ingesting verbs
95
+ would (disclosed per row; `--max-calls` caps it, and a folder of 20+
96
+ parseable files gets a preflight note before the first call).
97
+
90
98
  ## What rides along
91
99
 
92
100
  Every item carries its provenance in the `__source` spine field (path, cut
@@ -0,0 +1,109 @@
1
+ # The granularity ladder
2
+
3
+ Every pipe starts with one decision: **what is one item?** This page is that
4
+ decision, top to bottom - when each cut applies, how streams end up mixed,
5
+ and what the census and `strict-rows` do about it.
6
+
7
+ ## The ladder
8
+
9
+ From coarsest to finest:
10
+
11
+ | Rung | One item is | You get it from |
12
+ |---|---|---|
13
+ | **file** | a whole file (its extracted text + media) | naming a path, `--as file`, redirecting one document (`< report.pdf`) |
14
+ | **split** | a piece of a file: a page, N tokens, N minutes/seconds | `smartpipe split --by pages/tokens/minutes/seconds` |
15
+ | **lines / rows** | one text line, one JSONL record, one CSV row | piping text in, `.jsonl`/`.csv` paths, `--as lines/jsonl/csv` |
16
+
17
+ Three rules pick the rung when you don't say:
18
+
19
+ 1. **Paths decide the default.** `.jsonl`/`.ndjson` cut into strict records,
20
+ `.csv`/`.tsv` into header-named rows; every other path is one whole-file
21
+ item.
22
+ 2. **stdin sniffs per line.** A line that parses as a JSON object is a
23
+ record; anything else is a text line. One redirected binary document is a
24
+ single whole-file item.
25
+ 3. **`--as` overrides everything.** `--as file` slurps (even stdin);
26
+ `--as lines` keeps every line text, even lines that look like JSON;
27
+ `--as jsonl` demands one record per line, loudly; `--as csv` reads the
28
+ first line as the header.
29
+
30
+ `split` sits between file and lines: it cuts *below* the file into items
31
+ that remember how they were cut (each chunk carries a `__source` spine, so
32
+ `write` can reassemble them in order at the far end).
33
+
34
+ ## When each cut applies
35
+
36
+ - **file** - the unit of meaning is the document: summarize a report,
37
+ caption an image, transcribe a call.
38
+ - **split** - one document is too big, or you want the pieces addressable
39
+ ("page 3 says..."). Media clips cut by minutes/seconds; documents by pages
40
+ or tokens.
41
+ - **lines/rows** - the unit of meaning is the row: logs, exports, JSONL
42
+ datasets. This is where per-item verbs earn their keep.
43
+
44
+ ## How mixing happens
45
+
46
+ Auto mode sniffs stdin per line, so a stream can come out **mixed** - some
47
+ records, some plain text. It happens innocently:
48
+
49
+ - a log file where some lines are JSON events and some are free text,
50
+ - `cat a.jsonl b.txt` gluing two kinds together,
51
+ - a producer that writes headers, blank-ish banners, or progress lines
52
+ between records.
53
+
54
+ Mixing is legal in an interactive pipe. But a verb given both kinds treats
55
+ them differently (a record has fields; a text line only has `text`), so
56
+ silence would lie. Hence the census.
57
+
58
+ ## The census note
59
+
60
+ At end of stream, a mixed pipe gets exactly one stderr note:
61
+
62
+ ```
63
+ note: input: 812 records · 3 plain lines
64
+ ```
65
+
66
+ Nothing fails; the note tells you the stream wasn't what you probably
67
+ thought. Declare a kind to make it go away: `--as jsonl` (records) or
68
+ `--as lines` (text).
69
+
70
+ ## strict-rows
71
+
72
+ When your pipeline *demands* one kind, make mixing an error:
73
+
74
+ - `--strict-rows` on the verb, or
75
+ - `SMARTPIPE_STRICT_ROWS=1` in the environment.
76
+
77
+ Strict mode fails at the **first** mixed row, naming it - before the verb
78
+ sees it, before any model call could spend on it:
79
+
80
+ ```
81
+ error: input: line 4 is a plain text line in a record stream
82
+ --strict-rows demands one kind - declare it: --as jsonl (records) or --as lines (text).
83
+ ```
84
+
85
+ Strictness also covers field misses in the free verbs: `where` errors when
86
+ rows have no fields for a field predicate to read, `summarize` when rows
87
+ lack the `by` field.
88
+
89
+ ### `.sem` runs are strict by default
90
+
91
+ A script runs unattended, and unattended means loud: `smartpipe run x.sem`
92
+ behaves as if `--strict-rows` were set, for single-stage files and every
93
+ pipeline stage alike. Mixed-by-design pipelines opt out in the file:
94
+
95
+ ```toml
96
+ verb = "split"
97
+ strict-rows = false
98
+ ```
99
+
100
+ (per stage or top-level in pipeline files; an explicit CLI flag or
101
+ environment variable still wins). Interactive pipes keep the permissive
102
+ census note. The details live in
103
+ [.sem files - strict rows by default](../reference/sem-files.md#strict-rows-by-default).
104
+
105
+ ## See also
106
+
107
+ - [The item](the-item.md) - the five laws behind all of this
108
+ - [Feeding smartpipe](feeding-smartpipe.md) - the ingestion mechanics table
109
+ - [split](../verbs/split.md) - cutting below the file
@@ -3,18 +3,18 @@
3
3
  ## What's a "model"?
4
4
 
5
5
  A model is the AI that reads your instruction and produces the answer. smartpipe
6
- doesn't contain one - it sends your text to a model running either **locally** (on
7
- your machine, via Ollama) or in the **cloud** (OpenAI, Anthropic, or any
8
- compatible service). You choose which; smartpipe just talks to it.
6
+ doesn't contain one - it sends your text to a model running either in the
7
+ **cloud** (OpenAI, Anthropic, or any compatible service) or **locally** (on
8
+ your machine, via Ollama). You choose which; smartpipe just talks to it.
9
9
 
10
- ## Local vs. cloud
10
+ ## Cloud vs. local
11
11
 
12
- | | Local (Ollama) | Cloud |
12
+ | | Cloud | Local (Ollama) |
13
13
  |---|---|---|
14
- | Cost | Free | Small charge per use |
15
- | Privacy | Nothing leaves your machine when Ollama is local | Text and supported media go to the provider |
16
- | Setup | Install Ollama, pull a model | Get an API key |
17
- | Speed / quality | Depends on your hardware | Usually faster and stronger |
14
+ | Cost | Small charge per use | Free |
15
+ | Privacy | Text and supported media go to the provider | Nothing leaves your machine when Ollama is local |
16
+ | Setup | Log in with ChatGPT, or get an API key | Install Ollama, pull a model |
17
+ | Speed / quality | Usually faster and stronger | Depends on your hardware |
18
18
 
19
19
  With no configured chat model, smartpipe tries local Ollama first. If it finds a
20
20
  non-embedding model, it uses that model and prints the exact `ollama/...` name.
@@ -23,7 +23,7 @@ If no model is configured and no usable Ollama model is found, smartpipe stops w
23
23
  a setup screen. It does not silently fall through to a cloud provider just because
24
24
  a key or login exists.
25
25
 
26
- Once you choose a cloud model, profile, or ChatGPT login path, the relevant item data
26
+ Once you choose a cloud model or ChatGPT login path, the relevant item data
27
27
  for that run goes to that provider. That is an explicit provider choice, not a hidden
28
28
  fallback.
29
29
 
@@ -142,40 +142,39 @@ Example: the table floors Gemini at 128k, but the probe can discover that
142
142
  `SMARTPIPE_CONTEXT_TOKENS=32000` overrides everything. If an estimate is still wrong,
143
143
  `reduce` self-corrects: a rejected chunk is split in half and retried.
144
144
 
145
- ## Profiles: named setups you can switch between (D30)
145
+ ## One command, one coherent setup: `smartpipe use`
146
146
 
147
- A profile bundles the existing config keys (model, embed-model, concurrency,
148
- output) under a name. Three ship built in:
149
-
150
- | Profile | Chat | Embeddings | For |
151
- |---|---|---|---|
152
- | `openai` | gpt-5.4-mini | text-embedding-3-small | cloud preset |
153
- | `gemini` | gemini-3.1-flash-lite | gemini/gemini-embedding-001 | cloud multimodal preset |
154
- | `local` | ollama/gemma-4-e2b | embeddinggemma | local preset when Ollama runs on your machine |
147
+ `smartpipe use` stamps a COMPLETE bundle - a chat model plus the embedder
148
+ that pairs with it - in one command:
155
149
 
156
150
  ```bash
157
- smartpipe config profile # list (the active one marked)
158
- smartpipe config profile local # switch
159
- SMARTPIPE_PROFILE=gemini smartpipe map # one-off, no file change (D24: env is the override)
151
+ smartpipe use # interactive: text model, embeddings, OCR
152
+ smartpipe use gemini # gemini-3.1-flash-lite + gemini-embedding-001
153
+ smartpipe use openai # gpt-5.4-mini + text-embedding-3-small
154
+ smartpipe use ollama # the best installed local model + a local embedder
155
+ smartpipe use gpt-5.4-mini # any model ref: that model + its provider's pairing
160
156
  ```
161
157
 
162
- The cloud presets are **multimodal by default**: they set
163
- `allow-captions = true`, so images and audio convert to text through the
164
- profile's own model when a run needs it (fractions of a cent each, every
165
- conversion disclosed per row). Picking the profile is the consent; the wizard
166
- states this. Bare no-profile setups keep the conservative `--allow-captions`
167
- opt-in.
158
+ A provider whose key is absent refuses with the `smartpipe auth login` fix
159
+ and stamps nothing - never a partial setup. Re-running `use` refreshes the
160
+ whole bundle, which is also the cure for a drifted config.
161
+
162
+ Cloud picks are **multimodal by default**: they stamp `allow-captions = true`,
163
+ so images and audio convert to text through your own model when a run needs
164
+ it (fractions of a cent each, every conversion disclosed per row). Picking
165
+ the cloud setup is the consent; the command says so. Local setups keep the
166
+ conservative `--allow-captions` opt-in.
168
167
 
169
- Create your own as a `[profiles.NAME]` table in the config file (keys: model,
170
- embed-model, concurrency, output, allow-captions). Direct keys beat the active
171
- profile (a direct set is the most recent intent); flags and env vars beat
172
- both. Profiles never hold API keys.
168
+ Every save also writes a receipt at the top of `config.toml` - `# stamped
169
+ by: smartpipe use (…)` - so the file documents how it got that way. (Profiles
170
+ from older versions are retired: their keys load with one warning, are
171
+ ignored, and disappear on the next save.)
173
172
 
174
173
  ## Setting a default
175
174
 
176
175
  ```bash
177
- smartpipe config model ollama/qwen3:8b # save a default
178
- smartpipe config show # see the effective settings + where each comes from
176
+ smartpipe use gpt-5.4-mini # save a default (any provider: smartpipe use ollama works the same)
177
+ smartpipe using # see the effective settings + where each comes from
179
178
  ```
180
179
 
181
180
  Override the default for a single command with `--model`:
@@ -193,16 +192,13 @@ When the same setting is specified more than one way, the most specific wins:
193
192
  --model flag > SMARTPIPE_MODEL env var > config file > Ollama autodetect
194
193
  ```
195
194
 
196
- `smartpipe config show` prints each value with its origin, so you can see which value takes effect.
195
+ `smartpipe using` prints each value with its origin, so you can see which value takes effect.
197
196
 
198
197
  ## Two models: chat and embedding
199
198
 
200
199
  Most verbs use a **chat** model. `embed` and `top_k` use a separate
201
- **embedding** model, configured independently:
202
-
203
- ```bash
204
- smartpipe config embed-model nomic-embed-text
205
- ```
200
+ **embedding** model, configured independently - the embeddings stage of
201
+ `smartpipe use` sets it (or edit `embed-model` in `config.toml` directly).
206
202
 
207
203
  ## See also
208
204
 
@@ -212,7 +208,8 @@ smartpipe config embed-model nomic-embed-text
212
208
 
213
209
  ## The stt-model role
214
210
 
215
- `smartpipe config stt-model openai/whisper-1` names a dedicated remote
211
+ The `stt-model` config key (e.g. `stt-model = "openai/whisper-1"` in
212
+ `config.toml`) names a dedicated remote
216
213
  transcriber. When set, it runs FIRST in the audio ladder (a configured
217
214
  transcriber signals wanting verbatim text - LLM hearing paraphrases),
218
215
  falling back to the LLM rung and local `whisper` on failure. It is a paid
@@ -233,7 +230,7 @@ account. Only the `openai` wire exists today; the key accepts
233
230
 
234
231
  ## The ocr-model role
235
232
 
236
- `smartpipe config ocr-model mistral-ocr-latest` names a dedicated document
233
+ The `ocr-model` config key - the OCR stage of `smartpipe use` sets it - names a dedicated document
237
234
  parser. When set, ingested PDFs and images run through it instead of the
238
235
  local extraction ladder - page markdown becomes the item text, and a
239
236
  multi-page PDF becomes one item per page (the `__source` spine carries the
@@ -249,7 +246,7 @@ The role is provider-agnostic:
249
246
  - A **mistral** ref rides the dedicated `/v1/ocr` wire (needs
250
247
  `MISTRAL_API_KEY`; the endpoint charges per page).
251
248
  - **Any other ref** reads pages through the normal chat-vision wire with an
252
- extract-the-text framing - `smartpipe config ocr-model ollama/llava` is a
249
+ extract-the-text framing - `ocr-model = "ollama/llava"` is a
253
250
  free local OCR. For PDFs on this rung, pages with a healthy text layer
254
251
  keep their locally extracted text (zero calls); only thin, image-bearing
255
252
  pages (scans) go through the model.
@@ -262,7 +259,8 @@ ladder with a note - never a hard stop. `--ocr-model` (per run) >
262
259
 
263
260
  ## The media-embed-model role
264
261
 
265
- `smartpipe config media-embed-model jina/jina-clip-v2` names a JOINT
262
+ The `media-embed-model` config key (e.g. `media-embed-model =
263
+ "jina/jina-clip-v2"` in `config.toml`) names a JOINT
266
264
  text+image embedder. When set, `embed` and `top_k` route media items to it
267
265
  as pixels while text items keep using `embed-model` - and a text query can
268
266
  rank an image corpus, because both live in the same space.
@@ -76,9 +76,15 @@ The rules that make it a real table:
76
76
  - **CSV is RFC 4180** (proper quoting, CRLF line endings); **TSV** uses tabs, and
77
77
  replaces any tab or newline inside a value with a space (a tab inside a TSV cell
78
78
  would corrupt the columns).
79
- - **`top_k` scores land last.** A `_score` column sorts to the right of your data,
79
+ - **`top_k` scores land last.** A `__score` column sorts to the right of your data,
80
80
  where a spreadsheet reader expects it.
81
81
 
82
+ > **Migrating from pre-1.4:** `top_k` and `outliers` used to write `_score`
83
+ > (and `_rank`/`_snapshot`/`_distance`) with a single underscore. Those stamps
84
+ > now live in the reserved `__` namespace - update your `jq`/`sort --by`
85
+ > references to `__score` etc. The old spellings are still read for one
86
+ > release (they keep sorting last in CSV/TSV), but are no longer written.
87
+
82
88
  CSV and TSV need **structured** output - there have to be named columns. Ask for
83
89
  fields with braces or `--schema`; a plain-text prompt with `--output csv` is a
84
90
  usage error that tells you so.