jdsl 0.6.2__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.
- jdsl-0.6.2/.github/workflows/docs.yml +57 -0
- jdsl-0.6.2/.github/workflows/python-publish.yml +55 -0
- jdsl-0.6.2/.gitignore +45 -0
- jdsl-0.6.2/CONTRIBUTING.md +61 -0
- jdsl-0.6.2/LICENSE +8 -0
- jdsl-0.6.2/PKG-INFO +231 -0
- jdsl-0.6.2/README.md +211 -0
- jdsl-0.6.2/docs/api.md +249 -0
- jdsl-0.6.2/docs/cli.md +113 -0
- jdsl-0.6.2/docs/code/authoring.md +111 -0
- jdsl-0.6.2/docs/code/cli-config.md +123 -0
- jdsl-0.6.2/docs/code/compiler.md +218 -0
- jdsl-0.6.2/docs/code/packages.md +172 -0
- jdsl-0.6.2/docs/code/plugins.md +141 -0
- jdsl-0.6.2/docs/code/runtime.md +167 -0
- jdsl-0.6.2/docs/code/tracing.md +131 -0
- jdsl-0.6.2/docs/compiler.md +157 -0
- jdsl-0.6.2/docs/concepts.md +123 -0
- jdsl-0.6.2/docs/developer/layout.md +87 -0
- jdsl-0.6.2/docs/developer/publishing.md +56 -0
- jdsl-0.6.2/docs/developer/tracing.md +50 -0
- jdsl-0.6.2/docs/examples.md +43 -0
- jdsl-0.6.2/docs/for_respected_human.png +0 -0
- jdsl-0.6.2/docs/harness.md +153 -0
- jdsl-0.6.2/docs/harness_usage.md +219 -0
- jdsl-0.6.2/docs/index.md +125 -0
- jdsl-0.6.2/docs/opencode.md +148 -0
- jdsl-0.6.2/docs/packages.md +69 -0
- jdsl-0.6.2/docs/plugins.md +136 -0
- jdsl-0.6.2/docs/providers.md +89 -0
- jdsl-0.6.2/docs/quickstart.md +108 -0
- jdsl-0.6.2/docs/reference/compiler.md +121 -0
- jdsl-0.6.2/docs/reference/runtime.md +86 -0
- jdsl-0.6.2/docs/reference/trace-package.md +103 -0
- jdsl-0.6.2/docs/security.md +67 -0
- jdsl-0.6.2/docs/tui-placeholder.svg +48 -0
- jdsl-0.6.2/docs/tui.md +159 -0
- jdsl-0.6.2/docs/tui.png +0 -0
- jdsl-0.6.2/docs/tutorials/branching.md +68 -0
- jdsl-0.6.2/docs/tutorials/react-tools.md +68 -0
- jdsl-0.6.2/docs/tutorials/refinement.md +61 -0
- jdsl-0.6.2/examples/README.md +31 -0
- jdsl-0.6.2/examples/author_behavior.py +208 -0
- jdsl-0.6.2/examples/db.py +65 -0
- jdsl-0.6.2/examples/gate.py +49 -0
- jdsl-0.6.2/examples/greeter.py +21 -0
- jdsl-0.6.2/examples/harness/retail_mcp_server.py +104 -0
- jdsl-0.6.2/examples/harness/retail_tools.py +75 -0
- jdsl-0.6.2/examples/pipeline.py +46 -0
- jdsl-0.6.2/examples/react.py +45 -0
- jdsl-0.6.2/examples/reason.py +28 -0
- jdsl-0.6.2/examples/refine.py +45 -0
- jdsl-0.6.2/examples/shop.py +84 -0
- jdsl-0.6.2/examples/tinker.py +41 -0
- jdsl-0.6.2/examples/triage.py +67 -0
- jdsl-0.6.2/examples/triage_jev.py +64 -0
- jdsl-0.6.2/examples/trip.py +50 -0
- jdsl-0.6.2/examples/tutor.py +156 -0
- jdsl-0.6.2/examples/tutor_socratic.py +169 -0
- jdsl-0.6.2/examples/wiki.py +75 -0
- jdsl-0.6.2/install.sh +310 -0
- jdsl-0.6.2/jdsl/__init__.py +116 -0
- jdsl-0.6.2/jdsl/cli.py +387 -0
- jdsl-0.6.2/jdsl/config.py +80 -0
- jdsl-0.6.2/jdsl/context.py +159 -0
- jdsl-0.6.2/jdsl/dsl.py +174 -0
- jdsl-0.6.2/jdsl/ir/__init__.py +63 -0
- jdsl-0.6.2/jdsl/ir/expr.py +193 -0
- jdsl-0.6.2/jdsl/ir/lower.py +160 -0
- jdsl-0.6.2/jdsl/ir/schema.py +293 -0
- jdsl-0.6.2/jdsl/ir/validate.py +134 -0
- jdsl-0.6.2/jdsl/package/__init__.py +38 -0
- jdsl-0.6.2/jdsl/package/authoring.py +244 -0
- jdsl-0.6.2/jdsl/package/export.py +129 -0
- jdsl-0.6.2/jdsl/package/load.py +155 -0
- jdsl-0.6.2/jdsl/package/manifest.py +120 -0
- jdsl-0.6.2/jdsl/package/proposal.py +344 -0
- jdsl-0.6.2/jdsl/provider.py +214 -0
- jdsl-0.6.2/jdsl/render.py +35 -0
- jdsl-0.6.2/jdsl/router.py +31 -0
- jdsl-0.6.2/jdsl/trace/__init__.py +41 -0
- jdsl-0.6.2/jdsl/trace/blobs.py +56 -0
- jdsl-0.6.2/jdsl/trace/events.py +180 -0
- jdsl-0.6.2/jdsl/trace/jsonl.py +72 -0
- jdsl-0.6.2/jdsl/trace/redaction.py +89 -0
- jdsl-0.6.2/jdsl/trace/replay.py +117 -0
- jdsl-0.6.2/jdsl/trace/sink.py +110 -0
- jdsl-0.6.2/jdsl/tree.py +753 -0
- jdsl-0.6.2/jdsl/tui/__init__.py +6 -0
- jdsl-0.6.2/jdsl/tui/app.py +164 -0
- jdsl-0.6.2/jdsl/tui/commands.py +60 -0
- jdsl-0.6.2/jdsl/tui/definitions.py +157 -0
- jdsl-0.6.2/jdsl/tui/dialogs.py +56 -0
- jdsl-0.6.2/jdsl/tui/editors.py +420 -0
- jdsl-0.6.2/jdsl/tui/run_inputs.py +113 -0
- jdsl-0.6.2/jdsl/tui/run_panel.py +69 -0
- jdsl-0.6.2/jdsl/tui/screens.py +189 -0
- jdsl-0.6.2/jdsl/tui/settings.py +67 -0
- jdsl-0.6.2/jdsl/tui/signature_editor.py +325 -0
- jdsl-0.6.2/jdsl/tui/templates.py +387 -0
- jdsl-0.6.2/jdsl/tui/theme.py +33 -0
- jdsl-0.6.2/jdsl/tui/workbench.py +1457 -0
- jdsl-0.6.2/jdsl/tui/workbench.tcss +181 -0
- jdsl-0.6.2/jdsl/tui_skill.py +5 -0
- jdsl-0.6.2/jdsl_harness/__init__.py +8 -0
- jdsl-0.6.2/jdsl_harness/adapters/__init__.py +6 -0
- jdsl-0.6.2/jdsl_harness/adapters/claude_code.py +144 -0
- jdsl-0.6.2/jdsl_harness/adapters/correlation.py +88 -0
- jdsl-0.6.2/jdsl_harness/adapters/gemini_cli.py +70 -0
- jdsl-0.6.2/jdsl_harness/adapters/generic_mcp.py +53 -0
- jdsl-0.6.2/jdsl_harness/adapters/import_jsonl.py +86 -0
- jdsl-0.6.2/jdsl_harness/adapters/opencode.py +110 -0
- jdsl-0.6.2/jdsl_harness/capture.py +129 -0
- jdsl-0.6.2/jdsl_harness/compiler/__init__.py +48 -0
- jdsl-0.6.2/jdsl_harness/compiler/candidates.py +131 -0
- jdsl-0.6.2/jdsl_harness/compiler/consolidate.py +141 -0
- jdsl-0.6.2/jdsl_harness/compiler/lineage.py +106 -0
- jdsl-0.6.2/jdsl_harness/compiler/model.py +175 -0
- jdsl-0.6.2/jdsl_harness/compiler/normalize.py +157 -0
- jdsl-0.6.2/jdsl_harness/compiler/package.py +125 -0
- jdsl-0.6.2/jdsl_harness/compiler/residualize.py +31 -0
- jdsl-0.6.2/jdsl_harness/compiler/staticize.py +258 -0
- jdsl-0.6.2/jdsl_harness/compiler/verify.py +127 -0
- jdsl-0.6.2/jdsl_harness/gateway.py +107 -0
- jdsl-0.6.2/jdsl_harness/mcp_proxy.py +277 -0
- jdsl-0.6.2/jdsl_harness/metrics.py +125 -0
- jdsl-0.6.2/jdsl_harness/server.py +260 -0
- jdsl-0.6.2/jdsl_harness/state.py +64 -0
- jdsl-0.6.2/jdsl_harness/store.py +222 -0
- jdsl-0.6.2/mkdocs.yml +140 -0
- jdsl-0.6.2/plugins/README.md +66 -0
- jdsl-0.6.2/plugins/jdsl-claude-plugin/.claude-plugin/plugin.json +7 -0
- jdsl-0.6.2/plugins/jdsl-claude-plugin/hooks/hooks.json +18 -0
- jdsl-0.6.2/plugins/jdsl-claude-plugin/scripts/jdsl_hook_forwarder.py +57 -0
- jdsl-0.6.2/plugins/jdsl-gemini-extension/gemini-extension.json +13 -0
- jdsl-0.6.2/plugins/jdsl-gemini-extension/scripts/jdsl_gemini_forwarder.py +57 -0
- jdsl-0.6.2/plugins/jdsl-opencode-plugin/README.md +41 -0
- jdsl-0.6.2/plugins/jdsl-opencode-plugin/fixtures/tool-after.json +17 -0
- jdsl-0.6.2/plugins/jdsl-opencode-plugin/fixtures/tool-before.json +13 -0
- jdsl-0.6.2/plugins/jdsl-opencode-plugin/jdsl.ts +125 -0
- jdsl-0.6.2/pyproject.toml +71 -0
- jdsl-0.6.2/scripts/build_linux_x64_bundle.sh +47 -0
- jdsl-0.6.2/scripts/jdsl-linux-launcher +16 -0
- jdsl-0.6.2/test/conftest.py +53 -0
- jdsl-0.6.2/test/test_author_behavior_example.py +225 -0
- jdsl-0.6.2/test/test_blackboard.py +63 -0
- jdsl-0.6.2/test/test_cli.py +102 -0
- jdsl-0.6.2/test/test_compiler.py +286 -0
- jdsl-0.6.2/test/test_config.py +61 -0
- jdsl-0.6.2/test/test_decorators.py +72 -0
- jdsl-0.6.2/test/test_dsl.py +82 -0
- jdsl-0.6.2/test/test_dsl_package.py +88 -0
- jdsl-0.6.2/test/test_harness.py +282 -0
- jdsl-0.6.2/test/test_ir.py +165 -0
- jdsl-0.6.2/test/test_package.py +130 -0
- jdsl-0.6.2/test/test_provider.py +137 -0
- jdsl-0.6.2/test/test_react.py +128 -0
- jdsl-0.6.2/test/test_render.py +39 -0
- jdsl-0.6.2/test/test_repeat.py +52 -0
- jdsl-0.6.2/test/test_server_cli.py +306 -0
- jdsl-0.6.2/test/test_trace.py +255 -0
- jdsl-0.6.2/test/test_tree.py +186 -0
- jdsl-0.6.2/test/test_tui.py +611 -0
- jdsl-0.6.2/test/test_tui_templates.py +29 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: docs
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
- master
|
|
8
|
+
- harness
|
|
9
|
+
pull_request:
|
|
10
|
+
paths:
|
|
11
|
+
- docs/**
|
|
12
|
+
- mkdocs.yml
|
|
13
|
+
- pyproject.toml
|
|
14
|
+
- .github/workflows/docs.yml
|
|
15
|
+
workflow_dispatch:
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: write
|
|
19
|
+
|
|
20
|
+
concurrency:
|
|
21
|
+
group: docs
|
|
22
|
+
cancel-in-progress: false
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
build-and-deploy:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
with:
|
|
30
|
+
fetch-depth: 0
|
|
31
|
+
|
|
32
|
+
- uses: actions/setup-python@v5
|
|
33
|
+
with:
|
|
34
|
+
python-version: "3.x"
|
|
35
|
+
|
|
36
|
+
- name: Cache pip
|
|
37
|
+
uses: actions/cache@v4
|
|
38
|
+
with:
|
|
39
|
+
key: mkdocs-${{ runner.os }}-${{ hashFiles('mkdocs.yml') }}
|
|
40
|
+
path: ~/.cache/pip
|
|
41
|
+
restore-keys: |
|
|
42
|
+
mkdocs-${{ runner.os }}-
|
|
43
|
+
|
|
44
|
+
- name: Install docs dependencies
|
|
45
|
+
run: pip install "mkdocs>=1.6,<2" "mkdocs-material>=9.5,<10" "mkdocstrings[python]>=0.26,<1" "pymdown-extensions<12.2"
|
|
46
|
+
- name: Build docs
|
|
47
|
+
run: mkdocs build --strict
|
|
48
|
+
|
|
49
|
+
- name: Configure Git Credentials
|
|
50
|
+
if: github.event_name != 'pull_request'
|
|
51
|
+
run: |
|
|
52
|
+
git config user.name github-actions[bot]
|
|
53
|
+
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
|
54
|
+
|
|
55
|
+
- name: Deploy docs
|
|
56
|
+
if: github.event_name != 'pull_request'
|
|
57
|
+
run: mkdocs gh-deploy --force --strict --no-history
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# This workflow will upload a Python Package to PyPI when a release is created
|
|
2
|
+
name: Upload Python Package
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
release:
|
|
6
|
+
types: [published]
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
release-build:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.11"
|
|
22
|
+
|
|
23
|
+
- name: Build release distributions
|
|
24
|
+
run: |
|
|
25
|
+
python -m pip install --upgrade pip
|
|
26
|
+
python -m pip install build
|
|
27
|
+
python -m build
|
|
28
|
+
|
|
29
|
+
- name: Upload distributions
|
|
30
|
+
uses: actions/upload-artifact@v4
|
|
31
|
+
with:
|
|
32
|
+
name: release-dists
|
|
33
|
+
path: dist/
|
|
34
|
+
|
|
35
|
+
pypi-publish:
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
needs:
|
|
38
|
+
- release-build
|
|
39
|
+
permissions:
|
|
40
|
+
id-token: write
|
|
41
|
+
|
|
42
|
+
environment:
|
|
43
|
+
name: pypi
|
|
44
|
+
|
|
45
|
+
steps:
|
|
46
|
+
- name: Retrieve release distributions
|
|
47
|
+
uses: actions/download-artifact@v4
|
|
48
|
+
with:
|
|
49
|
+
name: release-dists
|
|
50
|
+
path: dist/
|
|
51
|
+
|
|
52
|
+
- name: Publish release distributions to PyPI
|
|
53
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
54
|
+
with:
|
|
55
|
+
packages-dir: dist/
|
jdsl-0.6.2/.gitignore
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
build/
|
|
6
|
+
uv.lock
|
|
7
|
+
|
|
8
|
+
dist/
|
|
9
|
+
|
|
10
|
+
# Environments & secrets
|
|
11
|
+
.venv/
|
|
12
|
+
.env
|
|
13
|
+
.env.*
|
|
14
|
+
|
|
15
|
+
# Tooling caches
|
|
16
|
+
.pytest_cache/
|
|
17
|
+
.ruff_cache/
|
|
18
|
+
.mypy_cache/
|
|
19
|
+
.coverage
|
|
20
|
+
htmlcov/
|
|
21
|
+
|
|
22
|
+
# OS / editor
|
|
23
|
+
.DS_Store
|
|
24
|
+
.idea/
|
|
25
|
+
.vscode/
|
|
26
|
+
.claude/
|
|
27
|
+
.opencode
|
|
28
|
+
|
|
29
|
+
# Local agent config (auto-launches servers; per-checkout, like .claude/)
|
|
30
|
+
.mcp.json
|
|
31
|
+
|
|
32
|
+
# Compiled behavior packages: build outputs / scratch compile dirs.
|
|
33
|
+
# (Committed example fixtures live under examples/ and are tracked explicitly.)
|
|
34
|
+
*.jdsl
|
|
35
|
+
/pkgs/
|
|
36
|
+
/pkgs.jdslpkg
|
|
37
|
+
|
|
38
|
+
VERSION_RELEASE.md
|
|
39
|
+
|
|
40
|
+
# Docs build output and local-only docs drafts / experiments.
|
|
41
|
+
site/
|
|
42
|
+
docs/*_next_steps.md
|
|
43
|
+
docs/*_experiment.ipynb
|
|
44
|
+
docs/draft/
|
|
45
|
+
jdsl-linux-x64.tar.gz
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
uv sync # installs jdsl (editable) + dev tools
|
|
7
|
+
uv run pytest # run the suite
|
|
8
|
+
uv run ruff check jdsl jdsl_harness examples test
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Python ≥ 3.11, [uv](https://docs.astral.sh/uv/) for everything.
|
|
12
|
+
|
|
13
|
+
## Style
|
|
14
|
+
|
|
15
|
+
Terse and dense, in the spirit of tinygrad — small files, one concept each, no
|
|
16
|
+
ceremony. Specifics:
|
|
17
|
+
|
|
18
|
+
- **Line length 120**, 4-space indent (ruff enforces both).
|
|
19
|
+
- Absolute imports only (`from jdsl.tree import ...`).
|
|
20
|
+
- Docstrings explain *why*, not *what the code obviously does*.
|
|
21
|
+
- Prefer a plain function to a class; prefer a combinator to a config object.
|
|
22
|
+
- Keep the public surface (`jdsl/__init__.py`) small and obvious.
|
|
23
|
+
|
|
24
|
+
Run `uv run ruff check jdsl jdsl_harness examples test` before opening a PR; CI
|
|
25
|
+
expects it clean.
|
|
26
|
+
|
|
27
|
+
## Tests are required
|
|
28
|
+
|
|
29
|
+
Every PR that changes behavior needs tests, and the suite must stay **fast and
|
|
30
|
+
offline** — no network, no real API keys.
|
|
31
|
+
|
|
32
|
+
- Tests live in `test/`, one file per module (`test_tree.py`, `test_dsl.py`, …).
|
|
33
|
+
- The LLM is never called for real. Use the `fake_model` fixture (see
|
|
34
|
+
`test/conftest.py`): a `LanguageModel`-shaped stub whose replies you script,
|
|
35
|
+
and which records every call so you can assert on the prompt/system/model.
|
|
36
|
+
- Cover the branch you touched: a happy path *and* a failure path. Behavior-tree
|
|
37
|
+
nodes have two outcomes (`SUCCESS`/`FAILURE`) — test both.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
uv run pytest -q # all
|
|
41
|
+
uv run pytest test/test_dsl.py -q
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Adding an example
|
|
45
|
+
|
|
46
|
+
Examples are teaching material and must run as-is.
|
|
47
|
+
|
|
48
|
+
1. Put a single-file script in `examples/`, named for what it demonstrates.
|
|
49
|
+
2. Start with a module docstring: what it shows, and the exact `uv run jdsl run
|
|
50
|
+
examples/greeter.py` command (with any `-i key=value` inputs).
|
|
51
|
+
3. Deterministic examples need no key; LLM examples read one from `.env`.
|
|
52
|
+
4. Add a one-line entry to `examples/README.md`.
|
|
53
|
+
5. Keep external-service calls robust (timeouts, a descriptive User-Agent) — an
|
|
54
|
+
example that crashes on a flaky network teaches nothing.
|
|
55
|
+
|
|
56
|
+
## Scope of a good PR
|
|
57
|
+
|
|
58
|
+
One idea per PR. New node type, new provider, new example, or a bug fix — not
|
|
59
|
+
all four. If you're adding a node, it needs: the node in `jdsl/tree.py`, a
|
|
60
|
+
combinator in `jdsl/dsl.py`, an export in `jdsl/__init__.py`, a row in
|
|
61
|
+
`docs/api.md`, and tests.
|
jdsl-0.6.2/LICENSE
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Copyright © 2026, Cantor Industries.
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
No licensee or downstream recipient may use the Software (including any modified or derivative versions) to directly compete with the original Licensor by offering it to third parties as a hosted, managed, or Software-as-a-Service (SaaS) product or cloud service where the primary value of the service is the functionality of the Software itself.
|
|
7
|
+
|
|
8
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
jdsl-0.6.2/PKG-INFO
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: jdsl
|
|
3
|
+
Version: 0.6.2
|
|
4
|
+
Summary: Declarative behavior-tree agents with DSPy-style signatures, run by a tree-walking interpreter over DeepSeek / Anthropic / OpenAI.
|
|
5
|
+
Author: Machar Kook
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Requires-Dist: anthropic>=0.49
|
|
10
|
+
Requires-Dist: mcp>=1.2
|
|
11
|
+
Requires-Dist: openai>=1.40
|
|
12
|
+
Requires-Dist: python-dotenv>=1.0
|
|
13
|
+
Requires-Dist: typer>=0.12
|
|
14
|
+
Requires-Dist: typesafe-sdk>=0.7.2
|
|
15
|
+
Provides-Extra: harness
|
|
16
|
+
Requires-Dist: mcp>=1.2; extra == 'harness'
|
|
17
|
+
Provides-Extra: tui
|
|
18
|
+
Requires-Dist: textual>=0.50; extra == 'tui'
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# jdsl
|
|
22
|
+
|
|
23
|
+
<p align="center">
|
|
24
|
+
<img src="docs/for_respected_human.png" alt="jdsl logo" width="240" />
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
> Declarative **behavior-tree agents** as clean Python combinators, run by a
|
|
28
|
+
> **tree-walking interpreter** over DeepSeek / Anthropic / OpenAI — with
|
|
29
|
+
> **DSPy-style signatures** on the LLM leaves.
|
|
30
|
+
|
|
31
|
+
Determinism lives in the tree (`seq` / `sel` / `act`); the model enters only at
|
|
32
|
+
`predict` leaves, typed by a signature like `"message -> category"`. No codegen,
|
|
33
|
+
no object-literal DSL — the tree structure *is* the call structure.
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from jdsl import tool, root, seq, sel, act, check, predict, ref, store
|
|
37
|
+
|
|
38
|
+
@tool
|
|
39
|
+
def route_to_billing(): print("→ billing")
|
|
40
|
+
@tool
|
|
41
|
+
def route_to_support(): print("→ support")
|
|
42
|
+
@tool
|
|
43
|
+
def route_to_human(): print("→ human")
|
|
44
|
+
|
|
45
|
+
skill = (
|
|
46
|
+
root("Triage", system="Classify inbound messages: billing, support, other.")
|
|
47
|
+
.model("deepseek-chat") # provider inferred from the id
|
|
48
|
+
.do(seq(
|
|
49
|
+
predict("message -> category"), # the model classifies…
|
|
50
|
+
sel( # …and the tree branches on it
|
|
51
|
+
seq(check("category", "billing"), act(route_to_billing)),
|
|
52
|
+
seq(check("category", "support"), act(route_to_support)),
|
|
53
|
+
act(route_to_human), # fallback
|
|
54
|
+
),
|
|
55
|
+
))
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
ctx = skill.run(message="I was double charged.")
|
|
59
|
+
print(ctx.blackboard["category"]) # -> "billing"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
…and the model can drive **your** tools. A `react` leaf hands it your `@tool`s and
|
|
63
|
+
lets it pick and chain them (native function-calling):
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from jdsl import tool, root, react
|
|
67
|
+
|
|
68
|
+
@tool
|
|
69
|
+
def distance_km(origin: str, destination: str) -> int: ... # your Python
|
|
70
|
+
@tool
|
|
71
|
+
def drive_hours(km: int) -> float: ...
|
|
72
|
+
|
|
73
|
+
skill = root("Trip").model("deepseek-chat").do(
|
|
74
|
+
react("request -> answer", tools=[distance_km, drive_hours])
|
|
75
|
+
)
|
|
76
|
+
skill.run(request="Driving Nairobi to Mombasa — how long?")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
> distance_km(origin='Nairobi', destination='Mombasa') -> 485
|
|
81
|
+
> drive_hours(km=485) -> 6.1
|
|
82
|
+
answer: About 6.1 hours.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Triage steers the model with the tree; `react` lets the model steer your tools.
|
|
86
|
+
Full version: [examples/trip.py](examples/trip.py).
|
|
87
|
+
|
|
88
|
+
## Skill authoring TUI
|
|
89
|
+
|
|
90
|
+
JDSL includes a compact terminal workbench for building restricted behavior
|
|
91
|
+
trees without writing the initial Python DSL:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
uv run --extra tui jdsl tui
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
<p align="center">
|
|
98
|
+
<img src="docs/tui.png" alt="JDSL skill authoring TUI" width="960" />
|
|
99
|
+
</p>
|
|
100
|
+
|
|
101
|
+
Add sequence, selector, action, guard, predict, react, and repeat nodes; edit
|
|
102
|
+
their properties; validate the tree; and save a portable `.jdsl` package. See
|
|
103
|
+
the [TUI guide](docs/tui.md) for the authoring workflow.
|
|
104
|
+
|
|
105
|
+
The workbench uses the Gruvbox Material palette, adapted from
|
|
106
|
+
[sainnhe/gruvbox-material](https://github.com/sainnhe/gruvbox-material) and
|
|
107
|
+
[curbol/omarchy-gruvbox-material](https://github.com/curbol/omarchy-gruvbox-material).
|
|
108
|
+
Truecolor terminals are recommended (`COLORTERM=truecolor`). Use `Ctrl+M` to
|
|
109
|
+
toggle reduced motion and `Ctrl+G` to switch between ASCII-safe and Unicode glyphs.
|
|
110
|
+
|
|
111
|
+
## Install & run
|
|
112
|
+
|
|
113
|
+
### Quick install (curl)
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
curl -fsSL https://cantorindustries.com/jdsl-py/install.sh | bash
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Or with options:
|
|
120
|
+
```bash
|
|
121
|
+
curl -fsSL https://cantorindustries.com/jdsl-py/install.sh | bash -s -- --version 0.6.0 --no-modify-path
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Requires Python ≥ 3.11. The curl installer includes the harness dependency as
|
|
125
|
+
well as the runtime CLI. After install:
|
|
126
|
+
```bash
|
|
127
|
+
jdsl about # banner + quickstart
|
|
128
|
+
jdsl run examples/greeter.py
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Upgrade a previous curl installation with:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
curl -fsSL https://cantorindustries.com/jdsl-py/install.sh | bash -s -- --uninstall
|
|
135
|
+
curl -fsSL https://cantorindustries.com/jdsl-py/install.sh | bash -s -- --version 0.6.0
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The installed CLI also supports `jdsl uninstall`; captures and provider
|
|
139
|
+
credentials are preserved.
|
|
140
|
+
|
|
141
|
+
### Development (uv)
|
|
142
|
+
|
|
143
|
+
Requires [uv](https://docs.astral.sh/uv/) and Python ≥ 3.11.
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
uv sync
|
|
147
|
+
|
|
148
|
+
uv run jdsl run examples/greeter.py # deterministic, no key
|
|
149
|
+
echo 'DEEPSEEK_API_KEY=sk-...' >> .env # or ANTHROPIC_API_KEY=...
|
|
150
|
+
uv run jdsl run examples/triage.py # LLM-driven
|
|
151
|
+
uv run pytest # tests (no network)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The **provider is inferred from the model id**: `deepseek-chat` → DeepSeek,
|
|
155
|
+
`claude-*` → Anthropic, `gpt-*`/`o*` → OpenAI. A `.env` in the working directory
|
|
156
|
+
is loaded automatically.
|
|
157
|
+
|
|
158
|
+
## The API in one screen
|
|
159
|
+
|
|
160
|
+
| Combinator | Meaning |
|
|
161
|
+
| ---------- | ------- |
|
|
162
|
+
| `root(name, system=…)` | Entry point. Chain `.model(id)` then `.do(child)`. |
|
|
163
|
+
| `seq(*children)` | Run in order; fail fast (behavior-tree AND). |
|
|
164
|
+
| `sel(*children)` | Try until one succeeds (behavior-tree OR). |
|
|
165
|
+
| `repeat(child, until=…, max=n)` | Loop `child` until `until` succeeds or `max` passes (retry/refine). |
|
|
166
|
+
| `invert(child)` · `optional(child)` | Decorators: flip a status · fail-soft (a failing step won't abort its `seq`). |
|
|
167
|
+
| `timeout(child, seconds=…)` · `oneshot(child)` | Decorators: bound wall-clock time · run once per run, replay the status. |
|
|
168
|
+
| `act(fn, *args)` | Leaf calling a `@tool`; literal args are type-checked. |
|
|
169
|
+
| `ref("key")` | An `act` argument resolved from the blackboard at run time. |
|
|
170
|
+
| `store(act(…), "key")` | Capture an action's return value onto the blackboard. |
|
|
171
|
+
| `check("key", value)` | Guard leaf on `blackboard["key"]`; string matches are case/whitespace-lenient. |
|
|
172
|
+
| `predict("a -> b")` | DSPy-style LLM leaf: reads inputs, writes outputs. |
|
|
173
|
+
| `react("q -> a", tools=[…])` | Agentic leaf: the model calls `@tool`s in a loop (function-calling) until it answers. |
|
|
174
|
+
|
|
175
|
+
## Layout
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
jdsl/ the runtime core — dsl, tree (interpreter), context, provider, render, cli
|
|
179
|
+
trace/ canonical trace events, sinks, storage, redaction, replay
|
|
180
|
+
ir/ Behavior IR: schema, safe guard expressions, validation, lowering
|
|
181
|
+
package/ .jdsl manifest, tool contracts, provenance, export + loader
|
|
182
|
+
jdsl_harness/ capture + behavior compiler (separate package; optional [harness] extra)
|
|
183
|
+
plugins/ Claude Code plugin + Gemini CLI extension (trace capture)
|
|
184
|
+
examples/ runnable skills — see examples/README.md
|
|
185
|
+
test/ pytest suite (no network; LLM leaves use fakes)
|
|
186
|
+
docs/ concepts, API reference, providers, harness & compiler
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Behavior harness & compiler
|
|
190
|
+
|
|
191
|
+
jdsl can also *compile* observed frontier-model behavior into portable policy a
|
|
192
|
+
smaller frozen model runs. The harness captures canonical traces, mines and
|
|
193
|
+
verifies reusable structure (exact dataflow, sequencing, guards, recovery), and
|
|
194
|
+
leaves only irreducible semantic decisions as typed signatures — exported as a
|
|
195
|
+
deterministic `.jdsl`.
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
jdsl harness serve # local capture daemon
|
|
199
|
+
jdsl capture inspect <id> # exact-lineage report
|
|
200
|
+
jdsl compile <id> --out retail.jdsl
|
|
201
|
+
jdsl package run retail.jdsl --tools tools.py --model <small-model>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
See [docs/harness_usage.md](docs/harness_usage.md) for the hands-on guide (all
|
|
205
|
+
three capture tiers, compile, verify, run) and [docs/harness.md](docs/harness.md)
|
|
206
|
+
for the design-to-code map.
|
|
207
|
+
|
|
208
|
+
## Docs
|
|
209
|
+
|
|
210
|
+
- [docs/index.md](https://cantor-industries.github.io/jdsl-py/) — MkDocs homepage
|
|
211
|
+
- [docs/quickstart.md](docs/quickstart.md) — install and first runs
|
|
212
|
+
- [docs/examples.md](docs/examples.md) — guide to the runnable examples
|
|
213
|
+
- [docs/concepts.md](docs/concepts.md) — behavior trees, the blackboard, signatures, why no codegen
|
|
214
|
+
- [docs/api.md](docs/api.md) — full combinator + node reference
|
|
215
|
+
- [docs/providers.md](docs/providers.md) — models, keys, `.env`, routing
|
|
216
|
+
- [docs/tui.md](docs/tui.md) — skill authoring TUI
|
|
217
|
+
- [docs/harness_usage.md](docs/harness_usage.md) — hands-on: capture, compile, verify, run
|
|
218
|
+
- [docs/harness.md](docs/harness.md) — capture harness and behavior compiler overview
|
|
219
|
+
- [docs/packages.md](docs/packages.md) — `.jdsl` package format and binding
|
|
220
|
+
- [CONTRIBUTING.md](CONTRIBUTING.md) — dev setup, tests, adding examples
|
|
221
|
+
|
|
222
|
+
## Status
|
|
223
|
+
|
|
224
|
+
Work in progress. The interpreter, combinator API, signatures, and the
|
|
225
|
+
Anthropic / OpenAI-compatible (DeepSeek, OpenAI) backends run today. Not yet
|
|
226
|
+
built: Google provider, and the DSPy-defining **optimization** step (tuning
|
|
227
|
+
prompts against a metric) — the natural next direction now the runtime exists.
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
O`Saasy · Author: Cantor Industries
|
jdsl-0.6.2/README.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# jdsl
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="docs/for_respected_human.png" alt="jdsl logo" width="240" />
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
> Declarative **behavior-tree agents** as clean Python combinators, run by a
|
|
8
|
+
> **tree-walking interpreter** over DeepSeek / Anthropic / OpenAI — with
|
|
9
|
+
> **DSPy-style signatures** on the LLM leaves.
|
|
10
|
+
|
|
11
|
+
Determinism lives in the tree (`seq` / `sel` / `act`); the model enters only at
|
|
12
|
+
`predict` leaves, typed by a signature like `"message -> category"`. No codegen,
|
|
13
|
+
no object-literal DSL — the tree structure *is* the call structure.
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from jdsl import tool, root, seq, sel, act, check, predict, ref, store
|
|
17
|
+
|
|
18
|
+
@tool
|
|
19
|
+
def route_to_billing(): print("→ billing")
|
|
20
|
+
@tool
|
|
21
|
+
def route_to_support(): print("→ support")
|
|
22
|
+
@tool
|
|
23
|
+
def route_to_human(): print("→ human")
|
|
24
|
+
|
|
25
|
+
skill = (
|
|
26
|
+
root("Triage", system="Classify inbound messages: billing, support, other.")
|
|
27
|
+
.model("deepseek-chat") # provider inferred from the id
|
|
28
|
+
.do(seq(
|
|
29
|
+
predict("message -> category"), # the model classifies…
|
|
30
|
+
sel( # …and the tree branches on it
|
|
31
|
+
seq(check("category", "billing"), act(route_to_billing)),
|
|
32
|
+
seq(check("category", "support"), act(route_to_support)),
|
|
33
|
+
act(route_to_human), # fallback
|
|
34
|
+
),
|
|
35
|
+
))
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
ctx = skill.run(message="I was double charged.")
|
|
39
|
+
print(ctx.blackboard["category"]) # -> "billing"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
…and the model can drive **your** tools. A `react` leaf hands it your `@tool`s and
|
|
43
|
+
lets it pick and chain them (native function-calling):
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from jdsl import tool, root, react
|
|
47
|
+
|
|
48
|
+
@tool
|
|
49
|
+
def distance_km(origin: str, destination: str) -> int: ... # your Python
|
|
50
|
+
@tool
|
|
51
|
+
def drive_hours(km: int) -> float: ...
|
|
52
|
+
|
|
53
|
+
skill = root("Trip").model("deepseek-chat").do(
|
|
54
|
+
react("request -> answer", tools=[distance_km, drive_hours])
|
|
55
|
+
)
|
|
56
|
+
skill.run(request="Driving Nairobi to Mombasa — how long?")
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
> distance_km(origin='Nairobi', destination='Mombasa') -> 485
|
|
61
|
+
> drive_hours(km=485) -> 6.1
|
|
62
|
+
answer: About 6.1 hours.
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Triage steers the model with the tree; `react` lets the model steer your tools.
|
|
66
|
+
Full version: [examples/trip.py](examples/trip.py).
|
|
67
|
+
|
|
68
|
+
## Skill authoring TUI
|
|
69
|
+
|
|
70
|
+
JDSL includes a compact terminal workbench for building restricted behavior
|
|
71
|
+
trees without writing the initial Python DSL:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv run --extra tui jdsl tui
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
<p align="center">
|
|
78
|
+
<img src="docs/tui.png" alt="JDSL skill authoring TUI" width="960" />
|
|
79
|
+
</p>
|
|
80
|
+
|
|
81
|
+
Add sequence, selector, action, guard, predict, react, and repeat nodes; edit
|
|
82
|
+
their properties; validate the tree; and save a portable `.jdsl` package. See
|
|
83
|
+
the [TUI guide](docs/tui.md) for the authoring workflow.
|
|
84
|
+
|
|
85
|
+
The workbench uses the Gruvbox Material palette, adapted from
|
|
86
|
+
[sainnhe/gruvbox-material](https://github.com/sainnhe/gruvbox-material) and
|
|
87
|
+
[curbol/omarchy-gruvbox-material](https://github.com/curbol/omarchy-gruvbox-material).
|
|
88
|
+
Truecolor terminals are recommended (`COLORTERM=truecolor`). Use `Ctrl+M` to
|
|
89
|
+
toggle reduced motion and `Ctrl+G` to switch between ASCII-safe and Unicode glyphs.
|
|
90
|
+
|
|
91
|
+
## Install & run
|
|
92
|
+
|
|
93
|
+
### Quick install (curl)
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
curl -fsSL https://cantorindustries.com/jdsl-py/install.sh | bash
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Or with options:
|
|
100
|
+
```bash
|
|
101
|
+
curl -fsSL https://cantorindustries.com/jdsl-py/install.sh | bash -s -- --version 0.6.0 --no-modify-path
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Requires Python ≥ 3.11. The curl installer includes the harness dependency as
|
|
105
|
+
well as the runtime CLI. After install:
|
|
106
|
+
```bash
|
|
107
|
+
jdsl about # banner + quickstart
|
|
108
|
+
jdsl run examples/greeter.py
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Upgrade a previous curl installation with:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
curl -fsSL https://cantorindustries.com/jdsl-py/install.sh | bash -s -- --uninstall
|
|
115
|
+
curl -fsSL https://cantorindustries.com/jdsl-py/install.sh | bash -s -- --version 0.6.0
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The installed CLI also supports `jdsl uninstall`; captures and provider
|
|
119
|
+
credentials are preserved.
|
|
120
|
+
|
|
121
|
+
### Development (uv)
|
|
122
|
+
|
|
123
|
+
Requires [uv](https://docs.astral.sh/uv/) and Python ≥ 3.11.
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
uv sync
|
|
127
|
+
|
|
128
|
+
uv run jdsl run examples/greeter.py # deterministic, no key
|
|
129
|
+
echo 'DEEPSEEK_API_KEY=sk-...' >> .env # or ANTHROPIC_API_KEY=...
|
|
130
|
+
uv run jdsl run examples/triage.py # LLM-driven
|
|
131
|
+
uv run pytest # tests (no network)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The **provider is inferred from the model id**: `deepseek-chat` → DeepSeek,
|
|
135
|
+
`claude-*` → Anthropic, `gpt-*`/`o*` → OpenAI. A `.env` in the working directory
|
|
136
|
+
is loaded automatically.
|
|
137
|
+
|
|
138
|
+
## The API in one screen
|
|
139
|
+
|
|
140
|
+
| Combinator | Meaning |
|
|
141
|
+
| ---------- | ------- |
|
|
142
|
+
| `root(name, system=…)` | Entry point. Chain `.model(id)` then `.do(child)`. |
|
|
143
|
+
| `seq(*children)` | Run in order; fail fast (behavior-tree AND). |
|
|
144
|
+
| `sel(*children)` | Try until one succeeds (behavior-tree OR). |
|
|
145
|
+
| `repeat(child, until=…, max=n)` | Loop `child` until `until` succeeds or `max` passes (retry/refine). |
|
|
146
|
+
| `invert(child)` · `optional(child)` | Decorators: flip a status · fail-soft (a failing step won't abort its `seq`). |
|
|
147
|
+
| `timeout(child, seconds=…)` · `oneshot(child)` | Decorators: bound wall-clock time · run once per run, replay the status. |
|
|
148
|
+
| `act(fn, *args)` | Leaf calling a `@tool`; literal args are type-checked. |
|
|
149
|
+
| `ref("key")` | An `act` argument resolved from the blackboard at run time. |
|
|
150
|
+
| `store(act(…), "key")` | Capture an action's return value onto the blackboard. |
|
|
151
|
+
| `check("key", value)` | Guard leaf on `blackboard["key"]`; string matches are case/whitespace-lenient. |
|
|
152
|
+
| `predict("a -> b")` | DSPy-style LLM leaf: reads inputs, writes outputs. |
|
|
153
|
+
| `react("q -> a", tools=[…])` | Agentic leaf: the model calls `@tool`s in a loop (function-calling) until it answers. |
|
|
154
|
+
|
|
155
|
+
## Layout
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
jdsl/ the runtime core — dsl, tree (interpreter), context, provider, render, cli
|
|
159
|
+
trace/ canonical trace events, sinks, storage, redaction, replay
|
|
160
|
+
ir/ Behavior IR: schema, safe guard expressions, validation, lowering
|
|
161
|
+
package/ .jdsl manifest, tool contracts, provenance, export + loader
|
|
162
|
+
jdsl_harness/ capture + behavior compiler (separate package; optional [harness] extra)
|
|
163
|
+
plugins/ Claude Code plugin + Gemini CLI extension (trace capture)
|
|
164
|
+
examples/ runnable skills — see examples/README.md
|
|
165
|
+
test/ pytest suite (no network; LLM leaves use fakes)
|
|
166
|
+
docs/ concepts, API reference, providers, harness & compiler
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Behavior harness & compiler
|
|
170
|
+
|
|
171
|
+
jdsl can also *compile* observed frontier-model behavior into portable policy a
|
|
172
|
+
smaller frozen model runs. The harness captures canonical traces, mines and
|
|
173
|
+
verifies reusable structure (exact dataflow, sequencing, guards, recovery), and
|
|
174
|
+
leaves only irreducible semantic decisions as typed signatures — exported as a
|
|
175
|
+
deterministic `.jdsl`.
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
jdsl harness serve # local capture daemon
|
|
179
|
+
jdsl capture inspect <id> # exact-lineage report
|
|
180
|
+
jdsl compile <id> --out retail.jdsl
|
|
181
|
+
jdsl package run retail.jdsl --tools tools.py --model <small-model>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
See [docs/harness_usage.md](docs/harness_usage.md) for the hands-on guide (all
|
|
185
|
+
three capture tiers, compile, verify, run) and [docs/harness.md](docs/harness.md)
|
|
186
|
+
for the design-to-code map.
|
|
187
|
+
|
|
188
|
+
## Docs
|
|
189
|
+
|
|
190
|
+
- [docs/index.md](https://cantor-industries.github.io/jdsl-py/) — MkDocs homepage
|
|
191
|
+
- [docs/quickstart.md](docs/quickstart.md) — install and first runs
|
|
192
|
+
- [docs/examples.md](docs/examples.md) — guide to the runnable examples
|
|
193
|
+
- [docs/concepts.md](docs/concepts.md) — behavior trees, the blackboard, signatures, why no codegen
|
|
194
|
+
- [docs/api.md](docs/api.md) — full combinator + node reference
|
|
195
|
+
- [docs/providers.md](docs/providers.md) — models, keys, `.env`, routing
|
|
196
|
+
- [docs/tui.md](docs/tui.md) — skill authoring TUI
|
|
197
|
+
- [docs/harness_usage.md](docs/harness_usage.md) — hands-on: capture, compile, verify, run
|
|
198
|
+
- [docs/harness.md](docs/harness.md) — capture harness and behavior compiler overview
|
|
199
|
+
- [docs/packages.md](docs/packages.md) — `.jdsl` package format and binding
|
|
200
|
+
- [CONTRIBUTING.md](CONTRIBUTING.md) — dev setup, tests, adding examples
|
|
201
|
+
|
|
202
|
+
## Status
|
|
203
|
+
|
|
204
|
+
Work in progress. The interpreter, combinator API, signatures, and the
|
|
205
|
+
Anthropic / OpenAI-compatible (DeepSeek, OpenAI) backends run today. Not yet
|
|
206
|
+
built: Google provider, and the DSPy-defining **optimization** step (tuning
|
|
207
|
+
prompts against a metric) — the natural next direction now the runtime exists.
|
|
208
|
+
|
|
209
|
+
## License
|
|
210
|
+
|
|
211
|
+
O`Saasy · Author: Cantor Industries
|