dirsql 0.4.14__tar.gz → 0.4.16__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.
- {dirsql-0.4.14 → dirsql-0.4.16}/Cargo.lock +1 -1
- {dirsql-0.4.14 → dirsql-0.4.16}/PKG-INFO +2 -1
- dirsql-0.4.16/dirsql/cli/main.py +66 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/.vitepress/config.ts +0 -1
- {dirsql-0.4.14/packages/rust → dirsql-0.4.16}/docs/howto/extract-from-contents.md +0 -2
- {dirsql-0.4.14/packages/rust → dirsql-0.4.16}/docs/howto/load-extension.md +0 -2
- {dirsql-0.4.14/packages/rust → dirsql-0.4.16}/docs/howto/write-a-plugin.md +15 -43
- {dirsql-0.4.14/packages/rust → dirsql-0.4.16}/docs/plugins.md +4 -27
- {dirsql-0.4.14/packages/python → dirsql-0.4.16}/docs/reference/cli.md +3 -4
- {dirsql-0.4.14/packages/rust → dirsql-0.4.16}/docs/reference/config.md +5 -15
- {dirsql-0.4.14/packages/rust → dirsql-0.4.16}/docs/reference/hooks.md +14 -52
- {dirsql-0.4.14/packages/rust → dirsql-0.4.16}/docs/reference/http-api.md +2 -11
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/Cargo.toml +5 -2
- dirsql-0.4.16/packages/python/changelog.d/2026-08-04-cli-in-process.md +3 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/.vitepress/config.ts +0 -1
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/howto/extract-from-contents.md +0 -2
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/howto/load-extension.md +0 -2
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/howto/write-a-plugin.md +15 -43
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/plugins.md +4 -27
- {dirsql-0.4.14/packages/rust → dirsql-0.4.16/packages/python}/docs/reference/cli.md +3 -4
- {dirsql-0.4.14 → dirsql-0.4.16/packages/python}/docs/reference/config.md +5 -15
- {dirsql-0.4.14 → dirsql-0.4.16/packages/python}/docs/reference/hooks.md +14 -52
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/reference/http-api.md +2 -11
- dirsql-0.4.16/packages/python/e2e-attestations/claude-737-cli-run-shim.json +7 -0
- dirsql-0.4.16/packages/python/e2e-attestations/claude-738-pypi-in-process.json +7 -0
- dirsql-0.4.16/packages/python/e2e-attestations/claude-739-npm-in-process.json +7 -0
- dirsql-0.4.16/packages/python/e2e-attestations/claude-803-remove-query-hooks.json +7 -0
- dirsql-0.4.16/packages/python/migrations.d/2026-08-04-cli-in-process.md +63 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/src/lib.rs +21 -0
- dirsql-0.4.16/packages/rust/changelog.d/2026-08-04-cli-run-shim.md +3 -0
- dirsql-0.4.16/packages/rust/changelog.d/2026-08-10-remove-query-hooks.md +3 -0
- {dirsql-0.4.14 → dirsql-0.4.16/packages/rust}/docs/howto/extract-from-contents.md +0 -2
- {dirsql-0.4.14 → dirsql-0.4.16/packages/rust}/docs/howto/load-extension.md +0 -2
- {dirsql-0.4.14 → dirsql-0.4.16/packages/rust}/docs/howto/write-a-plugin.md +15 -43
- {dirsql-0.4.14 → dirsql-0.4.16/packages/rust}/docs/plugins.md +4 -27
- {dirsql-0.4.14 → dirsql-0.4.16/packages/rust}/docs/reference/cli.md +3 -4
- {dirsql-0.4.14/packages/python → dirsql-0.4.16/packages/rust}/docs/reference/config.md +5 -15
- {dirsql-0.4.14/packages/python → dirsql-0.4.16/packages/rust}/docs/reference/hooks.md +14 -52
- {dirsql-0.4.14 → dirsql-0.4.16/packages/rust}/docs/reference/http-api.md +2 -11
- dirsql-0.4.16/packages/rust/migrations.d/2026-08-10-remove-query-hooks.md +47 -0
- dirsql-0.4.16/packages/rust/src/bin/dirsql.rs +46 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/cli/execute.rs +16 -139
- dirsql-0.4.16/packages/rust/src/cli/mod.rs +200 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/cli/router.rs +3 -19
- dirsql-0.4.14/packages/rust/src/bin/dirsql.rs → dirsql-0.4.16/packages/rust/src/cli/run.rs +142 -146
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/cli/server.rs +0 -2
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/command.rs +4 -5
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/config.rs +26 -156
- {dirsql-0.4.14 → dirsql-0.4.16}/pyproject.toml +7 -6
- dirsql-0.4.14/dirsql/cli/binary_path.py +0 -23
- dirsql-0.4.14/dirsql/cli/is_windows.py +0 -9
- dirsql-0.4.14/dirsql/cli/main.py +0 -42
- dirsql-0.4.14/docs/howto/search-by-meaning.md +0 -153
- dirsql-0.4.14/packages/python/docs/howto/search-by-meaning.md +0 -153
- dirsql-0.4.14/packages/rust/docs/howto/search-by-meaning.md +0 -153
- dirsql-0.4.14/packages/rust/src/cli/mod.rs +0 -364
- {dirsql-0.4.14 → dirsql-0.4.16}/Cargo.toml +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/README.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/__init__.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/_async.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/cli/discover_plugins/__init__.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/cli/discover_plugins/discovered_fragments.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/cli/discover_plugins/discovery_disabled.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/cli/discover_plugins/fragment_path.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/cli/discover_plugins/user_passed_config.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/cli/discover_plugins/with_discovered_plugins.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/cli/resolve_config_extensions.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/py.typed +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/resolve_config_extensions.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/dirsql/resolve_extension.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/AGENTS.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/explanation.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/getting-started.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/howto/embed.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/howto/persist.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/index.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/migrations.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/package.json +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/reference/columns.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/docs/reference/sdk.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/CHANGELOG.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/MIGRATIONS.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/README.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-07-13-plugin-discovery.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-07-13-repeatable-config.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-08-02-release-profile.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-08-02-scan-failures.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-08-03-discovery-ext-resolution.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-08-03-manylinux-dynamic-binary.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-08-03-python-no-ignore.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/2026-08-04-cast-lints.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/changelog.d/README.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/conftest.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/explanation.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/howto/embed.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/howto/persist.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/index.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/migrations.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/package.json +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/reference/columns.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/docs/reference/sdk.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/e2e-attestations/chore-766-narrow-pedantic.json +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/e2e-attestations/claude-772-extension-without-config.json +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/migrations.d/2026-07-29-restore-python-310.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/migrations.d/README.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/__init__.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/tests/e2e/fixtures/dirsql_plugin_fixture/dirsql.toml +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/tests/integration/binding/__init__.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/python/tests/integration/hermetic/__init__.py +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/CHANGELOG.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/Cargo.toml +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/MIGRATIONS.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/README.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-13-batch-ingest-transaction.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-13-chained-pre-post-query-hooks.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-13-fan-out-file-table-matching.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-13-persist-wal.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-13-repeatable-builder-config.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-13-repeatable-cli-config.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-13-subcommand-local-config-flags.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-19-path-table-query-fallback.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-19-path-table-vtab.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-20-path-table-glob-semantics.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-20-schema-inference.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-21-on-file-flag.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-23-init-escalation-example.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-23-query-default-cli.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-07-29-on-file-failures-accumulate.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-08-02-drop-regex.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-08-02-per-file-scan-failures.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-08-02-release-profile.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-08-03-gitignore-by-default.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-08-03-nested-default-ignores.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-08-04-cast-lints.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/2026-08-04-configless-extension.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/changelog.d/README.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/explanation.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/howto/define-tables.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/howto/embed.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/howto/parse-files-into-columns.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/howto/persist.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/howto/query-without-config.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/howto/skip-files.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/index.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/migrations.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/reference/columns.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/reference/path-tables.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/docs/reference/sdk.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-07-13-drop-cwd-config-auto-detect.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-07-13-fan-out-file-table-matching.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-07-13-persist-wal.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-07-13-rename-extract-to-on-file.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-07-13-sdk-default-baked-in-config.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-07-13-subcommand-local-config-flags.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-07-20-drop-implicit-files-table.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-07-20-path-table-glob-semantics.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-07-21-remove-glob-captures.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-07-23-init-escalation-example.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-07-23-query-default-cli.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-07-24-hookless-table-config-error.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-07-24-remove-stat-fact-injection.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-08-02-per-file-scan-failures.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-08-03-gitignore-by-default.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/2026-08-03-nested-default-ignores.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/migrations.d/README.md +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/db.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/default_config.toml +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/infer.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/lib.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/parsed_vtab.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/path_table.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/persist.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/scanner.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/vtab.rs +0 -0
- {dirsql-0.4.14 → dirsql-0.4.16}/packages/rust/src/watcher.rs +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dirsql
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.16
|
|
4
4
|
Requires-Dist: tomli>=2 ; python_full_version < '3.11'
|
|
5
|
+
Requires-Dist: bin-shim>=0.1
|
|
5
6
|
Summary: Ephemeral SQL index over a local directory
|
|
6
7
|
Keywords: sql,filesystem,directory,sqlite,index
|
|
7
8
|
Author: Kevin Scott
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Console-script entry point. Runs the CLI in-process through the compiled
|
|
2
|
+
extension module — the same `_dirsql` the SDK imports — so the wheel ships one
|
|
3
|
+
copy of the core instead of a `.so` plus a bundled binary (#738).
|
|
4
|
+
|
|
5
|
+
All argv is forwarded transparently to the core, which owns subcommand
|
|
6
|
+
dispatch; the launcher only prepends what the core cannot work out for itself
|
|
7
|
+
(plugin config fragments, resolved extension paths).
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import signal
|
|
13
|
+
import sys
|
|
14
|
+
|
|
15
|
+
from bin_shim import main as run_in_process
|
|
16
|
+
|
|
17
|
+
from .discover_plugins.with_discovered_plugins import with_discovered_plugins
|
|
18
|
+
from .resolve_config_extensions import with_resolved_extensions
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _absorb_interrupt(*_args: object) -> None:
|
|
22
|
+
"""Let the core's own shutdown decide the exit code on SIGINT.
|
|
23
|
+
|
|
24
|
+
signal-hook (which tokio uses) *chains*: it runs tokio's handler — which
|
|
25
|
+
drives `dirsql server`'s graceful shutdown, after which `run_cli` returns
|
|
26
|
+
0 — and then whatever handler was installed before it. CPython's default
|
|
27
|
+
is `default_int_handler`, which raises `KeyboardInterrupt`; that lands
|
|
28
|
+
after `run_cli` has already returned 0 and turns a clean shutdown into a
|
|
29
|
+
130. This handler occupies that slot without raising, so the core's exit
|
|
30
|
+
code is the one that survives, exactly as it does when the CLI is its own
|
|
31
|
+
process.
|
|
32
|
+
|
|
33
|
+
A signal arriving when the core is NOT handling signals still terminates:
|
|
34
|
+
`run_cli` is only reached with this installed, and it returns promptly for
|
|
35
|
+
every non-server command.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def with_core_owned_signals(handler=signal.signal):
|
|
40
|
+
"""Install `_absorb_interrupt` for SIGINT and return the prior handler."""
|
|
41
|
+
return handler(signal.SIGINT, _absorb_interrupt)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def main(argv: list[str] | None = None) -> int:
|
|
45
|
+
if argv is None:
|
|
46
|
+
argv = sys.argv[1:]
|
|
47
|
+
|
|
48
|
+
# Discover installed plugins (CLI only) and inject their config fragments as
|
|
49
|
+
# `-c` flags before resolving extensions; then resolve any package-name
|
|
50
|
+
# extensions in a TOML config here (the core can't) as `--extension`
|
|
51
|
+
# flags. Both are no-ops when nothing applies.
|
|
52
|
+
try:
|
|
53
|
+
argv = with_discovered_plugins(argv)
|
|
54
|
+
argv = with_resolved_extensions(argv)
|
|
55
|
+
except Exception as exc:
|
|
56
|
+
print(f"dirsql: {exc}", file=sys.stderr)
|
|
57
|
+
return 1
|
|
58
|
+
|
|
59
|
+
previous = with_core_owned_signals()
|
|
60
|
+
try:
|
|
61
|
+
return run_in_process(argv=argv, module="dirsql._dirsql")
|
|
62
|
+
except Exception as exc:
|
|
63
|
+
print(f"dirsql: {exc}", file=sys.stderr)
|
|
64
|
+
return 1
|
|
65
|
+
finally:
|
|
66
|
+
signal.signal(signal.SIGINT, previous)
|
|
@@ -54,7 +54,6 @@ export default defineConfig({
|
|
|
54
54
|
{ text: 'Derive columns from file paths', link: '/howto/columns-from-paths' },
|
|
55
55
|
{ text: 'Extract rows from file contents', link: '/howto/extract-from-contents' },
|
|
56
56
|
{ text: 'Parse your files into columns', link: '/howto/parse-files-into-columns' },
|
|
57
|
-
{ text: 'Search documents by meaning', link: '/howto/search-by-meaning' },
|
|
58
57
|
{ text: "Skip files you don't want indexed", link: '/howto/skip-files' },
|
|
59
58
|
{ text: 'Load a SQLite extension', link: '/howto/load-extension' },
|
|
60
59
|
{ text: 'Keep the index across restarts', link: '/howto/persist' },
|
|
@@ -79,8 +79,6 @@ SQLite value mapping is under
|
|
|
79
79
|
|
|
80
80
|
- The command re-runs on every startup and on every change to a matched
|
|
81
81
|
file. If it is expensive, [keep the index across restarts](./persist.md).
|
|
82
|
-
- The flagship use of `on-file` — computing embeddings — is
|
|
83
|
-
[Search documents by meaning](./search-by-meaning.md).
|
|
84
82
|
- Embedding `dirsql` in a program instead? The SDK's `on_file` callback
|
|
85
83
|
fills the same role in-process — see
|
|
86
84
|
[Embed `dirsql` in your application](./embed.md).
|
|
@@ -85,5 +85,3 @@ interpreter to resolve package names with
|
|
|
85
85
|
- Embedding `dirsql` in a program? The SDK constructor takes the same
|
|
86
86
|
specs via its `extensions` parameter
|
|
87
87
|
([SDK reference](../reference/sdk.md#constructor)).
|
|
88
|
-
- The payoff use case — `sqlite-vec` powering semantic search — is
|
|
89
|
-
[Search documents by meaning](./search-by-meaning.md).
|
|
@@ -24,8 +24,7 @@ dirsql-embeddings/
|
|
|
24
24
|
└── dirsql_embeddings/
|
|
25
25
|
├── __init__.py
|
|
26
26
|
├── dirsql.toml # the config fragment
|
|
27
|
-
|
|
28
|
-
└── search.py # pre-query hook
|
|
27
|
+
└── embed.py # on-file hook
|
|
29
28
|
```
|
|
30
29
|
|
|
31
30
|
The entry point maps a **source label** (the name) to the **module that
|
|
@@ -55,8 +54,7 @@ structurally **identical to a user config**. It may declare
|
|
|
55
54
|
[`[[table]]`](../reference/config.md#table) (with
|
|
56
55
|
[`on-file`](../reference/hooks.md#on-file)),
|
|
57
56
|
[`[[dirsql.extension]]`](../reference/config.md#dirsql-extension),
|
|
58
|
-
[`ignore`](../reference/config.md#dirsql-keys),
|
|
59
|
-
[`pre-query`/`post-query`](../reference/hooks.md#pre-query), and
|
|
57
|
+
[`ignore`](../reference/config.md#dirsql-keys), and
|
|
60
58
|
[`hook-timeout`](../reference/hooks.md#timeout).
|
|
61
59
|
|
|
62
60
|
There are **no plugin-specific keys and no plugin-specific restrictions**. The
|
|
@@ -96,17 +94,14 @@ matter most for a published plugin:
|
|
|
96
94
|
## Worked example: an embeddings plugin
|
|
97
95
|
|
|
98
96
|
Here is the whole plugin — vector search over a directory of notes, buildable
|
|
99
|
-
in about
|
|
100
|
-
[Search documents by meaning](./search-by-meaning.md): the
|
|
97
|
+
in about forty lines. It composes two pieces: the
|
|
101
98
|
[`sqlite-vec`](https://github.com/asg017/sqlite-vec) extension for the
|
|
102
|
-
distance math, an `on-file` command to embed each file
|
|
103
|
-
command to embed the question.
|
|
99
|
+
distance math, and an `on-file` command to embed each file.
|
|
104
100
|
|
|
105
101
|
The fragment, `src/dirsql_embeddings/dirsql.toml`:
|
|
106
102
|
|
|
107
103
|
```toml
|
|
108
104
|
[dirsql]
|
|
109
|
-
pre-query = "uv run --with model2vec python search.py {args}"
|
|
110
105
|
hook-timeout = 300 # headroom for the first-run model download
|
|
111
106
|
|
|
112
107
|
[[dirsql.extension]]
|
|
@@ -140,46 +135,23 @@ row = {"path": os.path.relpath(path, root), "text": text,
|
|
|
140
135
|
print(json.dumps([row]))
|
|
141
136
|
```
|
|
142
137
|
|
|
143
|
-
`
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
import sys
|
|
149
|
-
|
|
150
|
-
from model2vec import StaticModel
|
|
151
|
-
|
|
152
|
-
body = json.loads(sys.argv[1])
|
|
153
|
-
model = StaticModel.from_pretrained("minishlab/potion-base-8M")
|
|
154
|
-
vector = model.encode([body["q"]])[0]
|
|
155
|
-
needle = json.dumps([round(float(x), 6) for x in vector])
|
|
156
|
-
print(
|
|
157
|
-
"SELECT path, ROUND(vec_distance_cosine(embedding, '%s'), 3) AS distance "
|
|
158
|
-
"FROM notes ORDER BY distance LIMIT 3" % needle
|
|
159
|
-
)
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
::: warning The hook owns SQL safety
|
|
163
|
-
Whatever SQL `pre-query` prints is executed as-is. Here the interpolated
|
|
164
|
-
value is a numeric vector the script itself produced; never splice raw request
|
|
165
|
-
text into SQL. See [`pre-query`](../reference/hooks.md#pre-query).
|
|
166
|
-
:::
|
|
167
|
-
|
|
168
|
-
The relative `embed.py` / `search.py` above resolve against the fragment
|
|
169
|
-
directory, which is convenient during development. For a published plugin,
|
|
170
|
-
promote them to console scripts (`[project.scripts]` → `embed-file`,
|
|
171
|
-
`embed-search`) so the commands carry their own interpreter and dependencies
|
|
172
|
-
and no longer depend on `uv run --with`.
|
|
138
|
+
The relative `embed.py` above resolves against the fragment directory, which
|
|
139
|
+
is convenient during development. For a published plugin, promote it to a
|
|
140
|
+
console script (`[project.scripts]` → `embed-file`) so the command carries
|
|
141
|
+
its own interpreter and dependencies and no longer depends on
|
|
142
|
+
`uv run --with`.
|
|
173
143
|
|
|
174
144
|
Once the package is installed alongside the launcher, its `notes` table is
|
|
175
145
|
queryable with no config edits:
|
|
176
146
|
|
|
177
147
|
```bash
|
|
178
|
-
uvx --with dirsql-embeddings dirsql query
|
|
148
|
+
uvx --with dirsql-embeddings dirsql query \
|
|
149
|
+
"SELECT path FROM notes ORDER BY vec_distance_cosine(embedding, '[0.1, ...]') LIMIT 3"
|
|
179
150
|
```
|
|
180
151
|
|
|
181
152
|
The launcher discovers the installed plugin, composes its fragment, and the
|
|
182
|
-
`
|
|
153
|
+
`notes` table (with `vec_distance_cosine()` from the loaded extension) is
|
|
154
|
+
available to the query.
|
|
183
155
|
|
|
184
156
|
## SDK-style convention: expose the config
|
|
185
157
|
|
|
@@ -230,8 +202,8 @@ Discovery is deliberately narrow. Know exactly who does what:
|
|
|
230
202
|
[convention above](#sdk-style-convention-expose-the-config)).
|
|
231
203
|
- **Name collisions are a hard error.** Because fragments compose like any
|
|
232
204
|
[multiple configs](../reference/config.md#composing-multiple-configs), two
|
|
233
|
-
plugins (or a plugin and your config) defining a table of the same name
|
|
234
|
-
|
|
205
|
+
plugins (or a plugin and your config) defining a table of the same name
|
|
206
|
+
fail loudly, naming the conflict. It is never a silent
|
|
235
207
|
last-writer-wins.
|
|
236
208
|
|
|
237
209
|
::: warning Config flags are subcommand-local
|
|
@@ -22,10 +22,6 @@ question into nearest-neighbor SQL over that table, ranked by
|
|
|
22
22
|
[PyPI](https://pypi.org/project/dirsql-plugin-embeddings/) ·
|
|
23
23
|
[Source](https://github.com/thekevinscott/dirsql/tree/main/plugins/dirsql-plugin-embeddings)
|
|
24
24
|
|
|
25
|
-
It is the packaged form of the
|
|
26
|
-
[Search documents by meaning](./howto/search-by-meaning.md) how-to, with that
|
|
27
|
-
guide's local `model2vec` model swapped for a hosted endpoint.
|
|
28
|
-
|
|
29
25
|
### Install and launch
|
|
30
26
|
|
|
31
27
|
The plugin is a normal PyPI package; installing it alongside `dirsql` is the
|
|
@@ -43,29 +39,10 @@ uvx --with dirsql-plugin-embeddings dirsql server
|
|
|
43
39
|
|
|
44
40
|
The launcher finds the package through its `dirsql` entry point and injects
|
|
45
41
|
the shipped `dirsql.toml` fragment as an ordinary `-c` flag, composed after
|
|
46
|
-
your own configs. The fragment declares
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
- the `documents` table (`path`, `text`, `embedding`), whose
|
|
51
|
-
[`on-file`](./reference/hooks.md#on-file) hook embeds each matched file at
|
|
52
|
-
index time;
|
|
53
|
-
- a [`pre-query`](./reference/hooks.md#pre-query) hook that embeds each
|
|
54
|
-
incoming question and emits the nearest-neighbor SQL, plus a 300-second
|
|
55
|
-
[`hook-timeout`](./reference/config.md#dirsql-keys) so slow embedding calls
|
|
56
|
-
don't hit the 30-second default.
|
|
57
|
-
|
|
58
|
-
Ask a question as a `{"q": …}` body — via `POST /query` against the server,
|
|
59
|
-
or in one shot from the shell:
|
|
60
|
-
|
|
61
|
-
```sh
|
|
62
|
-
uvx --with dirsql-plugin-embeddings \
|
|
63
|
-
dirsql query '{"q": "how do I cook spaghetti?"}'
|
|
64
|
-
# [{"path":"pasta.md","distance":0.113}, …]
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
The result is the three nearest documents, closest first. Discovery can be
|
|
68
|
-
turned off per-invocation with `--no-plugin` or `DIRSQL_NO_PLUGIN=1`
|
|
42
|
+
your own configs. The fragment declares the `sqlite-vec` extension (resolved
|
|
43
|
+
from the installed `sqlite-vec` package, which the plugin depends on), so
|
|
44
|
+
`vec_distance_cosine()` is callable in queries. Discovery can be turned off
|
|
45
|
+
per-invocation with `--no-plugin` or `DIRSQL_NO_PLUGIN=1`
|
|
69
46
|
([reference](./reference/cli.md#plugins)).
|
|
70
47
|
|
|
71
48
|
### Configuration
|
|
@@ -78,8 +78,8 @@ Config flags are subcommand-local: pass them after `server`
|
|
|
78
78
|
|
|
79
79
|
- Per-query timeout: **30 seconds**. A query exceeding it returns
|
|
80
80
|
`408 Request Timeout`.
|
|
81
|
-
-
|
|
82
|
-
|
|
81
|
+
- `on-file` command hooks default to a **30-second** timeout each,
|
|
82
|
+
overridable with the config key
|
|
83
83
|
[`[dirsql].hook-timeout`](./config.md#dirsql-keys).
|
|
84
84
|
|
|
85
85
|
### Configless mode
|
|
@@ -166,8 +166,7 @@ uses**, so behavior is identical to `POST /query` by construction:
|
|
|
166
166
|
(`--persist=/path`) so it does not swallow the SQL argument.
|
|
167
167
|
- **`--no-ignore`** is honored: path-tables in the query scan files a
|
|
168
168
|
`.gitignore` would hide. See [Skip rules](./path-tables.md#skip-rules).
|
|
169
|
-
-
|
|
170
|
-
[`post-query`](./hooks.md#post-query)) and the
|
|
169
|
+
- **`on-file` hooks** and the
|
|
171
170
|
[`[dirsql].hook-timeout`](./config.md#dirsql-keys) apply identically.
|
|
172
171
|
- The **30-second query timeout**, the **read-only rule**, and the
|
|
173
172
|
`_dirsql_*` **internal-table denial** apply identically. A rejected read
|
|
@@ -23,9 +23,7 @@ the config file's location. See [`--config`](./cli.md#flags).
|
|
|
23
23
|
| Key | Type | Default | Description |
|
|
24
24
|
|---|---|---|---|
|
|
25
25
|
| `ignore` | array of strings | `[]` | Glob patterns matched against root-relative paths. Matched files are skipped entirely — excluded from the initial scan and from watch events. |
|
|
26
|
-
| `
|
|
27
|
-
| `post-query` | string | none | Server-wide command hook: each successful `POST /query` result set is handed to this command (as a JSON array on stdin, and as `{args}` up to 96 KiB), and the JSON body it prints is returned instead of the bare row array. CLI server only; the SDKs ignore it. Must be non-empty. See [Command hooks](./hooks.md#post-query). |
|
|
28
|
-
| `hook-timeout` | integer (seconds) | `30` | One global per-run timeout for every command hook — `on-file`, `pre-query`, and `post-query` alike. Positive whole seconds; zero and negative values are a config error. See [Command hooks](./hooks.md#timeout). |
|
|
26
|
+
| `hook-timeout` | integer (seconds) | `30` | One global per-run timeout for every `on-file` command hook run. Positive whole seconds; zero and negative values are a config error. See [Command hooks](./hooks.md#timeout). |
|
|
29
27
|
|
|
30
28
|
The top-level `.dirsql/` directory under the root is always excluded from
|
|
31
29
|
scanning, whether or not it appears in `ignore` — it is reserved for
|
|
@@ -147,15 +145,10 @@ The configs load and merge in **argv order**:
|
|
|
147
145
|
|
|
148
146
|
- **`[[table]]`, `ignore`, and `[[dirsql.extension]]` entries accumulate** across
|
|
149
147
|
all configs, in order.
|
|
150
|
-
- **Each config's `on-file
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
wherever it lives.
|
|
155
|
-
- **`pre-query` / `post-query` hooks chain FIFO**: the request body flows through
|
|
156
|
-
each `pre-query` stage in order to the final SQL, and the result rows flow
|
|
157
|
-
through each `post-query` stage to the response. See the
|
|
158
|
-
[hook contract](./hooks.md).
|
|
148
|
+
- **Each config's `on-file` hooks run from that config file's own
|
|
149
|
+
directory**, under that config's own [`hook-timeout`](#dirsql-keys) — so a
|
|
150
|
+
relative command like `on-file = "sh ./extract.sh"` resolves against the
|
|
151
|
+
config that declared it, wherever it lives.
|
|
159
152
|
- Each config is **validated on its own** (the [parse errors](#parse-errors)
|
|
160
153
|
below apply per file). There is no cross-file merge validation, with one
|
|
161
154
|
structural exception: **two configs defining a table of the same name is an
|
|
@@ -181,7 +174,6 @@ SDKs raise/reject) when:
|
|
|
181
174
|
> `[[table]] '**/*.md' has no on-file hook, so every row would be all-NULL. Add an `on-file` hook that emits the columns, or, for stat columns with no code, query the path directly: `FROM './'``
|
|
182
175
|
|
|
183
176
|
- A `[[dirsql.extension]]` entry omits `path`, or `path` is empty.
|
|
184
|
-
- `pre-query` or `post-query` is present but empty/whitespace.
|
|
185
177
|
- `hook-timeout` is zero or negative.
|
|
186
178
|
|
|
187
179
|
## Full example
|
|
@@ -189,8 +181,6 @@ SDKs raise/reject) when:
|
|
|
189
181
|
```toml
|
|
190
182
|
[dirsql]
|
|
191
183
|
ignore = ["node_modules/**", ".git/**", "dist/**"]
|
|
192
|
-
pre-query = "uv run python to_sql.py {args}"
|
|
193
|
-
post-query = "jq -c '{results: .}'"
|
|
194
184
|
hook-timeout = 120
|
|
195
185
|
|
|
196
186
|
[[dirsql.extension]]
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Command hooks
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
The `on-file` [config key](./config.md) (per `[[table]]`, also available as
|
|
4
|
+
the [`--on-file` flag](./cli.md#on-file-command) on `dirsql query`) runs an
|
|
5
|
+
external command under the execution contract below.
|
|
6
6
|
|
|
7
7
|
## Execution contract
|
|
8
8
|
|
|
@@ -32,8 +32,8 @@ occurrence, within whole argv tokens, in a single left-to-right pass:
|
|
|
32
32
|
`{…}` is inert.
|
|
33
33
|
- An unrecognized `{…}` is left literal.
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
[
|
|
35
|
+
The available placeholders are listed under the
|
|
36
|
+
[`on-file` contract](#on-file-contract) below.
|
|
37
37
|
|
|
38
38
|
### Working directory and environment
|
|
39
39
|
|
|
@@ -62,7 +62,7 @@ compactly on one line.
|
|
|
62
62
|
|
|
63
63
|
Every hook run is bounded by a **30-second** default timeout. A run
|
|
64
64
|
exceeding it is killed and treated as a failure. One global config key
|
|
65
|
-
raises (or tightens) the bound
|
|
65
|
+
raises (or tightens) the bound:
|
|
66
66
|
|
|
67
67
|
```toml
|
|
68
68
|
[dirsql]
|
|
@@ -80,19 +80,16 @@ A hook run fails when the command:
|
|
|
80
80
|
stderr tail are reported),
|
|
81
81
|
- exceeds the timeout (killed; stderr tail reported),
|
|
82
82
|
- exits zero but prints no non-empty stdout line,
|
|
83
|
-
- or
|
|
83
|
+
- or prints output that does not parse as a JSON array of row objects.
|
|
84
84
|
|
|
85
|
-
What a failure *means
|
|
85
|
+
What a failure *means*: **per-file isolation.** The file contributes no rows
|
|
86
|
+
and is reported as skipped; the scan indexes every other file and commits.
|
|
87
|
+
The CLI names up to ten skipped files on stderr, then `... and N more`, and
|
|
88
|
+
exits `23` — distinct from `0` (clean) and `1` (the run failed), so a caller
|
|
89
|
+
can tell a partial index from a complete one. A row the table rejects under
|
|
90
|
+
`strict` counts as the same kind of failure.
|
|
86
91
|
|
|
87
|
-
|
|
88
|
-
|---|---|
|
|
89
|
-
| `on-file` | **Per-file isolation.** The file contributes no rows and is reported as skipped; the scan indexes every other file and commits. The CLI names up to ten skipped files on stderr, then `... and N more`, and exits `23` — distinct from `0` (clean) and `1` (the run failed), so a caller can tell a partial index from a complete one. A row the table rejects under `strict` counts as the same kind of failure. |
|
|
90
|
-
| `pre-query` | The request returns `500 Internal Server Error` with the command's stderr tail in the JSON `error` body. |
|
|
91
|
-
| `post-query` | The request returns `500 Internal Server Error` with the command's stderr tail (or, for unparseable output, `post-query did not return valid JSON: <err>`) in the JSON `error` body. |
|
|
92
|
-
|
|
93
|
-
## Per-hook contracts
|
|
94
|
-
|
|
95
|
-
### `on-file`
|
|
92
|
+
## `on-file` contract
|
|
96
93
|
|
|
97
94
|
Runs once per file matched by the table's `glob`, at initial scan and on
|
|
98
95
|
every watched change. The command reads the file itself and prints a JSON
|
|
@@ -114,38 +111,3 @@ the path or stat metadata emits it (it has `{path}`).
|
|
|
114
111
|
|---|---|
|
|
115
112
|
| `{path}` | The matched file's **absolute** path. `on-file = "extract.py {path}"` — self-sufficient from any working directory, so the command resolves it even when the config lives outside the index. |
|
|
116
113
|
| `{root}` | The index root directory. Derive a root-relative path with `relpath({path}, {root})`. |
|
|
117
|
-
|
|
118
|
-
### `pre-query`
|
|
119
|
-
|
|
120
|
-
Runs once per `POST /query` request, before the query. The raw request body
|
|
121
|
-
goes in; plain-text SQL comes out (the stdout payload line). `dirsql` runs
|
|
122
|
-
that SQL and returns rows as usual. With no `pre-query` key, the body is
|
|
123
|
-
parsed as `{"sql": …}` instead — see [HTTP API](./http-api.md#post-query).
|
|
124
|
-
|
|
125
|
-
| Placeholder | Value |
|
|
126
|
-
|---|---|
|
|
127
|
-
| `{args}` | The raw `POST /query` request body, verbatim, as one argv token. |
|
|
128
|
-
|
|
129
|
-
**The hook owns SQL safety.** The `{args}` substitution keeps the untrusted
|
|
130
|
-
body inert *as an argv token*, but whatever SQL string the hook prints is
|
|
131
|
-
executed as-is. Validate, escape, or parameterize inside the hook.
|
|
132
|
-
|
|
133
|
-
### `post-query`
|
|
134
|
-
|
|
135
|
-
Runs once per successful `POST /query`, after the query. The result rows
|
|
136
|
-
are serialized to a JSON array and delivered two ways:
|
|
137
|
-
|
|
138
|
-
- **On stdin** — always, unbounded. This is the recommended path.
|
|
139
|
-
- **As `{args}`** — only when the serialized payload is ≤ **96 KiB**. Above
|
|
140
|
-
that, `{args}` is substituted with an **empty string** and a stderr
|
|
141
|
-
warning naming the byte size directs the operator to stdin. The full
|
|
142
|
-
payload is still on stdin — this is a fallback, not truncation.
|
|
143
|
-
|
|
144
|
-
| Placeholder | Value |
|
|
145
|
-
|---|---|
|
|
146
|
-
| `{args}` | The result rows as a JSON array, as one argv token; emptied (with a stderr warning) when the payload exceeds 96 KiB. |
|
|
147
|
-
|
|
148
|
-
The stdout payload line is parsed as JSON and returned verbatim as the
|
|
149
|
-
`200 application/json` response body. A payload that is not valid JSON
|
|
150
|
-
fails the request (`500`). With no `post-query` key, the bare row array is
|
|
151
|
-
returned — see [HTTP API](./http-api.md#post-query).
|
|
@@ -48,11 +48,11 @@ excluded from `SELECT *` results.
|
|
|
48
48
|
|
|
49
49
|
| Status | When |
|
|
50
50
|
|---|---|
|
|
51
|
-
| `200` | Query succeeded. Body: array of row objects
|
|
51
|
+
| `200` | Query succeeded. Body: array of row objects. |
|
|
52
52
|
| `400` | Malformed JSON body, missing or empty `sql` field, or a SQL error (syntax error, unknown table, or a statement SQLite classifies as a write — queries are read-only). |
|
|
53
53
|
| `405` | `GET /query`. Plain-text body `method not allowed`. |
|
|
54
54
|
| `408` | The query exceeded the 30-second per-query timeout. |
|
|
55
|
-
| `500` | Internal server fault
|
|
55
|
+
| `500` | Internal server fault. |
|
|
56
56
|
| `503` | The server is in [degraded mode](./cli.md#degraded-mode) (the config file exists but failed to load). |
|
|
57
57
|
|
|
58
58
|
All error responses (except `405`) are `application/json`:
|
|
@@ -61,15 +61,6 @@ All error responses (except `405`) are `application/json`:
|
|
|
61
61
|
{"error": "syntax error near \"SLECT\""}
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
### Hook interactions
|
|
65
|
-
|
|
66
|
-
- With [`[dirsql].pre-query`](./config.md#dirsql-keys) configured, the
|
|
67
|
-
request body is **not** parsed as `{"sql": …}`; the raw body is passed to
|
|
68
|
-
the hook, which prints the SQL to run. Hook failure → `500`.
|
|
69
|
-
- With [`[dirsql].post-query`](./config.md#dirsql-keys) configured, the
|
|
70
|
-
`200` body is whatever JSON the hook prints instead of the bare row
|
|
71
|
-
array. Hook failure or non-JSON output → `500`.
|
|
72
|
-
|
|
73
64
|
## `GET /events`
|
|
74
65
|
|
|
75
66
|
Opens a [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events)
|
|
@@ -4,7 +4,7 @@ name = "dirsql-py-ext"
|
|
|
4
4
|
# pypi/maturin handler can rewrite it via `write-version` before
|
|
5
5
|
# `maturin build`. `pyproject.toml` declares `dynamic = ["version"]`
|
|
6
6
|
# and maturin reads this field. Mirrors `packages/rust/Cargo.toml`.
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.16"
|
|
8
8
|
# abi3 note: the `abi3-py310` pyo3 feature (below) builds ONE stable-ABI
|
|
9
9
|
# `cp310-abi3` wheel per platform that loads on every CPython >= 3.10
|
|
10
10
|
# (matching `pyproject.toml`'s `requires-python = ">=3.10"`), instead of
|
|
@@ -22,7 +22,10 @@ name = "dirsql_py_ext"
|
|
|
22
22
|
crate-type = ["cdylib", "rlib"]
|
|
23
23
|
|
|
24
24
|
[dependencies]
|
|
25
|
-
dirsql
|
|
25
|
+
# `cli` is on so the extension module carries `dirsql::cli::run_cli`: the
|
|
26
|
+
# console script calls it in-process instead of exec'ing a bundled binary
|
|
27
|
+
# (#738), which is what lets `dirsql/_binary/` leave the wheel.
|
|
28
|
+
dirsql = { workspace = true, features = ["cli"] }
|
|
26
29
|
pyo3 = { version = "0.28", features = ["extension-module", "generate-import-lib", "abi3-py310"], optional = true }
|
|
27
30
|
|
|
28
31
|
[lints.rust]
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
**Changed** — the `dirsql` console script now runs **in-process** through the compiled extension module instead of `exec`ing a bundled binary. `_dirsql` is built with the core's `cli` feature and exports `run_cli`, which the launcher calls via [bin-shim](https://pypi.org/project/bin-shim/). Plugin discovery and config-extension resolution are unchanged and still run first. The Windows/POSIX split is gone — `os.execv` on POSIX and `subprocess.run` on Windows are replaced by one in-process call on every platform, so the two no longer drift.
|
|
2
|
+
|
|
3
|
+
**Removed** — **BREAKING (packaging)**: the wheel no longer ships `dirsql/_binary/`. It held a standalone `dirsql` executable duplicating the core already present in the extension module; `pyproject.toml`'s `[tool.maturin].include` row and the release pipeline's pypi `bundle_cli` staging are both gone. `pip install dirsql && dirsql ...` and `uvx dirsql` behave exactly as before — verified across `--version`, a query, a SQL error (1), an unknown flag (2), and `dirsql server` + Ctrl-C (graceful shutdown, **0**). Anyone locating that binary by path must instead call `dirsql._dirsql.run_cli(argv)`, or install the Rust binary with `cargo install dirsql --features cli`. See [MIGRATIONS.md](../../MIGRATIONS.md). #738.
|
|
@@ -54,7 +54,6 @@ export default defineConfig({
|
|
|
54
54
|
{ text: 'Derive columns from file paths', link: '/howto/columns-from-paths' },
|
|
55
55
|
{ text: 'Extract rows from file contents', link: '/howto/extract-from-contents' },
|
|
56
56
|
{ text: 'Parse your files into columns', link: '/howto/parse-files-into-columns' },
|
|
57
|
-
{ text: 'Search documents by meaning', link: '/howto/search-by-meaning' },
|
|
58
57
|
{ text: "Skip files you don't want indexed", link: '/howto/skip-files' },
|
|
59
58
|
{ text: 'Load a SQLite extension', link: '/howto/load-extension' },
|
|
60
59
|
{ text: 'Keep the index across restarts', link: '/howto/persist' },
|
|
@@ -79,8 +79,6 @@ SQLite value mapping is under
|
|
|
79
79
|
|
|
80
80
|
- The command re-runs on every startup and on every change to a matched
|
|
81
81
|
file. If it is expensive, [keep the index across restarts](./persist.md).
|
|
82
|
-
- The flagship use of `on-file` — computing embeddings — is
|
|
83
|
-
[Search documents by meaning](./search-by-meaning.md).
|
|
84
82
|
- Embedding `dirsql` in a program instead? The SDK's `on_file` callback
|
|
85
83
|
fills the same role in-process — see
|
|
86
84
|
[Embed `dirsql` in your application](./embed.md).
|
|
@@ -85,5 +85,3 @@ interpreter to resolve package names with
|
|
|
85
85
|
- Embedding `dirsql` in a program? The SDK constructor takes the same
|
|
86
86
|
specs via its `extensions` parameter
|
|
87
87
|
([SDK reference](../reference/sdk.md#constructor)).
|
|
88
|
-
- The payoff use case — `sqlite-vec` powering semantic search — is
|
|
89
|
-
[Search documents by meaning](./search-by-meaning.md).
|
|
@@ -24,8 +24,7 @@ dirsql-embeddings/
|
|
|
24
24
|
└── dirsql_embeddings/
|
|
25
25
|
├── __init__.py
|
|
26
26
|
├── dirsql.toml # the config fragment
|
|
27
|
-
|
|
28
|
-
└── search.py # pre-query hook
|
|
27
|
+
└── embed.py # on-file hook
|
|
29
28
|
```
|
|
30
29
|
|
|
31
30
|
The entry point maps a **source label** (the name) to the **module that
|
|
@@ -55,8 +54,7 @@ structurally **identical to a user config**. It may declare
|
|
|
55
54
|
[`[[table]]`](../reference/config.md#table) (with
|
|
56
55
|
[`on-file`](../reference/hooks.md#on-file)),
|
|
57
56
|
[`[[dirsql.extension]]`](../reference/config.md#dirsql-extension),
|
|
58
|
-
[`ignore`](../reference/config.md#dirsql-keys),
|
|
59
|
-
[`pre-query`/`post-query`](../reference/hooks.md#pre-query), and
|
|
57
|
+
[`ignore`](../reference/config.md#dirsql-keys), and
|
|
60
58
|
[`hook-timeout`](../reference/hooks.md#timeout).
|
|
61
59
|
|
|
62
60
|
There are **no plugin-specific keys and no plugin-specific restrictions**. The
|
|
@@ -96,17 +94,14 @@ matter most for a published plugin:
|
|
|
96
94
|
## Worked example: an embeddings plugin
|
|
97
95
|
|
|
98
96
|
Here is the whole plugin — vector search over a directory of notes, buildable
|
|
99
|
-
in about
|
|
100
|
-
[Search documents by meaning](./search-by-meaning.md): the
|
|
97
|
+
in about forty lines. It composes two pieces: the
|
|
101
98
|
[`sqlite-vec`](https://github.com/asg017/sqlite-vec) extension for the
|
|
102
|
-
distance math, an `on-file` command to embed each file
|
|
103
|
-
command to embed the question.
|
|
99
|
+
distance math, and an `on-file` command to embed each file.
|
|
104
100
|
|
|
105
101
|
The fragment, `src/dirsql_embeddings/dirsql.toml`:
|
|
106
102
|
|
|
107
103
|
```toml
|
|
108
104
|
[dirsql]
|
|
109
|
-
pre-query = "uv run --with model2vec python search.py {args}"
|
|
110
105
|
hook-timeout = 300 # headroom for the first-run model download
|
|
111
106
|
|
|
112
107
|
[[dirsql.extension]]
|
|
@@ -140,46 +135,23 @@ row = {"path": os.path.relpath(path, root), "text": text,
|
|
|
140
135
|
print(json.dumps([row]))
|
|
141
136
|
```
|
|
142
137
|
|
|
143
|
-
`
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
import sys
|
|
149
|
-
|
|
150
|
-
from model2vec import StaticModel
|
|
151
|
-
|
|
152
|
-
body = json.loads(sys.argv[1])
|
|
153
|
-
model = StaticModel.from_pretrained("minishlab/potion-base-8M")
|
|
154
|
-
vector = model.encode([body["q"]])[0]
|
|
155
|
-
needle = json.dumps([round(float(x), 6) for x in vector])
|
|
156
|
-
print(
|
|
157
|
-
"SELECT path, ROUND(vec_distance_cosine(embedding, '%s'), 3) AS distance "
|
|
158
|
-
"FROM notes ORDER BY distance LIMIT 3" % needle
|
|
159
|
-
)
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
::: warning The hook owns SQL safety
|
|
163
|
-
Whatever SQL `pre-query` prints is executed as-is. Here the interpolated
|
|
164
|
-
value is a numeric vector the script itself produced; never splice raw request
|
|
165
|
-
text into SQL. See [`pre-query`](../reference/hooks.md#pre-query).
|
|
166
|
-
:::
|
|
167
|
-
|
|
168
|
-
The relative `embed.py` / `search.py` above resolve against the fragment
|
|
169
|
-
directory, which is convenient during development. For a published plugin,
|
|
170
|
-
promote them to console scripts (`[project.scripts]` → `embed-file`,
|
|
171
|
-
`embed-search`) so the commands carry their own interpreter and dependencies
|
|
172
|
-
and no longer depend on `uv run --with`.
|
|
138
|
+
The relative `embed.py` above resolves against the fragment directory, which
|
|
139
|
+
is convenient during development. For a published plugin, promote it to a
|
|
140
|
+
console script (`[project.scripts]` → `embed-file`) so the command carries
|
|
141
|
+
its own interpreter and dependencies and no longer depends on
|
|
142
|
+
`uv run --with`.
|
|
173
143
|
|
|
174
144
|
Once the package is installed alongside the launcher, its `notes` table is
|
|
175
145
|
queryable with no config edits:
|
|
176
146
|
|
|
177
147
|
```bash
|
|
178
|
-
uvx --with dirsql-embeddings dirsql query
|
|
148
|
+
uvx --with dirsql-embeddings dirsql query \
|
|
149
|
+
"SELECT path FROM notes ORDER BY vec_distance_cosine(embedding, '[0.1, ...]') LIMIT 3"
|
|
179
150
|
```
|
|
180
151
|
|
|
181
152
|
The launcher discovers the installed plugin, composes its fragment, and the
|
|
182
|
-
`
|
|
153
|
+
`notes` table (with `vec_distance_cosine()` from the loaded extension) is
|
|
154
|
+
available to the query.
|
|
183
155
|
|
|
184
156
|
## SDK-style convention: expose the config
|
|
185
157
|
|
|
@@ -230,8 +202,8 @@ Discovery is deliberately narrow. Know exactly who does what:
|
|
|
230
202
|
[convention above](#sdk-style-convention-expose-the-config)).
|
|
231
203
|
- **Name collisions are a hard error.** Because fragments compose like any
|
|
232
204
|
[multiple configs](../reference/config.md#composing-multiple-configs), two
|
|
233
|
-
plugins (or a plugin and your config) defining a table of the same name
|
|
234
|
-
|
|
205
|
+
plugins (or a plugin and your config) defining a table of the same name
|
|
206
|
+
fail loudly, naming the conflict. It is never a silent
|
|
235
207
|
last-writer-wins.
|
|
236
208
|
|
|
237
209
|
::: warning Config flags are subcommand-local
|