flowjet 2.0.2__tar.gz → 2.0.3__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.
Potentially problematic release.
This version of flowjet might be problematic. Click here for more details.
- {flowjet-2.0.2 → flowjet-2.0.3}/CHANGELOG.md +11 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/PKG-INFO +1 -1
- {flowjet-2.0.2 → flowjet-2.0.3}/pyproject.toml +1 -1
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/progress.py +34 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/bridges/nano/mapping.py +193 -2
- {flowjet-2.0.2 → flowjet-2.0.3}/.gitignore +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/LICENSE +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/README.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/config/nano.yml +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/deploy/README.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/deploy/nano.yml +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/completion-design.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/drafts/README.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/drafts/api-spec.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/impl/IG-001-openai-compatible-server.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/impl/IG-002-isolated-thread-pool-runtime.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/impl/IG-003-production-isolation-hardening.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/impl/README.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/impl/TEST-COVERAGE-MATRIX.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/naming.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/server.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/specs/RFC-001-openai-compatible-api.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/specs/RFC-002-isolated-thread-pool-runtime.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/specs/RFC-003-production-isolation-hardening.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/specs/RFC-004-unified-package.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/specs/rfc-history.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/specs/rfc-index.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/specs/rfc-namings.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/specs/templates/architecture-design.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/specs/templates/conceptual-design.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/specs/templates/impl-interface-design.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/specs/templates/rfc-standard.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/specs/templates/rfc-template.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/docs/upgrade.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/examples/README.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/nano.yml +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/__init__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/__main__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/README.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/gws-drive/SKILL.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/gws-drive-upload/SKILL.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/logo-generator-skill/.env.example +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/logo-generator-skill/README.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/logo-generator-skill/SKILL.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/logo-generator-skill/assets/background_library.html +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/logo-generator-skill/assets/showcase_template.html +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/logo-generator-skill/references/background_styles.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/logo-generator-skill/references/design_patterns.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/logo-generator-skill/references/webgl_backgrounds.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/logo-generator-skill/requirements.txt +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/logo-generator-skill/scripts/generate_showcase.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/logo-generator-skill/scripts/svg_to_png.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/SKILL.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/brainstorming/spec-document-reviewer-prompt.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/implementation/coding-plan-template.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/implementation/impl-guide-template.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/review/pr-review-template.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/review/review-checklist.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/specs/rfc-template.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/specs/template-architecture-design.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/specs/template-conceptual-design.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/specs/template-impl-interface-design.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-drafts-readme.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-impl-readme.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-platonic.yml +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-rfc-history.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-rfc-index.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-rfc-namings.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-rfc-standard.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/BRAINSTORM/brainstorm.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-code.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-create-guide.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-full.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-update-guide.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-validate-guide.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-plan-modular-specs.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-recover-architecture.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-recover-conceptual.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-recover-impl-interface.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-scaffold.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-scan.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/REFERENCE.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/REVIEW/review-spec-compliance.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-check-compliance.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-check-taxonomy.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-generate-history.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-generate-index.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-generate-namings.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-refine.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-validate-consistency.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/WORKFLOW/workflow-overview.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/WORKFLOW/workflow-phase-1.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/WORKFLOW/workflow-phase-2.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/WORKFLOW/workflow-phase-3.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/SKILL.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/patterns/evidence-deep.json +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/patterns/evidence-first.json +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/patterns/idea-first.json +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/patterns/loop.json +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/patterns/paper-pipeline.json +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/patterns/rapid.json +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/patterns/rigor-first.json +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/patterns/stance-first.json +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/patterns/systematic-review.json +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/patterns/verify-loop.json +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/references/backends.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/references/handoff-ars-omr.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/references/handoff-omr-ars.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/references/routing.md +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/scripts/csljson_to_omr.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/scripts/papers_index_to_csljson.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/__init__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/__main__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/agent.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/cli.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/completion/__init__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/completion/context.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/completion/engine.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/doctor_cmd.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/doctor_fix_cmd.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/serve_cmd.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/setup_cmd.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/shell/__init__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/shell/_fj.zsh +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/shell/fj.bash +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/stream.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/threads.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/cli/tool_stream.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/__init__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/backend.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/backends/__init__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/backends/direct.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/backends/fake.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/backends/isolation/__init__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/backends/isolation/adapter.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/backends/isolation/admission.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/backends/isolation/backend.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/backends/isolation/errors.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/backends/isolation/mode_gate.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/backends/isolation/pool.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/backends/isolation/request.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/backends/isolation/workspace.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/bootstrap.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/bridges/nano/__init__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/bridges/nano/adapter.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/bridges/nano/backend.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/events.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/identity.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/modes.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/protocol.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/tool_results.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/core/tool_stream.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/__init__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/__main__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/acp/__init__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/acp/agent.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/acp/routes.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/config.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/http/__init__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/http/app.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/http/auth.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/openai_compat/__init__.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/openai_compat/errors.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/openai_compat/projection.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/openai_compat/routes.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/openai_compat/schemas.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/openai_compat/service.py +0 -0
- {flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/server/openai_compat/store.py +0 -0
|
@@ -10,6 +10,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [2.0.3] — 2026-09-18
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **Plan-step and middleware-phase progress in the CLI.** The nano bridge now
|
|
18
|
+
maps the host (soothe) loop's todo list and middleware phase updates into
|
|
19
|
+
step/tool progress events, so the terminal shows `Step 2/3 · Create a2.txt`
|
|
20
|
+
instead of a bare `Working` line. Late-parsing tool args refresh the status
|
|
21
|
+
line once, and `write_todos` bookkeeping is suppressed as a tool call (it
|
|
22
|
+
already drives the step line).
|
|
23
|
+
|
|
13
24
|
## [2.0.2] — 2026-09-18
|
|
14
25
|
|
|
15
26
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: flowjet
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.3
|
|
4
4
|
Summary: FlowJet — agent CLI (fj) and server (ACP + OpenAI-compatible HTTP) powered by soothe-nano
|
|
5
5
|
Project-URL: Homepage, https://github.com/caesar0301/flowjet
|
|
6
6
|
Project-URL: Repository, https://github.com/caesar0301/flowjet
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "flowjet"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.3"
|
|
8
8
|
description = "FlowJet — agent CLI (fj) and server (ACP + OpenAI-compatible HTTP) powered by soothe-nano"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -67,6 +67,14 @@ _ACTION_LABELS: dict[str, str] = {
|
|
|
67
67
|
"queued": "Queued",
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
# Host (soothe) loop phases surfaced as graph updates by the nano bridge.
|
|
71
|
+
_STEP_PHASE_LABELS: dict[str, str] = {
|
|
72
|
+
"planned": "Planning steps",
|
|
73
|
+
"decomposed": "Decomposing task",
|
|
74
|
+
"evaluated": "Evaluating step",
|
|
75
|
+
"fanned_out": "Coordinating agents",
|
|
76
|
+
}
|
|
77
|
+
|
|
70
78
|
# Verb + color for well-known tools (fallback: Running / yellow)
|
|
71
79
|
_TOOL_VERBS: dict[str, tuple[str, str]] = {
|
|
72
80
|
"read_file": ("Reading", "yellow"),
|
|
@@ -693,6 +701,32 @@ def friendly_progress(data: dict[str, Any]) -> tuple[str, str] | None:
|
|
|
693
701
|
label = f"{label} · {detail}"
|
|
694
702
|
return _fit(label), color
|
|
695
703
|
|
|
704
|
+
if domain == "step":
|
|
705
|
+
# Plan steps come from the agent's todo list (one event per change).
|
|
706
|
+
if "steps" in data or "todo" in data:
|
|
707
|
+
step = data.get("step")
|
|
708
|
+
steps = data.get("steps")
|
|
709
|
+
todo = _compact(data.get("todo"))
|
|
710
|
+
head = f"Step {step}/{steps}" if step and steps else "Step"
|
|
711
|
+
if todo:
|
|
712
|
+
return _fit(f"{head} · {todo}"), "blue"
|
|
713
|
+
if data.get("status") == "completed":
|
|
714
|
+
return _fit(f"Steps complete · {step}/{steps}"), "green"
|
|
715
|
+
return _fit(head), "blue"
|
|
716
|
+
label = _STEP_PHASE_LABELS.get(action) or verb
|
|
717
|
+
return _fit(label), "blue"
|
|
718
|
+
|
|
719
|
+
if event_type == "soothe.ask.requested":
|
|
720
|
+
question = _compact(data.get("question") or data.get("message"))
|
|
721
|
+
if question:
|
|
722
|
+
q_limit = _detail_budget(prefix="Preparing question · ", fraction=0.55, floor=16)
|
|
723
|
+
return _fit(f"Preparing question · {_truncate_middle(question, q_limit)}"), "magenta"
|
|
724
|
+
return _fit("Preparing question"), "magenta"
|
|
725
|
+
|
|
726
|
+
if event_type == "soothe.intake.routed":
|
|
727
|
+
name = _compact(data.get("subagent") or data.get("subagent_type") or "specialist")
|
|
728
|
+
return _fit(f"Routing · {name}"), "magenta"
|
|
729
|
+
|
|
696
730
|
if domain == "skill" or "skill" in short:
|
|
697
731
|
color = "blue"
|
|
698
732
|
name = data.get("skill") or data.get("name") or "skill"
|
|
@@ -33,6 +33,161 @@ _SKIP_CUSTOM_TYPES = frozenset(
|
|
|
33
33
|
}
|
|
34
34
|
)
|
|
35
35
|
|
|
36
|
+
# Host (soothe) middleware surfaces as ``<Middleware>.<phase>`` graph updates.
|
|
37
|
+
# The CLI renders these through ``friendly_progress``, so the synthetic payloads
|
|
38
|
+
# below stay in the same ``soothe.*`` vocabulary as nano's custom events.
|
|
39
|
+
_HOST_PHASE_EVENTS: dict[str, str] = {
|
|
40
|
+
"GoalStepGuardMiddleware": "soothe.step.planned",
|
|
41
|
+
"DecomposeTaskMiddleware": "soothe.step.decomposed",
|
|
42
|
+
"EvalStepMiddleware": "soothe.step.evaluated",
|
|
43
|
+
"WestWorldMiddleware": "soothe.step.fanned_out",
|
|
44
|
+
"AskUserPromptMiddleware": "soothe.ask.requested",
|
|
45
|
+
"IntakeOnlyTaskGuardMiddleware": "soothe.intake.routed",
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# Plan bookkeeping: the todo list already drives the step line.
|
|
49
|
+
_QUIET_TOOLS = frozenset({"write_todos", "todo_write", "write_todo_list"})
|
|
50
|
+
|
|
51
|
+
# Fires on every turn with no user-visible content.
|
|
52
|
+
_SKIP_UPDATE_NODES = frozenset(
|
|
53
|
+
{
|
|
54
|
+
"PatchToolCallsMiddleware",
|
|
55
|
+
"ProgressiveToolMiddleware",
|
|
56
|
+
"WorkspaceContextMiddleware",
|
|
57
|
+
"TodoListMiddleware",
|
|
58
|
+
"model",
|
|
59
|
+
"tools",
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def todo_step_payload(todos: list[Any]) -> dict[str, Any] | None:
|
|
65
|
+
"""Turn a soothe todo list into a step-progress payload.
|
|
66
|
+
|
|
67
|
+
The agent writes its plan as todos (``write_todos``); each ``in_progress``
|
|
68
|
+
item is the step the user is waiting on, which is far more informative than
|
|
69
|
+
a generic "Working" line.
|
|
70
|
+
"""
|
|
71
|
+
items = [item for item in todos if isinstance(item, dict)]
|
|
72
|
+
if not items:
|
|
73
|
+
return None
|
|
74
|
+
total = len(items)
|
|
75
|
+
done = sum(1 for item in items if str(item.get("status")) == "completed")
|
|
76
|
+
current = next(
|
|
77
|
+
(item for item in items if str(item.get("status")) == "in_progress"),
|
|
78
|
+
None,
|
|
79
|
+
)
|
|
80
|
+
if current is None:
|
|
81
|
+
if done == 0:
|
|
82
|
+
return None
|
|
83
|
+
return {
|
|
84
|
+
"type": "soothe.step.progress",
|
|
85
|
+
"step": done,
|
|
86
|
+
"steps": total,
|
|
87
|
+
"done": done,
|
|
88
|
+
"status": "completed",
|
|
89
|
+
"todo": "",
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
"type": "soothe.step.progress",
|
|
93
|
+
"step": items.index(current) + 1,
|
|
94
|
+
"steps": total,
|
|
95
|
+
"done": done,
|
|
96
|
+
"status": "in_progress",
|
|
97
|
+
"todo": str(current.get("content") or ""),
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _skill_names(payload: dict[str, Any]) -> list[str]:
|
|
102
|
+
"""Best-effort skill names from a ``SkillActivationMiddleware`` payload."""
|
|
103
|
+
raw = payload.get("skill_activation")
|
|
104
|
+
if isinstance(raw, dict):
|
|
105
|
+
raw = raw.get("skills") or raw.get("activated") or raw.get("names") or []
|
|
106
|
+
if not isinstance(raw, (list, tuple)):
|
|
107
|
+
return []
|
|
108
|
+
names: list[str] = []
|
|
109
|
+
for item in raw:
|
|
110
|
+
if isinstance(item, str) and item.strip():
|
|
111
|
+
names.append(item.strip())
|
|
112
|
+
elif isinstance(item, dict):
|
|
113
|
+
name = item.get("name") or item.get("skill")
|
|
114
|
+
if isinstance(name, str) and name.strip():
|
|
115
|
+
names.append(name.strip())
|
|
116
|
+
return names
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def update_progress(data: dict[str, Any]) -> tuple[str, dict[str, Any]] | None:
|
|
120
|
+
"""Map one soothe ``updates`` chunk to ``(dedupe_key, event_payload)``.
|
|
121
|
+
|
|
122
|
+
Returns ``None`` for the plumbing updates that carry no user-visible step.
|
|
123
|
+
"""
|
|
124
|
+
todos = data.get("todos")
|
|
125
|
+
if isinstance(todos, list):
|
|
126
|
+
payload = todo_step_payload(todos)
|
|
127
|
+
if payload is not None:
|
|
128
|
+
key = f"todo:{payload['step']}/{payload['steps']}:{payload['todo']}:{payload['done']}"
|
|
129
|
+
return key, payload
|
|
130
|
+
|
|
131
|
+
for node, node_payload in data.items():
|
|
132
|
+
name = node.split(".")[0]
|
|
133
|
+
# The todo list rides along inside the ``tools`` node update.
|
|
134
|
+
if isinstance(node_payload, dict) and isinstance(node_payload.get("todos"), list):
|
|
135
|
+
payload = todo_step_payload(node_payload["todos"])
|
|
136
|
+
if payload is not None:
|
|
137
|
+
key = (
|
|
138
|
+
f"todo:{payload['step']}/{payload['steps']}:{payload['todo']}:{payload['done']}"
|
|
139
|
+
)
|
|
140
|
+
return key, payload
|
|
141
|
+
if name in _SKIP_UPDATE_NODES:
|
|
142
|
+
continue
|
|
143
|
+
event = _HOST_PHASE_EVENTS.get(name)
|
|
144
|
+
if event is not None:
|
|
145
|
+
phase = node.split(".", 1)[1] if "." in node else ""
|
|
146
|
+
return node, {"type": event, "middleware": name, "phase": phase}
|
|
147
|
+
if name == "SkillActivationMiddleware" and isinstance(node_payload, dict):
|
|
148
|
+
names = _skill_names(node_payload)
|
|
149
|
+
if names:
|
|
150
|
+
return node, {"type": "soothe.skill.activated", "skill": ", ".join(names)}
|
|
151
|
+
return None
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
# Arg keys worth echoing in a one-line tool summary (first match wins).
|
|
155
|
+
_TOOL_SUMMARY_KEYS = (
|
|
156
|
+
"file_path",
|
|
157
|
+
"path",
|
|
158
|
+
"target_file",
|
|
159
|
+
"command",
|
|
160
|
+
"cmd",
|
|
161
|
+
"script",
|
|
162
|
+
"query",
|
|
163
|
+
"pattern",
|
|
164
|
+
"url",
|
|
165
|
+
"skill",
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def tool_call_summary(name: str, args: dict[str, Any]) -> str:
|
|
170
|
+
"""``write_file a.txt``-style summary for renderers without tool metadata."""
|
|
171
|
+
for key in _TOOL_SUMMARY_KEYS:
|
|
172
|
+
value = args.get(key)
|
|
173
|
+
if isinstance(value, (str, int, float)) and str(value).strip():
|
|
174
|
+
text = " ".join(str(value).split())
|
|
175
|
+
return f"{name} {text[:60]}"
|
|
176
|
+
return str(name)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def step_message(payload: dict[str, Any]) -> str:
|
|
180
|
+
"""Human-readable one-liner for a step payload (used by non-CLI renderers)."""
|
|
181
|
+
step = payload.get("step")
|
|
182
|
+
steps = payload.get("steps")
|
|
183
|
+
todo = str(payload.get("todo") or "").strip()
|
|
184
|
+
head = f"{step}/{steps}" if step and steps else "step"
|
|
185
|
+
if todo:
|
|
186
|
+
return f"Step {head} · {todo}"
|
|
187
|
+
if payload.get("status") == "completed":
|
|
188
|
+
return f"Steps complete · {head}"
|
|
189
|
+
return f"Step {head}"
|
|
190
|
+
|
|
36
191
|
|
|
37
192
|
def resolve_interaction_mode(metadata: dict[str, Any] | None) -> str:
|
|
38
193
|
"""Return ``agent`` or ``ask`` from request metadata (default ``agent``)."""
|
|
@@ -114,6 +269,8 @@ async def iter_nano_runtime_events(
|
|
|
114
269
|
open_args: dict[str, dict[str, Any]] = {}
|
|
115
270
|
tool_args = ToolCallArgAccumulator()
|
|
116
271
|
emitted_calls: set[str] = set()
|
|
272
|
+
refreshed_calls: set[str] = set()
|
|
273
|
+
last_step_key = ""
|
|
117
274
|
|
|
118
275
|
try:
|
|
119
276
|
async for chunk in agent.astream(
|
|
@@ -132,8 +289,23 @@ async def iter_nano_runtime_events(
|
|
|
132
289
|
yield mapped
|
|
133
290
|
continue
|
|
134
291
|
|
|
135
|
-
if mode == "updates" and isinstance(data, dict)
|
|
136
|
-
|
|
292
|
+
if mode == "updates" and isinstance(data, dict):
|
|
293
|
+
if "__interrupt__" in data:
|
|
294
|
+
yield InterruptWaiting(message="Waiting for input…")
|
|
295
|
+
continue
|
|
296
|
+
# Plan steps (todos) and host middleware phases are the only
|
|
297
|
+
# signal soothe gives us about *what* it is doing between tool
|
|
298
|
+
# calls; surface each change once.
|
|
299
|
+
step = update_progress(data)
|
|
300
|
+
if step is not None:
|
|
301
|
+
key, payload = step
|
|
302
|
+
if key != last_step_key:
|
|
303
|
+
last_step_key = key
|
|
304
|
+
yield Progress(
|
|
305
|
+
stage="Step",
|
|
306
|
+
message=step_message(payload),
|
|
307
|
+
raw=payload,
|
|
308
|
+
)
|
|
137
309
|
continue
|
|
138
310
|
|
|
139
311
|
if mode != "messages":
|
|
@@ -153,6 +325,22 @@ async def iter_nano_runtime_events(
|
|
|
153
325
|
if tc_id in emitted_calls:
|
|
154
326
|
# Later updates refresh args; the call already started.
|
|
155
327
|
open_args[tc_id] = args
|
|
328
|
+
# Tool args stream as partial JSON, so ToolStarted
|
|
329
|
+
# usually carries none — refresh the status line
|
|
330
|
+
# once they parse (Writing b1.txt, not Writing).
|
|
331
|
+
# Once per call: partial JSON grows on every token,
|
|
332
|
+
# and re-emitting it would flood the event stream.
|
|
333
|
+
if args and name not in _QUIET_TOOLS and tc_id not in refreshed_calls:
|
|
334
|
+
refreshed_calls.add(tc_id)
|
|
335
|
+
yield Progress(
|
|
336
|
+
stage="Tool",
|
|
337
|
+
message=tool_call_summary(str(name), args),
|
|
338
|
+
raw={
|
|
339
|
+
"type": "soothe.tool.started",
|
|
340
|
+
"tool": name,
|
|
341
|
+
"args": args,
|
|
342
|
+
},
|
|
343
|
+
)
|
|
156
344
|
continue
|
|
157
345
|
emitted_calls.add(tc_id)
|
|
158
346
|
open_tools[tc_id] = str(name)
|
|
@@ -197,6 +385,9 @@ async def iter_nano_runtime_events(
|
|
|
197
385
|
err_detail = tool_result_error_detail(message_obj.content)
|
|
198
386
|
ok = status != "error" and err_detail is None
|
|
199
387
|
detail = simplify_tool_error(err_detail) if err_detail else None
|
|
388
|
+
if str(name) in _QUIET_TOOLS and ok:
|
|
389
|
+
# Plan bookkeeping already surfaced as a step event.
|
|
390
|
+
continue
|
|
200
391
|
yield ToolCompleted(
|
|
201
392
|
tool=str(name),
|
|
202
393
|
ok=ok,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/logo-generator-skill/.env.example
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/logo-generator-skill/requirements.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/platonic-coding/references/REFERENCE.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/patterns/loop.json
RENAMED
|
File without changes
|
|
File without changes
|
{flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/patterns/rapid.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/references/backends.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flowjet-2.0.2 → flowjet-2.0.3}/src/flowjet/builtin_skills/research-bootstrap/references/routing.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|