flowjet 2.0.3__tar.gz → 2.0.4__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.3 → flowjet-2.0.4}/CHANGELOG.md +7 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/PKG-INFO +2 -2
- {flowjet-2.0.3 → flowjet-2.0.4}/pyproject.toml +2 -2
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/agent.py +23 -70
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/cli.py +135 -4
- flowjet-2.0.4/src/flowjet/core/home.py +127 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/__main__.py +9 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/.gitignore +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/LICENSE +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/README.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/config/nano.yml +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/deploy/README.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/deploy/nano.yml +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/completion-design.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/drafts/README.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/drafts/api-spec.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/impl/IG-001-openai-compatible-server.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/impl/IG-002-isolated-thread-pool-runtime.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/impl/IG-003-production-isolation-hardening.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/impl/README.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/impl/TEST-COVERAGE-MATRIX.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/naming.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/server.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/specs/RFC-001-openai-compatible-api.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/specs/RFC-002-isolated-thread-pool-runtime.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/specs/RFC-003-production-isolation-hardening.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/specs/RFC-004-unified-package.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/specs/rfc-history.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/specs/rfc-index.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/specs/rfc-namings.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/specs/templates/architecture-design.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/specs/templates/conceptual-design.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/specs/templates/impl-interface-design.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/specs/templates/rfc-standard.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/specs/templates/rfc-template.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/docs/upgrade.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/examples/README.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/nano.yml +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/__init__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/__main__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/README.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/gws-drive/SKILL.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/gws-drive-upload/SKILL.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/logo-generator-skill/.env.example +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/logo-generator-skill/README.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/logo-generator-skill/SKILL.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/logo-generator-skill/assets/background_library.html +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/logo-generator-skill/assets/showcase_template.html +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/logo-generator-skill/references/background_styles.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/logo-generator-skill/references/design_patterns.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/logo-generator-skill/references/webgl_backgrounds.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/logo-generator-skill/requirements.txt +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/logo-generator-skill/scripts/generate_showcase.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/logo-generator-skill/scripts/svg_to_png.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/SKILL.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/brainstorming/spec-document-reviewer-prompt.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/implementation/coding-plan-template.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/implementation/impl-guide-template.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/review/pr-review-template.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/review/review-checklist.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/specs/rfc-template.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/specs/template-architecture-design.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/specs/template-conceptual-design.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/specs/template-impl-interface-design.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-drafts-readme.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-impl-readme.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-platonic.yml +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-rfc-history.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-rfc-index.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-rfc-namings.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-rfc-standard.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/BRAINSTORM/brainstorm.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-code.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-create-guide.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-full.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-update-guide.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-validate-guide.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-plan-modular-specs.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-recover-architecture.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-recover-conceptual.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-recover-impl-interface.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-scaffold.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-scan.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/REFERENCE.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/REVIEW/review-spec-compliance.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-check-compliance.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-check-taxonomy.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-generate-history.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-generate-index.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-generate-namings.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-refine.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-validate-consistency.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/WORKFLOW/workflow-overview.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/WORKFLOW/workflow-phase-1.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/WORKFLOW/workflow-phase-2.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/platonic-coding/references/WORKFLOW/workflow-phase-3.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/SKILL.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/patterns/evidence-deep.json +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/patterns/evidence-first.json +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/patterns/idea-first.json +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/patterns/loop.json +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/patterns/paper-pipeline.json +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/patterns/rapid.json +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/patterns/rigor-first.json +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/patterns/stance-first.json +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/patterns/systematic-review.json +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/patterns/verify-loop.json +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/references/backends.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/references/handoff-ars-omr.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/references/handoff-omr-ars.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/references/routing.md +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/scripts/csljson_to_omr.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/scripts/papers_index_to_csljson.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/__init__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/__main__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/completion/__init__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/completion/context.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/completion/engine.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/doctor_cmd.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/doctor_fix_cmd.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/progress.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/serve_cmd.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/setup_cmd.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/shell/__init__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/shell/_fj.zsh +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/shell/fj.bash +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/stream.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/threads.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/cli/tool_stream.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/__init__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/backend.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/backends/__init__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/backends/direct.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/backends/fake.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/backends/isolation/__init__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/backends/isolation/adapter.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/backends/isolation/admission.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/backends/isolation/backend.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/backends/isolation/errors.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/backends/isolation/mode_gate.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/backends/isolation/pool.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/backends/isolation/request.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/backends/isolation/workspace.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/bootstrap.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/bridges/nano/__init__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/bridges/nano/adapter.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/bridges/nano/backend.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/bridges/nano/mapping.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/events.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/identity.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/modes.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/protocol.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/tool_results.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/core/tool_stream.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/__init__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/acp/__init__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/acp/agent.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/acp/routes.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/config.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/http/__init__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/http/app.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/http/auth.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/openai_compat/__init__.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/openai_compat/errors.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/openai_compat/projection.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/openai_compat/routes.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/openai_compat/schemas.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/openai_compat/service.py +0 -0
- {flowjet-2.0.3 → flowjet-2.0.4}/src/flowjet/server/openai_compat/store.py +0 -0
|
@@ -10,6 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [2.0.4] — 2026-09-19
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Bumped `soothe` lower bound to `1.0.13` (was `1.0.12`). soothe-nano stays
|
|
18
|
+
pinned at `>=1.2.28,<1.3.0`.
|
|
19
|
+
|
|
13
20
|
## [2.0.3] — 2026-09-18
|
|
14
21
|
|
|
15
22
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: flowjet
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.4
|
|
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
|
|
@@ -23,7 +23,7 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
|
23
23
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
24
|
Requires-Python: <3.15,>=3.11
|
|
25
25
|
Requires-Dist: soothe-nano<1.3.0,>=1.2.28
|
|
26
|
-
Requires-Dist: soothe<2.0.0,>=1.0.
|
|
26
|
+
Requires-Dist: soothe<2.0.0,>=1.0.13
|
|
27
27
|
Provides-Extra: dev
|
|
28
28
|
Requires-Dist: httpx>=0.27.0; extra == 'dev'
|
|
29
29
|
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
@@ -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.4"
|
|
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" }
|
|
@@ -31,7 +31,7 @@ classifiers = [
|
|
|
31
31
|
dependencies = [
|
|
32
32
|
# Default CLI runtime (FLOWJET_BACKEND=soothe). soothe is a host layer over
|
|
33
33
|
# soothe-nano, so nano stays pinned explicitly: soothe only caps it at <2.
|
|
34
|
-
"soothe>=1.0.
|
|
34
|
+
"soothe>=1.0.13,<2.0.0",
|
|
35
35
|
"soothe-nano>=1.2.28,<1.3.0",
|
|
36
36
|
]
|
|
37
37
|
|
|
@@ -8,14 +8,12 @@ Nano bootstrap, config loading and the builtin-skill root now live in
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import logging
|
|
11
|
-
import os
|
|
12
|
-
import sys
|
|
13
|
-
from logging.handlers import RotatingFileHandler
|
|
14
11
|
from pathlib import Path
|
|
15
12
|
from typing import Any
|
|
16
13
|
|
|
17
14
|
from soothe_nano.config import SootheConfig
|
|
18
15
|
|
|
16
|
+
from flowjet.cli.cli import _CompactConsoleFormatter
|
|
19
17
|
from flowjet.core.bootstrap import (
|
|
20
18
|
BUILTIN_SKILLS_DIR,
|
|
21
19
|
FJ_CORE_SKILL_NAMES,
|
|
@@ -31,6 +29,27 @@ from flowjet.core.modes import CLI_PROFILE, apply_profile
|
|
|
31
29
|
|
|
32
30
|
logger = logging.getLogger(__name__)
|
|
33
31
|
|
|
32
|
+
# ---------------------------------------------------------------------------
|
|
33
|
+
# CLI logging (delegated to ``flowjet.cli.cli`` at call time)
|
|
34
|
+
# ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def configure_cli_logging(*, verbose: bool = False) -> None:
|
|
38
|
+
"""Quiet the console for one-shot CLI use (see ``flowjet.cli.cli``).
|
|
39
|
+
|
|
40
|
+
Delegated dynamically so monkeypatching ``flowjet.cli.cli.configure_cli_logging``
|
|
41
|
+
(as tests do via ``monkeypatch.setattr(cli, ...)``) is honored here too.
|
|
42
|
+
"""
|
|
43
|
+
from flowjet.cli import cli as _cli
|
|
44
|
+
|
|
45
|
+
_cli.configure_cli_logging(verbose=verbose)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def silence_after_plugins(*, verbose: bool = False) -> None:
|
|
49
|
+
"""Re-apply quieting after plugin imports (belt-and-suspenders)."""
|
|
50
|
+
configure_cli_logging(verbose=verbose)
|
|
51
|
+
|
|
52
|
+
|
|
34
53
|
# ---------------------------------------------------------------------------
|
|
35
54
|
# Builtin skills (re-exported; owned by flowjet.core.bootstrap)
|
|
36
55
|
# ---------------------------------------------------------------------------
|
|
@@ -57,73 +76,6 @@ def apply_fj_defaults(config: SootheConfig) -> SootheConfig:
|
|
|
57
76
|
return apply_profile(config, CLI_PROFILE)
|
|
58
77
|
|
|
59
78
|
|
|
60
|
-
# ---------------------------------------------------------------------------
|
|
61
|
-
# CLI logging
|
|
62
|
-
# ---------------------------------------------------------------------------
|
|
63
|
-
|
|
64
|
-
_BROWSER_USE_SETUP_LOGGING = "BROWSER_USE_SETUP_LOGGING"
|
|
65
|
-
_FJ_CONSOLE_HANDLER = "fj-console"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class _CompactConsoleFormatter(logging.Formatter):
|
|
69
|
-
"""One-line console records without exception tracebacks."""
|
|
70
|
-
|
|
71
|
-
def formatException(self, ei: object) -> str: # noqa: N802 - logging API
|
|
72
|
-
return ""
|
|
73
|
-
|
|
74
|
-
def format(self, record: logging.LogRecord) -> str:
|
|
75
|
-
# logger.exception sets exc_info; drop it so format() stays one line.
|
|
76
|
-
record.exc_info = None
|
|
77
|
-
record.exc_text = None
|
|
78
|
-
return super().format(record)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def configure_cli_logging(*, verbose: bool = False) -> None:
|
|
82
|
-
"""Quiet the console for one-shot CLI use.
|
|
83
|
-
|
|
84
|
-
- Opt out of ``browser_use`` import-time root logger setup when unset.
|
|
85
|
-
- Remove existing root stream handlers (stderr/stdout) so init INFO
|
|
86
|
-
lines do not interleave with the agent answer.
|
|
87
|
-
- Prevent ``lastResort`` traceback dumps from soothe tool failures.
|
|
88
|
-
- When ``verbose``, show WARNING+ as single-line messages on stderr.
|
|
89
|
-
"""
|
|
90
|
-
os.environ.setdefault(_BROWSER_USE_SETUP_LOGGING, "false")
|
|
91
|
-
_remove_root_console_handlers()
|
|
92
|
-
root = logging.getLogger()
|
|
93
|
-
if verbose:
|
|
94
|
-
handler = logging.StreamHandler(sys.stderr)
|
|
95
|
-
handler.set_name(_FJ_CONSOLE_HANDLER)
|
|
96
|
-
handler.setLevel(logging.WARNING)
|
|
97
|
-
handler.setFormatter(_CompactConsoleFormatter("%(message)s"))
|
|
98
|
-
root.addHandler(handler)
|
|
99
|
-
elif not root.handlers:
|
|
100
|
-
null = logging.NullHandler()
|
|
101
|
-
null.set_name(_FJ_CONSOLE_HANDLER)
|
|
102
|
-
root.addHandler(null)
|
|
103
|
-
if root.level < logging.WARNING:
|
|
104
|
-
root.setLevel(logging.WARNING)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
def silence_after_plugins(*, verbose: bool = False) -> None:
|
|
108
|
-
"""Re-apply quieting after plugin imports (belt-and-suspenders)."""
|
|
109
|
-
configure_cli_logging(verbose=verbose)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def _remove_root_console_handlers() -> None:
|
|
113
|
-
root = logging.getLogger()
|
|
114
|
-
for handler in list(root.handlers):
|
|
115
|
-
if isinstance(handler, RotatingFileHandler):
|
|
116
|
-
continue
|
|
117
|
-
if isinstance(handler, logging.FileHandler):
|
|
118
|
-
continue
|
|
119
|
-
if isinstance(handler, logging.StreamHandler) or isinstance(handler, logging.NullHandler):
|
|
120
|
-
root.removeHandler(handler)
|
|
121
|
-
try:
|
|
122
|
-
handler.close()
|
|
123
|
-
except Exception: # pragma: no cover - defensive
|
|
124
|
-
pass
|
|
125
|
-
|
|
126
|
-
|
|
127
79
|
# ---------------------------------------------------------------------------
|
|
128
80
|
# Agent build
|
|
129
81
|
# ---------------------------------------------------------------------------
|
|
@@ -165,6 +117,7 @@ async def build_agent(
|
|
|
165
117
|
__all__ = [
|
|
166
118
|
"BUILTIN_SKILLS_DIR",
|
|
167
119
|
"FJ_CORE_SKILL_NAMES",
|
|
120
|
+
"_CompactConsoleFormatter",
|
|
168
121
|
"apply_fj_defaults",
|
|
169
122
|
"build_agent",
|
|
170
123
|
"configure_cli_logging",
|
|
@@ -8,18 +8,113 @@ from __future__ import annotations
|
|
|
8
8
|
import argparse
|
|
9
9
|
import asyncio
|
|
10
10
|
import contextlib
|
|
11
|
+
import logging
|
|
12
|
+
import os
|
|
11
13
|
import sys
|
|
12
14
|
from collections.abc import Coroutine
|
|
15
|
+
from logging.handlers import RotatingFileHandler
|
|
13
16
|
from pathlib import Path
|
|
14
17
|
from typing import Any
|
|
15
18
|
|
|
16
19
|
from flowjet.cli import __version__
|
|
17
|
-
from flowjet.cli.agent import configure_cli_logging
|
|
18
20
|
|
|
19
21
|
FORMAL_CLI = "flowjet"
|
|
20
22
|
CLI_ALIASES = frozenset({"fj", "fjf", FORMAL_CLI})
|
|
21
23
|
|
|
22
24
|
|
|
25
|
+
# ---------------------------------------------------------------------------
|
|
26
|
+
# CLI logging — stdlib only, kept here so ``fj -V`` / ``fj -h`` never pay the
|
|
27
|
+
# heavy ``soothe_nano`` / ``flowjet.core.bootstrap`` import cost.
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
_BROWSER_USE_SETUP_LOGGING = "BROWSER_USE_SETUP_LOGGING"
|
|
31
|
+
_FJ_CONSOLE_HANDLER = "fj-console"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class _CompactConsoleFormatter(logging.Formatter):
|
|
35
|
+
"""One-line console records without exception tracebacks."""
|
|
36
|
+
|
|
37
|
+
def formatException(self, ei: object) -> str: # noqa: N802 - logging API
|
|
38
|
+
return ""
|
|
39
|
+
|
|
40
|
+
def format(self, record: logging.LogRecord) -> str:
|
|
41
|
+
# logger.exception sets exc_info; drop it so format() stays one line.
|
|
42
|
+
record.exc_info = None
|
|
43
|
+
record.exc_text = None
|
|
44
|
+
return super().format(record)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
_FILE_LOGGING_INSTALLED = False
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def configure_cli_logging(*, verbose: bool = False) -> None:
|
|
51
|
+
"""Quiet the console for one-shot CLI use and enable file logging by default.
|
|
52
|
+
|
|
53
|
+
- Opt out of ``browser_use`` import-time root logger setup when unset.
|
|
54
|
+
- Remove existing root stream handlers (stderr/stdout) so init INFO
|
|
55
|
+
lines do not interleave with the agent answer.
|
|
56
|
+
- Prevent ``lastResort`` traceback dumps from soothe tool failures.
|
|
57
|
+
- When ``verbose``, show WARNING+ as single-line messages on stderr.
|
|
58
|
+
- Attach a rotating file handler at ``<FLOWJET_HOME>/logs/cli.log`` so
|
|
59
|
+
every CLI run is recorded by default (idempotent across re-invocations
|
|
60
|
+
within the same process, e.g. tests).
|
|
61
|
+
"""
|
|
62
|
+
os.environ.setdefault(_BROWSER_USE_SETUP_LOGGING, "false")
|
|
63
|
+
_remove_root_console_handlers()
|
|
64
|
+
root = logging.getLogger()
|
|
65
|
+
if verbose:
|
|
66
|
+
handler = logging.StreamHandler(sys.stderr)
|
|
67
|
+
handler.set_name(_FJ_CONSOLE_HANDLER)
|
|
68
|
+
handler.setLevel(logging.WARNING)
|
|
69
|
+
handler.setFormatter(_CompactConsoleFormatter("%(message)s"))
|
|
70
|
+
root.addHandler(handler)
|
|
71
|
+
elif not root.handlers:
|
|
72
|
+
null = logging.NullHandler()
|
|
73
|
+
null.set_name(_FJ_CONSOLE_HANDLER)
|
|
74
|
+
root.addHandler(null)
|
|
75
|
+
if root.level < logging.WARNING:
|
|
76
|
+
root.setLevel(logging.WARNING)
|
|
77
|
+
|
|
78
|
+
_ensure_cli_file_logging()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _ensure_cli_file_logging() -> None:
|
|
82
|
+
"""Attach the rotating file handler for CLI runs (idempotent)."""
|
|
83
|
+
global _FILE_LOGGING_INSTALLED
|
|
84
|
+
if _FILE_LOGGING_INSTALLED:
|
|
85
|
+
return
|
|
86
|
+
try:
|
|
87
|
+
from flowjet.core.home import cli_log_path, ensure_flowjet_home
|
|
88
|
+
|
|
89
|
+
ensure_flowjet_home()
|
|
90
|
+
from soothe_nano.logging.setup import setup_logging
|
|
91
|
+
|
|
92
|
+
setup_logging(log_file=str(cli_log_path()), extra_logger_names=("flowjet",))
|
|
93
|
+
_FILE_LOGGING_INSTALLED = True
|
|
94
|
+
except Exception: # pragma: no cover - logging must never break the CLI
|
|
95
|
+
pass
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def silence_after_plugins(*, verbose: bool = False) -> None:
|
|
99
|
+
"""Re-apply quieting after plugin imports (belt-and-suspenders)."""
|
|
100
|
+
configure_cli_logging(verbose=verbose)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _remove_root_console_handlers() -> None:
|
|
104
|
+
root = logging.getLogger()
|
|
105
|
+
for handler in list(root.handlers):
|
|
106
|
+
if isinstance(handler, RotatingFileHandler):
|
|
107
|
+
continue
|
|
108
|
+
if isinstance(handler, logging.FileHandler):
|
|
109
|
+
continue
|
|
110
|
+
if isinstance(handler, logging.StreamHandler) or isinstance(handler, logging.NullHandler):
|
|
111
|
+
root.removeHandler(handler)
|
|
112
|
+
try:
|
|
113
|
+
handler.close()
|
|
114
|
+
except Exception: # pragma: no cover - defensive
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
|
|
23
118
|
def resolve_cli_prog(argv0: str | None = None) -> str:
|
|
24
119
|
"""Return the invoked command name for help / version strings.
|
|
25
120
|
|
|
@@ -217,6 +312,13 @@ class _HelpFormatter(argparse.RawDescriptionHelpFormatter):
|
|
|
217
312
|
def __init__(self, prog: str) -> None:
|
|
218
313
|
super().__init__(prog, max_help_position=26, width=92)
|
|
219
314
|
|
|
315
|
+
def _format_action(self, action: argparse.Action) -> str: # type: ignore[override]
|
|
316
|
+
# Resolve lazy help strings only when help is actually rendered, so
|
|
317
|
+
# ``-V`` never pays for the import behind ``_default_config_help``.
|
|
318
|
+
if isinstance(action.help, _LazyHelp):
|
|
319
|
+
action.help = str(action.help)
|
|
320
|
+
return super()._format_action(action)
|
|
321
|
+
|
|
220
322
|
|
|
221
323
|
def _default_config_help() -> str:
|
|
222
324
|
from flowjet.cli.agent import default_config_path
|
|
@@ -224,6 +326,26 @@ def _default_config_help() -> str:
|
|
|
224
326
|
return f"Alternate nano.yml (default: {default_config_path()})"
|
|
225
327
|
|
|
226
328
|
|
|
329
|
+
class _LazyHelp:
|
|
330
|
+
"""Resolve a help-string callable only when argparse reads it.
|
|
331
|
+
|
|
332
|
+
``-V`` / ``-h``-without-our-flag paths never touch the help text, so the
|
|
333
|
+
heavy import behind ``_default_config_help`` stays deferred until a flag
|
|
334
|
+
that actually shows help (``-h``) or errors is invoked.
|
|
335
|
+
"""
|
|
336
|
+
|
|
337
|
+
__slots__ = ("_factory", "_cached")
|
|
338
|
+
|
|
339
|
+
def __init__(self, factory: Any) -> None:
|
|
340
|
+
self._factory = factory
|
|
341
|
+
self._cached: str | None = None
|
|
342
|
+
|
|
343
|
+
def __str__(self) -> str:
|
|
344
|
+
if self._cached is None:
|
|
345
|
+
self._cached = self._factory()
|
|
346
|
+
return self._cached
|
|
347
|
+
|
|
348
|
+
|
|
227
349
|
def _build_parser(prog: str | None = None) -> argparse.ArgumentParser:
|
|
228
350
|
cli_prog = prog or resolve_cli_prog()
|
|
229
351
|
parser = argparse.ArgumentParser(
|
|
@@ -297,7 +419,7 @@ def _build_parser(prog: str | None = None) -> argparse.ArgumentParser:
|
|
|
297
419
|
"-c",
|
|
298
420
|
"--config",
|
|
299
421
|
metavar="PATH",
|
|
300
|
-
help=_default_config_help
|
|
422
|
+
help=_LazyHelp(_default_config_help),
|
|
301
423
|
)
|
|
302
424
|
paths.add_argument(
|
|
303
425
|
"-w",
|
|
@@ -324,7 +446,7 @@ def _build_setup_parser(prog: str | None = None) -> argparse.ArgumentParser:
|
|
|
324
446
|
"-c",
|
|
325
447
|
"--config",
|
|
326
448
|
metavar="PATH",
|
|
327
|
-
help=_default_config_help
|
|
449
|
+
help=_LazyHelp(_default_config_help),
|
|
328
450
|
)
|
|
329
451
|
return parser
|
|
330
452
|
|
|
@@ -565,8 +687,17 @@ def main_follow(argv: list[str] | None = None) -> int:
|
|
|
565
687
|
|
|
566
688
|
def main(argv: list[str] | None = None) -> int:
|
|
567
689
|
try:
|
|
568
|
-
|
|
690
|
+
# Align SOOTHE_HOME with FLOWJET_HOME before any soothe import so
|
|
691
|
+
# config, data, and logs all land under ~/.flowjet. Must run first:
|
|
692
|
+
# soothe_sdk.paths binds SOOTHE_HOME at import time.
|
|
693
|
+
from flowjet.core.home import ensure_flowjet_home
|
|
694
|
+
|
|
695
|
+
ensure_flowjet_home()
|
|
696
|
+
# Parse first so ``-V`` / ``-h`` / ``--help`` exit before we touch the
|
|
697
|
+
# logging stack (and the heavy ``flowjet.cli.agent`` import it used to
|
|
698
|
+
# drag in). Version/help must stay instant.
|
|
569
699
|
args = parse_args(argv)
|
|
700
|
+
configure_cli_logging()
|
|
570
701
|
# Re-apply after parse so ``-v`` can enable compact console warnings.
|
|
571
702
|
if getattr(args, "verbose", False):
|
|
572
703
|
configure_cli_logging(verbose=True)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Align ``SOOTHE_HOME`` with ``FLOWJET_HOME`` and enable file logging by default.
|
|
2
|
+
|
|
3
|
+
FlowJet ships its own home directory (``~/.flowjet``) distinct from Soothe's
|
|
4
|
+
default (``~/.soothe``). Soothe-nano reads ``SOOTHE_HOME`` once at import time
|
|
5
|
+
(``soothe_sdk.paths``), so this module must run *before* any soothe import.
|
|
6
|
+
|
|
7
|
+
Call :func:`ensure_flowjet_home` at the top of every entry point
|
|
8
|
+
(``flowjet.cli.cli.main``, ``flowjet.server.__main__.main``). It is idempotent
|
|
9
|
+
and safe to call from tests.
|
|
10
|
+
|
|
11
|
+
Resolution order for the shared home:
|
|
12
|
+
1. ``FLOWJET_HOME`` env var (if set)
|
|
13
|
+
2. ``SOOTHE_HOME`` env var (if set) — honours an operator who pinned Soothe's home
|
|
14
|
+
3. ``~/.flowjet`` (default)
|
|
15
|
+
|
|
16
|
+
When ``SOOTHE_HOME`` is unset or still points at the Soothe default
|
|
17
|
+
(``~/.soothe``), it is repointed at the resolved FlowJet home so config, data,
|
|
18
|
+
and logs all land under one root.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import logging
|
|
24
|
+
import os
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
_DEFAULT_SOOTHE_HOME = str(Path.home() / ".soothe")
|
|
30
|
+
_DEFAULT_FLOWJET_HOME = str(Path.home() / ".flowjet")
|
|
31
|
+
|
|
32
|
+
_ALIGNED = False
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def resolve_home() -> Path:
|
|
36
|
+
"""Return the shared home directory for FlowJet and Soothe.
|
|
37
|
+
|
|
38
|
+
Priority: ``FLOWJET_HOME`` > ``SOOTHE_HOME`` > ``~/.flowjet``.
|
|
39
|
+
"""
|
|
40
|
+
env_fj = os.environ.get("FLOWJET_HOME")
|
|
41
|
+
if env_fj:
|
|
42
|
+
return Path(env_fj).expanduser()
|
|
43
|
+
env_soothe = os.environ.get("SOOTHE_HOME")
|
|
44
|
+
if env_soothe and env_soothe != _DEFAULT_SOOTHE_HOME:
|
|
45
|
+
return Path(env_soothe).expanduser()
|
|
46
|
+
return Path(_DEFAULT_FLOWJET_HOME).expanduser()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def ensure_flowjet_home() -> Path:
|
|
50
|
+
"""Align ``SOOTHE_HOME`` with the FlowJet home and create the logs dir.
|
|
51
|
+
|
|
52
|
+
Idempotent. Returns the resolved home path. Safe to call before any soothe
|
|
53
|
+
module is imported — and it *must* be, because ``soothe_sdk.paths`` binds
|
|
54
|
+
``SOOTHE_HOME`` at import time.
|
|
55
|
+
"""
|
|
56
|
+
global _ALIGNED
|
|
57
|
+
home = resolve_home()
|
|
58
|
+
|
|
59
|
+
# Repoint SOOTHE_HOME at the FlowJet home unless an operator has already
|
|
60
|
+
# pinned it somewhere other than the Soothe default. ``setdefault`` keeps
|
|
61
|
+
# an explicit SOOTHE_HOME that is not the default.
|
|
62
|
+
current_soothe = os.environ.get("SOOTHE_HOME")
|
|
63
|
+
if current_soothe is None or current_soothe == _DEFAULT_SOOTHE_HOME:
|
|
64
|
+
os.environ["SOOTHE_HOME"] = str(home)
|
|
65
|
+
|
|
66
|
+
# SOOTHE_DATA_DIR follows SOOTHE_HOME/data by default in soothe_sdk.paths;
|
|
67
|
+
# only set it when unset so an explicit operator override wins.
|
|
68
|
+
os.environ.setdefault("SOOTHE_DATA_DIR", str(home / "data"))
|
|
69
|
+
|
|
70
|
+
# Ensure the logs directory exists so file handlers never fail on first write.
|
|
71
|
+
(home / "logs").mkdir(parents=True, exist_ok=True)
|
|
72
|
+
|
|
73
|
+
_ALIGNED = True
|
|
74
|
+
return home
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def flowjet_home() -> Path:
|
|
78
|
+
"""Return the aligned FlowJet home (aligns on first call if not yet done)."""
|
|
79
|
+
if not _ALIGNED:
|
|
80
|
+
return ensure_flowjet_home()
|
|
81
|
+
return resolve_home()
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def log_dir() -> Path:
|
|
85
|
+
"""Return the log directory under the FlowJet home."""
|
|
86
|
+
return flowjet_home() / "logs"
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def cli_log_path() -> Path:
|
|
90
|
+
"""Return the CLI log file path (``<home>/logs/cli.log``)."""
|
|
91
|
+
return log_dir() / "cli.log"
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def setup_file_logging(
|
|
95
|
+
*,
|
|
96
|
+
log_file: str | Path | None = None,
|
|
97
|
+
extra_logger_names: tuple[str, ...] = (),
|
|
98
|
+
) -> None:
|
|
99
|
+
"""Configure rotating file logging under the FlowJet home.
|
|
100
|
+
|
|
101
|
+
Delegates to ``soothe_nano.logging.setup.setup_logging`` so the FlowJet
|
|
102
|
+
logger trees share the same rotating handler, formatter, and thread-id
|
|
103
|
+
context as Soothe. The default log file is ``<home>/logs/flowjet.log``;
|
|
104
|
+
pass ``log_file`` to override (e.g. ``cli.log`` for the CLI surface).
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
log_file: Optional log file path override.
|
|
108
|
+
extra_logger_names: Additional logger tree roots (e.g. ``("flowjet",)``)
|
|
109
|
+
to attach the same file handler to.
|
|
110
|
+
"""
|
|
111
|
+
ensure_flowjet_home()
|
|
112
|
+
from soothe_nano.logging.setup import setup_logging
|
|
113
|
+
|
|
114
|
+
target = str(log_file) if log_file is not None else str(log_dir() / "flowjet.log")
|
|
115
|
+
# FlowJet's own logger trees share the handler with soothe_nano's.
|
|
116
|
+
names: tuple[str, ...] = ("flowjet", *extra_logger_names)
|
|
117
|
+
setup_logging(log_file=target, extra_logger_names=names)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
__all__ = [
|
|
121
|
+
"cli_log_path",
|
|
122
|
+
"ensure_flowjet_home",
|
|
123
|
+
"flowjet_home",
|
|
124
|
+
"log_dir",
|
|
125
|
+
"resolve_home",
|
|
126
|
+
"setup_file_logging",
|
|
127
|
+
]
|
|
@@ -35,6 +35,15 @@ def _create_dual_stack_socket(host: str, port: int) -> socket.socket:
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
def main() -> None:
|
|
38
|
+
# Align SOOTHE_HOME with FLOWJET_HOME before any soothe import so config,
|
|
39
|
+
# data, and logs all land under ~/.flowjet. Must run before Settings() or
|
|
40
|
+
# any soothe_nano import: soothe_sdk.paths binds SOOTHE_HOME at import time.
|
|
41
|
+
from flowjet.core.home import ensure_flowjet_home, setup_file_logging
|
|
42
|
+
|
|
43
|
+
ensure_flowjet_home()
|
|
44
|
+
# Record server runs to <FLOWJET_HOME>/logs/flowjet.log by default.
|
|
45
|
+
setup_file_logging(extra_logger_names=("flowjet",))
|
|
46
|
+
|
|
38
47
|
settings = Settings()
|
|
39
48
|
# When the host is a wildcard (``::`` or ``0.0.0.0``), use a dual-stack
|
|
40
49
|
# socket so both IPv4 and IPv6 clients can connect. This is essential
|
|
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.3 → flowjet-2.0.4}/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.3 → flowjet-2.0.4}/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.3 → flowjet-2.0.4}/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.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/patterns/loop.json
RENAMED
|
File without changes
|
|
File without changes
|
{flowjet-2.0.3 → flowjet-2.0.4}/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.3 → flowjet-2.0.4}/src/flowjet/builtin_skills/research-bootstrap/references/backends.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flowjet-2.0.3 → flowjet-2.0.4}/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
|