flowjet 2.0.0__tar.gz → 2.0.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.

Potentially problematic release.


This version of flowjet might be problematic. Click here for more details.

Files changed (171) hide show
  1. {flowjet-2.0.0 → flowjet-2.0.2}/CHANGELOG.md +49 -0
  2. flowjet-2.0.2/PKG-INFO +195 -0
  3. flowjet-2.0.2/README.md +151 -0
  4. {flowjet-2.0.0 → flowjet-2.0.2}/docs/naming.md +2 -2
  5. flowjet-2.0.2/docs/server.md +136 -0
  6. {flowjet-2.0.0 → flowjet-2.0.2}/docs/specs/RFC-003-production-isolation-hardening.md +10 -4
  7. {flowjet-2.0.0 → flowjet-2.0.2}/pyproject.toml +7 -4
  8. flowjet-2.0.2/src/flowjet/core/backend.py +107 -0
  9. flowjet-2.0.2/src/flowjet/core/bootstrap.py +310 -0
  10. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/bridges/nano/adapter.py +7 -6
  11. flowjet-2.0.2/src/flowjet/core/identity.py +140 -0
  12. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/modes.py +36 -7
  13. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/acp/agent.py +34 -1
  14. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/config.py +11 -1
  15. flowjet-2.0.0/PKG-INFO +0 -288
  16. flowjet-2.0.0/README.md +0 -245
  17. flowjet-2.0.0/src/flowjet/core/bootstrap.py +0 -183
  18. {flowjet-2.0.0 → flowjet-2.0.2}/.gitignore +0 -0
  19. {flowjet-2.0.0 → flowjet-2.0.2}/LICENSE +0 -0
  20. {flowjet-2.0.0 → flowjet-2.0.2}/config/nano.yml +0 -0
  21. {flowjet-2.0.0 → flowjet-2.0.2}/deploy/README.md +0 -0
  22. {flowjet-2.0.0 → flowjet-2.0.2}/deploy/nano.yml +0 -0
  23. {flowjet-2.0.0 → flowjet-2.0.2}/docs/completion-design.md +0 -0
  24. {flowjet-2.0.0 → flowjet-2.0.2}/docs/drafts/README.md +0 -0
  25. {flowjet-2.0.0 → flowjet-2.0.2}/docs/drafts/api-spec.md +0 -0
  26. {flowjet-2.0.0 → flowjet-2.0.2}/docs/impl/IG-001-openai-compatible-server.md +0 -0
  27. {flowjet-2.0.0 → flowjet-2.0.2}/docs/impl/IG-002-isolated-thread-pool-runtime.md +0 -0
  28. {flowjet-2.0.0 → flowjet-2.0.2}/docs/impl/IG-003-production-isolation-hardening.md +0 -0
  29. {flowjet-2.0.0 → flowjet-2.0.2}/docs/impl/README.md +0 -0
  30. {flowjet-2.0.0 → flowjet-2.0.2}/docs/impl/TEST-COVERAGE-MATRIX.md +0 -0
  31. {flowjet-2.0.0 → flowjet-2.0.2}/docs/specs/RFC-001-openai-compatible-api.md +0 -0
  32. {flowjet-2.0.0 → flowjet-2.0.2}/docs/specs/RFC-002-isolated-thread-pool-runtime.md +0 -0
  33. {flowjet-2.0.0 → flowjet-2.0.2}/docs/specs/RFC-004-unified-package.md +0 -0
  34. {flowjet-2.0.0 → flowjet-2.0.2}/docs/specs/rfc-history.md +0 -0
  35. {flowjet-2.0.0 → flowjet-2.0.2}/docs/specs/rfc-index.md +0 -0
  36. {flowjet-2.0.0 → flowjet-2.0.2}/docs/specs/rfc-namings.md +0 -0
  37. {flowjet-2.0.0 → flowjet-2.0.2}/docs/specs/templates/architecture-design.md +0 -0
  38. {flowjet-2.0.0 → flowjet-2.0.2}/docs/specs/templates/conceptual-design.md +0 -0
  39. {flowjet-2.0.0 → flowjet-2.0.2}/docs/specs/templates/impl-interface-design.md +0 -0
  40. {flowjet-2.0.0 → flowjet-2.0.2}/docs/specs/templates/rfc-standard.md +0 -0
  41. {flowjet-2.0.0 → flowjet-2.0.2}/docs/specs/templates/rfc-template.md +0 -0
  42. {flowjet-2.0.0 → flowjet-2.0.2}/docs/upgrade.md +0 -0
  43. {flowjet-2.0.0 → flowjet-2.0.2}/examples/README.md +0 -0
  44. {flowjet-2.0.0 → flowjet-2.0.2}/nano.yml +0 -0
  45. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/__init__.py +0 -0
  46. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/__main__.py +0 -0
  47. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/README.md +0 -0
  48. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/gws-drive/SKILL.md +0 -0
  49. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/gws-drive-upload/SKILL.md +0 -0
  50. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/logo-generator-skill/.env.example +0 -0
  51. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/logo-generator-skill/README.md +0 -0
  52. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/logo-generator-skill/SKILL.md +0 -0
  53. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/logo-generator-skill/assets/background_library.html +0 -0
  54. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/logo-generator-skill/assets/showcase_template.html +0 -0
  55. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/logo-generator-skill/references/background_styles.md +0 -0
  56. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/logo-generator-skill/references/design_patterns.md +0 -0
  57. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/logo-generator-skill/references/webgl_backgrounds.md +0 -0
  58. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/logo-generator-skill/requirements.txt +0 -0
  59. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/logo-generator-skill/scripts/generate_showcase.py +0 -0
  60. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/logo-generator-skill/scripts/svg_to_png.py +0 -0
  61. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/SKILL.md +0 -0
  62. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/brainstorming/spec-document-reviewer-prompt.md +0 -0
  63. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/implementation/coding-plan-template.md +0 -0
  64. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/implementation/impl-guide-template.md +0 -0
  65. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/review/pr-review-template.md +0 -0
  66. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/review/review-checklist.md +0 -0
  67. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/specs/rfc-template.md +0 -0
  68. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/specs/template-architecture-design.md +0 -0
  69. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/specs/template-conceptual-design.md +0 -0
  70. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/specs/template-impl-interface-design.md +0 -0
  71. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-drafts-readme.md +0 -0
  72. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-impl-readme.md +0 -0
  73. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-platonic.yml +0 -0
  74. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-rfc-history.md +0 -0
  75. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-rfc-index.md +0 -0
  76. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-rfc-namings.md +0 -0
  77. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/assets/templates/template-rfc-standard.md +0 -0
  78. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/BRAINSTORM/brainstorm.md +0 -0
  79. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-code.md +0 -0
  80. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-create-guide.md +0 -0
  81. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-full.md +0 -0
  82. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-update-guide.md +0 -0
  83. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/IMPL/impl-validate-guide.md +0 -0
  84. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-plan-modular-specs.md +0 -0
  85. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-recover-architecture.md +0 -0
  86. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-recover-conceptual.md +0 -0
  87. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-recover-impl-interface.md +0 -0
  88. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-scaffold.md +0 -0
  89. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/INIT/init-scan.md +0 -0
  90. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/REFERENCE.md +0 -0
  91. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/REVIEW/review-spec-compliance.md +0 -0
  92. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-check-compliance.md +0 -0
  93. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-check-taxonomy.md +0 -0
  94. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-generate-history.md +0 -0
  95. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-generate-index.md +0 -0
  96. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-generate-namings.md +0 -0
  97. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-refine.md +0 -0
  98. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/SPECS/specs-validate-consistency.md +0 -0
  99. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/WORKFLOW/workflow-overview.md +0 -0
  100. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/WORKFLOW/workflow-phase-1.md +0 -0
  101. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/WORKFLOW/workflow-phase-2.md +0 -0
  102. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/platonic-coding/references/WORKFLOW/workflow-phase-3.md +0 -0
  103. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/SKILL.md +0 -0
  104. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/patterns/evidence-deep.json +0 -0
  105. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/patterns/evidence-first.json +0 -0
  106. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/patterns/idea-first.json +0 -0
  107. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/patterns/loop.json +0 -0
  108. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/patterns/paper-pipeline.json +0 -0
  109. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/patterns/rapid.json +0 -0
  110. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/patterns/rigor-first.json +0 -0
  111. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/patterns/stance-first.json +0 -0
  112. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/patterns/systematic-review.json +0 -0
  113. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/patterns/verify-loop.json +0 -0
  114. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/references/backends.md +0 -0
  115. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/references/handoff-ars-omr.md +0 -0
  116. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/references/handoff-omr-ars.md +0 -0
  117. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/references/routing.md +0 -0
  118. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/scripts/csljson_to_omr.py +0 -0
  119. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/builtin_skills/research-bootstrap/scripts/papers_index_to_csljson.py +0 -0
  120. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/__init__.py +0 -0
  121. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/__main__.py +0 -0
  122. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/agent.py +0 -0
  123. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/cli.py +0 -0
  124. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/completion/__init__.py +0 -0
  125. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/completion/context.py +0 -0
  126. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/completion/engine.py +0 -0
  127. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/doctor_cmd.py +0 -0
  128. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/doctor_fix_cmd.py +0 -0
  129. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/progress.py +0 -0
  130. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/serve_cmd.py +0 -0
  131. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/setup_cmd.py +0 -0
  132. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/shell/__init__.py +0 -0
  133. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/shell/_fj.zsh +0 -0
  134. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/shell/fj.bash +0 -0
  135. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/stream.py +0 -0
  136. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/threads.py +0 -0
  137. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/cli/tool_stream.py +0 -0
  138. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/__init__.py +0 -0
  139. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/backends/__init__.py +0 -0
  140. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/backends/direct.py +0 -0
  141. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/backends/fake.py +0 -0
  142. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/backends/isolation/__init__.py +0 -0
  143. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/backends/isolation/adapter.py +0 -0
  144. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/backends/isolation/admission.py +0 -0
  145. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/backends/isolation/backend.py +0 -0
  146. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/backends/isolation/errors.py +0 -0
  147. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/backends/isolation/mode_gate.py +0 -0
  148. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/backends/isolation/pool.py +0 -0
  149. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/backends/isolation/request.py +0 -0
  150. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/backends/isolation/workspace.py +0 -0
  151. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/bridges/nano/__init__.py +0 -0
  152. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/bridges/nano/backend.py +0 -0
  153. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/bridges/nano/mapping.py +0 -0
  154. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/events.py +0 -0
  155. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/protocol.py +0 -0
  156. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/tool_results.py +0 -0
  157. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/core/tool_stream.py +0 -0
  158. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/__init__.py +0 -0
  159. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/__main__.py +0 -0
  160. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/acp/__init__.py +0 -0
  161. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/acp/routes.py +0 -0
  162. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/http/__init__.py +0 -0
  163. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/http/app.py +0 -0
  164. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/http/auth.py +0 -0
  165. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/openai_compat/__init__.py +0 -0
  166. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/openai_compat/errors.py +0 -0
  167. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/openai_compat/projection.py +0 -0
  168. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/openai_compat/routes.py +0 -0
  169. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/openai_compat/schemas.py +0 -0
  170. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/openai_compat/service.py +0 -0
  171. {flowjet-2.0.0 → flowjet-2.0.2}/src/flowjet/server/openai_compat/store.py +0 -0
@@ -8,6 +8,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  > History from 0.1.0–0.2.0 below was released as the separate `flowjet-server`
9
9
  > distribution, now merged into `flowjet`. See [docs/upgrade.md](docs/upgrade.md).
10
10
 
11
+ ## [Unreleased]
12
+
13
+ ## [2.0.2] — 2026-09-18
14
+
15
+ ### Added
16
+
17
+ - **Duo backends — `soothe` or `soothe-nano`.** `FLOWJET_BACKEND` (CLI, default
18
+ `soothe`) and `FLOWJET_SERVER_BACKEND` (HTTP/ACP, default `nano`) select which
19
+ runtime builds the agent. `soothe` is a host layer over soothe-nano, so the
20
+ engine stays installed either way; the two surfaces switch independently
21
+ because the server needs a dual-mode agent (AGENT + ASK graphs per request),
22
+ which soothe does not expose — with `FLOWJET_SERVER_BACKEND=soothe` the server
23
+ builds one host agent per mode and routes on `interaction_mode`.
24
+
25
+ ### Changed
26
+
27
+ - The CLI now builds its agent through the `soothe` host runtime by default
28
+ (host middleware, `request_plan_mode` / `ask_user` tools, configurable
29
+ persona). Set `FLOWJET_BACKEND=nano` for the previous behaviour.
30
+
31
+ ## [2.0.1] — 2026-09-17
32
+
33
+ ### Added
34
+
35
+ - **ACP sessions run in the client's directory.** `FlowJetAcpAgent` now records
36
+ the `cwd` from `session/new`, `session/load`, `session/resume` and
37
+ `session/fork` and forwards it as the run's `metadata.workspace`. Previously
38
+ the client `cwd` was accepted and discarded, so every ACP session ran in a
39
+ hashed workspace under `FLOWJET_HOME`.
40
+
41
+ ### Changed
42
+
43
+ - **The assistant identifies as FlowJet, not Soothe.** soothe-nano prepends its
44
+ own `<ASSISTANT_IDENTITY>` block — "a helpful AI assistant" named `Soothe` —
45
+ to every system prompt tier, and only parameterises it by `agent.name`.
46
+ `flowjet.core.identity` now installs a FlowJet template (coding agent, creator
47
+ line, and an explicit "never identify as Soothe / soothe-nano / Claude /
48
+ ChatGPT / Gemini / Anthropic / OpenAI / Google" rule) and `apply_profile`
49
+ defaults `agent.name` to `FlowJet` on both the CLI and server surfaces. An
50
+ explicit `agent.name` or `agent.system_prompt` in `nano.yml` still wins.
51
+ - **Workspace resolution is caller-driven by default.**
52
+ `FLOWJET_ALLOW_EXTERNAL_WORKSPACE` now defaults to `true`, so a workspace
53
+ outside `FLOWJET_HOME` is honoured rather than rejected. This is not a
54
+ sandbox escape — tools remain confined to whichever workspace is selected
55
+ (`allow_paths_outside_workspace` is still `false`); the boundary moves to the
56
+ caller's directory instead of disappearing. Set
57
+ `FLOWJET_ALLOW_EXTERNAL_WORKSPACE=false` to restore forced hashed
58
+ per-session workspaces.
59
+
11
60
  ## [2.0.0] — 2026-09-17 — unified CLI + server
12
61
 
13
62
  **Breaking.** `flowjet-server` is merged into this repository and ships as one
flowjet-2.0.2/PKG-INFO ADDED
@@ -0,0 +1,195 @@
1
+ Metadata-Version: 2.5
2
+ Name: flowjet
3
+ Version: 2.0.2
4
+ Summary: FlowJet — agent CLI (fj) and server (ACP + OpenAI-compatible HTTP) powered by soothe-nano
5
+ Project-URL: Homepage, https://github.com/caesar0301/flowjet
6
+ Project-URL: Repository, https://github.com/caesar0301/flowjet
7
+ Project-URL: Issues, https://github.com/caesar0301/flowjet/issues
8
+ Author: Xiaming Chen
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: acp,agent,ai,cli,coding-agent,fj,flowjet,nano,openai,server,soothe
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Environment :: Web Environment
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Requires-Python: <3.15,>=3.11
25
+ Requires-Dist: soothe-nano<1.3.0,>=1.2.28
26
+ Requires-Dist: soothe<2.0.0,>=1.0.12
27
+ Provides-Extra: dev
28
+ Requires-Dist: httpx>=0.27.0; extra == 'dev'
29
+ Requires-Dist: mypy>=1.0.0; extra == 'dev'
30
+ Requires-Dist: openai>=2.51.0; extra == 'dev'
31
+ Requires-Dist: pytest-asyncio>=1.3.0; extra == 'dev'
32
+ Requires-Dist: pytest-cov; extra == 'dev'
33
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
34
+ Requires-Dist: ruff>=0.12.0; extra == 'dev'
35
+ Requires-Dist: twine>=5.0.0; extra == 'dev'
36
+ Provides-Extra: server
37
+ Requires-Dist: agent-client-protocol[http]<1.0.0,>=0.12.1; extra == 'server'
38
+ Requires-Dist: fastapi>=0.115.0; extra == 'server'
39
+ Requires-Dist: langchain-core>=0.3; extra == 'server'
40
+ Requires-Dist: pydantic-settings>=2.0; extra == 'server'
41
+ Requires-Dist: pydantic>=2.0; extra == 'server'
42
+ Requires-Dist: uvicorn[standard]>=0.32.0; extra == 'server'
43
+ Description-Content-Type: text/markdown
44
+
45
+ # FlowJet
46
+
47
+ [![PyPI version](https://img.shields.io/pypi/v/flowjet.svg)](https://pypi.org/p/flowjet)
48
+ [![Python versions](https://img.shields.io/pypi/pyversions/flowjet.svg)](https://pypi.org/p/flowjet)
49
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
50
+
51
+ **FlowJet** is a coding agent you can run two ways:
52
+
53
+ - **`fj`** — ask a question in your terminal, get an answer. No UI, no context-switching.
54
+ - **`flowjet-server`** — the same agent as a service: **ACP** over WebSocket and an **OpenAI-compatible HTTP API**, so any OpenAI SDK can drive it.
55
+
56
+ It runs on [soothe-nano](https://github.com/mirasoth/soothe-nano) — tools, skills, MCP, subagents — with SQLite persistence, so every conversation is resumable.
57
+
58
+ ---
59
+
60
+ ## Install
61
+
62
+ ```bash
63
+ pip install flowjet # CLI
64
+ pip install 'flowjet[server]' # CLI + HTTP service
65
+ ```
66
+
67
+ Requires Python 3.11+. The server is an optional extra — installing just `flowjet` pulls a single runtime dependency.
68
+
69
+ ## Configure
70
+
71
+ ```bash
72
+ fj setup # guided: pick a local or hosted model
73
+ # or, with no config file at all:
74
+ export OPENAI_API_KEY=sk-...
75
+ fj summarize README.md
76
+ ```
77
+
78
+ `fj setup` writes `~/.soothe/config/nano.yml`. Without it, FlowJet falls back to `OPENAI_API_KEY` or `ANTHROPIC_API_KEY`.
79
+
80
+ Not sure your machine is ready? `fj doctor` (add `--deep`, `--live-llm`).
81
+
82
+ ### Backends
83
+
84
+ Two runtimes can build the agent; they are switched independently per surface:
85
+
86
+ | Env var | Surface | Default | Values |
87
+ |---------|---------|---------|--------|
88
+ | `FLOWJET_BACKEND` | CLI (`fj`) | `soothe` | `soothe`, `nano` |
89
+ | `FLOWJET_SERVER_BACKEND` | `flowjet-server` / `fj serve` | `nano` | `soothe`, `nano` |
90
+
91
+ `soothe` is the host runtime (extra middleware and tools over the same
92
+ soothe-nano engine). The server defaults to `nano` because it needs a dual-mode
93
+ agent — AGENT and ASK graphs selected per request — which `soothe` does not
94
+ expose yet; on `soothe` the server builds one host agent per mode instead.
95
+
96
+ ---
97
+
98
+ ## CLI
99
+
100
+ ```bash
101
+ fj explain this repo
102
+ fj -f and now add tests # continue this project's latest conversation
103
+ fjf what did we decide? # short alias of fj -f
104
+ fj -l # list recent conversations
105
+ ```
106
+
107
+ | Flag | Meaning |
108
+ |------|---------|
109
+ | `-f` / `--follow` | Continue the latest thread in this project |
110
+ | `-t ID` / `--thread` | Continue (or pin) a specific thread — overrides `-f` |
111
+ | `-l` / `--list` | List recent threads (newest first) |
112
+ | `-n NUM` | How many threads `-l` shows (`0` = all) |
113
+ | `-a` / `--ask` | Read-only: answer without touching files |
114
+ | `-v` / `--verbose` | Mirror tool calls on stderr |
115
+ | `-c PATH` / `-w DIR` | Alternate `nano.yml` / workspace root |
116
+
117
+ `-f` is scoped to your current project, so work in other checkouts never hijacks your thread.
118
+
119
+ Enable shell completion (predicts full queries, not just flags):
120
+
121
+ ```bash
122
+ eval "$(fj completion zsh)" # or: fj completion bash
123
+ ```
124
+
125
+ ---
126
+
127
+ ## Server
128
+
129
+ ```bash
130
+ flowjet-server # host :: (dual-stack), port 8618
131
+ fj serve --port 8618 # same, from the CLI
132
+ ```
133
+
134
+ ```python
135
+ from openai import OpenAI
136
+
137
+ client = OpenAI(api_key="local", base_url="http://127.0.0.1:8618/v1")
138
+ print(client.responses.create(model="default", input="Hello"))
139
+ ```
140
+
141
+ | Endpoint | Purpose |
142
+ |----------|---------|
143
+ | `POST /v1/responses` | Create a response (`stream=true` → SSE) |
144
+ | `GET` / `DELETE /v1/responses/{id}` | Retrieve / cancel |
145
+ | `POST /v1/chat/completions` | Chat Completions (non-stream + SSE) |
146
+ | `GET /v1/models` | Model ids |
147
+ | `GET /health` | Liveness |
148
+ | `WS /acp` | Agent Client Protocol |
149
+
150
+ Per-request options go in `extra_body.flowjet`:
151
+
152
+ | Field | Values | Meaning |
153
+ |-------|--------|---------|
154
+ | `session` | string | Isolates workspace + conversation thread |
155
+ | `interaction_mode` | `agent` (default) \| `ask` | `ask` is hard read-only |
156
+ | `projection` | `report` \| `progress` \| `developer` | How much SSE detail to expose |
157
+
158
+ Full configuration, environment variables and the security model: [docs/server.md](docs/server.md) · deployment: [deploy/README.md](deploy/README.md).
159
+
160
+ ---
161
+
162
+ ## Extend
163
+
164
+ Add skills and MCP servers in `nano.yml`:
165
+
166
+ ```yaml
167
+ skills:
168
+ - ~/.soothe/skills/my-reviewer
169
+
170
+ mcp_servers:
171
+ - name: filesystem
172
+ transport: stdio
173
+ command: npx
174
+ args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
175
+ ```
176
+
177
+ Skills are `SKILL.md` files loaded on demand; MCP tools activate on demand by default (`defer: true`).
178
+
179
+ ---
180
+
181
+ ## Development
182
+
183
+ ```bash
184
+ git clone https://github.com/caesar0301/flowjet.git
185
+ cd flowjet
186
+ make sync-dev && make test && make lint
187
+ ```
188
+
189
+ ## Upgrading from 1.x
190
+
191
+ Version 2.0 merges the former `flowjet-server` project into this one. The distribution is now `flowjet` and import paths changed. See [docs/upgrade.md](docs/upgrade.md).
192
+
193
+ ## License
194
+
195
+ MIT
@@ -0,0 +1,151 @@
1
+ # FlowJet
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/flowjet.svg)](https://pypi.org/p/flowjet)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/flowjet.svg)](https://pypi.org/p/flowjet)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
+
7
+ **FlowJet** is a coding agent you can run two ways:
8
+
9
+ - **`fj`** — ask a question in your terminal, get an answer. No UI, no context-switching.
10
+ - **`flowjet-server`** — the same agent as a service: **ACP** over WebSocket and an **OpenAI-compatible HTTP API**, so any OpenAI SDK can drive it.
11
+
12
+ It runs on [soothe-nano](https://github.com/mirasoth/soothe-nano) — tools, skills, MCP, subagents — with SQLite persistence, so every conversation is resumable.
13
+
14
+ ---
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ pip install flowjet # CLI
20
+ pip install 'flowjet[server]' # CLI + HTTP service
21
+ ```
22
+
23
+ Requires Python 3.11+. The server is an optional extra — installing just `flowjet` pulls a single runtime dependency.
24
+
25
+ ## Configure
26
+
27
+ ```bash
28
+ fj setup # guided: pick a local or hosted model
29
+ # or, with no config file at all:
30
+ export OPENAI_API_KEY=sk-...
31
+ fj summarize README.md
32
+ ```
33
+
34
+ `fj setup` writes `~/.soothe/config/nano.yml`. Without it, FlowJet falls back to `OPENAI_API_KEY` or `ANTHROPIC_API_KEY`.
35
+
36
+ Not sure your machine is ready? `fj doctor` (add `--deep`, `--live-llm`).
37
+
38
+ ### Backends
39
+
40
+ Two runtimes can build the agent; they are switched independently per surface:
41
+
42
+ | Env var | Surface | Default | Values |
43
+ |---------|---------|---------|--------|
44
+ | `FLOWJET_BACKEND` | CLI (`fj`) | `soothe` | `soothe`, `nano` |
45
+ | `FLOWJET_SERVER_BACKEND` | `flowjet-server` / `fj serve` | `nano` | `soothe`, `nano` |
46
+
47
+ `soothe` is the host runtime (extra middleware and tools over the same
48
+ soothe-nano engine). The server defaults to `nano` because it needs a dual-mode
49
+ agent — AGENT and ASK graphs selected per request — which `soothe` does not
50
+ expose yet; on `soothe` the server builds one host agent per mode instead.
51
+
52
+ ---
53
+
54
+ ## CLI
55
+
56
+ ```bash
57
+ fj explain this repo
58
+ fj -f and now add tests # continue this project's latest conversation
59
+ fjf what did we decide? # short alias of fj -f
60
+ fj -l # list recent conversations
61
+ ```
62
+
63
+ | Flag | Meaning |
64
+ |------|---------|
65
+ | `-f` / `--follow` | Continue the latest thread in this project |
66
+ | `-t ID` / `--thread` | Continue (or pin) a specific thread — overrides `-f` |
67
+ | `-l` / `--list` | List recent threads (newest first) |
68
+ | `-n NUM` | How many threads `-l` shows (`0` = all) |
69
+ | `-a` / `--ask` | Read-only: answer without touching files |
70
+ | `-v` / `--verbose` | Mirror tool calls on stderr |
71
+ | `-c PATH` / `-w DIR` | Alternate `nano.yml` / workspace root |
72
+
73
+ `-f` is scoped to your current project, so work in other checkouts never hijacks your thread.
74
+
75
+ Enable shell completion (predicts full queries, not just flags):
76
+
77
+ ```bash
78
+ eval "$(fj completion zsh)" # or: fj completion bash
79
+ ```
80
+
81
+ ---
82
+
83
+ ## Server
84
+
85
+ ```bash
86
+ flowjet-server # host :: (dual-stack), port 8618
87
+ fj serve --port 8618 # same, from the CLI
88
+ ```
89
+
90
+ ```python
91
+ from openai import OpenAI
92
+
93
+ client = OpenAI(api_key="local", base_url="http://127.0.0.1:8618/v1")
94
+ print(client.responses.create(model="default", input="Hello"))
95
+ ```
96
+
97
+ | Endpoint | Purpose |
98
+ |----------|---------|
99
+ | `POST /v1/responses` | Create a response (`stream=true` → SSE) |
100
+ | `GET` / `DELETE /v1/responses/{id}` | Retrieve / cancel |
101
+ | `POST /v1/chat/completions` | Chat Completions (non-stream + SSE) |
102
+ | `GET /v1/models` | Model ids |
103
+ | `GET /health` | Liveness |
104
+ | `WS /acp` | Agent Client Protocol |
105
+
106
+ Per-request options go in `extra_body.flowjet`:
107
+
108
+ | Field | Values | Meaning |
109
+ |-------|--------|---------|
110
+ | `session` | string | Isolates workspace + conversation thread |
111
+ | `interaction_mode` | `agent` (default) \| `ask` | `ask` is hard read-only |
112
+ | `projection` | `report` \| `progress` \| `developer` | How much SSE detail to expose |
113
+
114
+ Full configuration, environment variables and the security model: [docs/server.md](docs/server.md) · deployment: [deploy/README.md](deploy/README.md).
115
+
116
+ ---
117
+
118
+ ## Extend
119
+
120
+ Add skills and MCP servers in `nano.yml`:
121
+
122
+ ```yaml
123
+ skills:
124
+ - ~/.soothe/skills/my-reviewer
125
+
126
+ mcp_servers:
127
+ - name: filesystem
128
+ transport: stdio
129
+ command: npx
130
+ args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
131
+ ```
132
+
133
+ Skills are `SKILL.md` files loaded on demand; MCP tools activate on demand by default (`defer: true`).
134
+
135
+ ---
136
+
137
+ ## Development
138
+
139
+ ```bash
140
+ git clone https://github.com/caesar0301/flowjet.git
141
+ cd flowjet
142
+ make sync-dev && make test && make lint
143
+ ```
144
+
145
+ ## Upgrading from 1.x
146
+
147
+ Version 2.0 merges the former `flowjet-server` project into this one. The distribution is now `flowjet` and import paths changed. See [docs/upgrade.md](docs/upgrade.md).
148
+
149
+ ## License
150
+
151
+ MIT
@@ -10,7 +10,7 @@
10
10
  |--------|-------|------|
11
11
  | Product brand | **FlowJet** | Human-facing product name |
12
12
  | PyPI / `[project].name` | **`flowjet`** | Installable distribution (CLI **and** server) |
13
- | Source repository | **`flowjet-agent`** | GitHub repo (`caesar0301/flowjet-agent`) |
13
+ | Source repository | **`flowjet`** | GitHub repo (`caesar0301/flowjet`) |
14
14
  | Formal CLI | **`flowjet`** | Canonical console entrypoint |
15
15
  | CLI alias | **`fj`** | Same as `flowjet` |
16
16
  | CLI alias | **`fjf`** | Same as `flowjet -f` / `fj -f` |
@@ -51,7 +51,7 @@ alias packages. Rationale:
51
51
  **Cost.** Anyone importing `fj_ai.*` or `flowjet_server.*` must update.
52
52
  Migration table: [upgrade.md](upgrade.md).
53
53
 
54
- **Not changed.** The repository name (`flowjet-agent`), the `fj` / `fjf` aliases,
54
+ **Not changed.** The `fj` / `fjf` aliases,
55
55
  and the `flowjet-server` console script — so Docker, compose and existing shell
56
56
  habits keep working.
57
57
 
@@ -0,0 +1,136 @@
1
+ # FlowJet server reference
2
+
3
+ Everything you need to run `flowjet-server` (or `fj serve`) beyond the
4
+ [quick start in the README](../README.md#server).
5
+
6
+ ## Endpoints
7
+
8
+ Base path for the OpenAI-compatible API is `/v1`, so an SDK `base_url` should
9
+ end in `/v1`.
10
+
11
+ | HTTP | OpenAI SDK | Purpose |
12
+ |------|-----------|---------|
13
+ | `GET /health` | — | Liveness + thread-pool metrics |
14
+ | `GET /v1/models` | `client.models.list()` | Logical model ids |
15
+ | `POST /v1/responses` | `client.responses.create(...)` | Create a response |
16
+ | `POST /v1/responses` + SSE | `client.responses.stream(...)` | Streaming response |
17
+ | `GET /v1/responses/{id}` | `client.responses.retrieve(id)` | Retrieve a stored response |
18
+ | `DELETE /v1/responses/{id}` | `client.responses.delete(id)` | Delete + cancel the run |
19
+ | `POST /v1/chat/completions` | `client.chat.completions.create(...)` | Chat Completions (non-stream + SSE) |
20
+ | `WS /acp` | — | Agent Client Protocol (JSON-RPC) |
21
+
22
+ Responses are held in an in-process store; agent conversation state is
23
+ persisted by soothe-nano (SQLite by default, Postgres with `deploy/nano.yml`).
24
+
25
+ ## `extra_body.flowjet`
26
+
27
+ | Field | Values | Default | Meaning |
28
+ |-------|--------|---------|---------|
29
+ | `projection` | `report` \| `progress` \| `developer` | `report` | How much SSE detail to expose |
30
+ | `session` | string | new `fj-<uuid>` | Isolates workspace + conversation thread |
31
+ | `interaction_mode` | `agent` \| `ask` | `agent` | `ask` is hard read-only |
32
+ | `metadata` | object | — | Opaque bag forwarded to the runtime |
33
+
34
+ ### Projection modes
35
+
36
+ - **`report`** — final answer plus standard OpenAI lifecycle events.
37
+ - **`progress`** — adds `response.flowjet.progress` stages.
38
+ - **`developer`** — adds `response.flowjet.tool.started` / `.completed` summaries.
39
+
40
+ No mode exposes chain-of-thought or tool arguments.
41
+
42
+ ### Ask vs agent
43
+
44
+ The service builds nano's dual-mode agent and routes each request by
45
+ `interaction_mode`:
46
+
47
+ | Mode | Behavior |
48
+ |------|----------|
49
+ | `agent` | Full coding agent (read/write tools, shell if enabled in `nano.yml`) |
50
+ | `ask` | Read-only: `ls`, `read_file`, `glob`, `grep`, `file_info` — no writes, no shell |
51
+
52
+ Mode is pinned per session. To switch, start a new session.
53
+
54
+ ```python
55
+ with client.responses.stream(
56
+ model="default",
57
+ input="Explain how auth works in this workspace.",
58
+ extra_body={"flowjet": {"projection": "progress", "interaction_mode": "ask"}},
59
+ ) as stream:
60
+ for event in stream:
61
+ if event.type == "response.flowjet.progress":
62
+ print(event.stage, event.message)
63
+ elif event.type == "response.output_text.delta":
64
+ print(event.delta, end="", flush=True)
65
+ ```
66
+
67
+ ## Environment
68
+
69
+ | Variable | Default | Meaning |
70
+ |----------|---------|---------|
71
+ | `FLOWJET_API_KEY` | unset | If set, require Bearer auth |
72
+ | `FLOWJET_MODELS` | `default` | Comma-separated logical model ids |
73
+ | `FLOWJET_HOST` | `::` | Bind host (dual-stack IPv4/IPv6) |
74
+ | `FLOWJET_PORT` | `8618` | Bind port |
75
+ | `FLOWJET_HOME` | `~/.flowjet` | Root for per-session workspaces |
76
+ | `FLOWJET_NANO_CONFIG` | unset | Optional `nano.yml` (else `$SOOTHE_HOME/config/nano.yml`) |
77
+ | `FLOWJET_THREAD_POOL_MIN` | `2` | Min isolation worker threads |
78
+ | `FLOWJET_THREAD_POOL_MAX` | `8` | Max isolation worker threads |
79
+ | `FLOWJET_THREAD_POOL_IDLE_TIMEOUT` | `300` | Scaled-worker idle exit seconds (`0` = never) |
80
+ | `FLOWJET_MAX_REQUESTS_PER_WORKER` | `100` | Recycle worker after N turns (`0` = unlimited) |
81
+ | `FLOWJET_REUSE_RUNNER` | `true` | Reuse agent adapter per worker |
82
+ | `FLOWJET_REQUEST_TIMEOUT` | `0` | Per-run timeout seconds (`0` = none — **set this in production**) |
83
+ | `FLOWJET_READY_TIMEOUT` | `30` | Max wait for post-turn worker ready |
84
+ | `FLOWJET_ALLOW_EXTERNAL_WORKSPACE` | `true` | Honour `metadata.workspace` outside `FLOWJET_HOME`; set `false` to force hashed per-session workspaces |
85
+ | `FLOWJET_CORS_ORIGINS` | `*` | Comma-separated browser origins allowed to call the API |
86
+
87
+ ## Security model
88
+
89
+ The CLI and the server have deliberately different invariants, declared in
90
+ `flowjet.core.modes` rather than implied by whichever module builds the agent.
91
+
92
+ | | CLI | Server |
93
+ |---|---|---|
94
+ | `allow_paths_outside_workspace` | `True` (your own machine) | **`False`** — per-request workspace, non-overridable |
95
+ | `bypass` interaction mode | available | **rejected** — tools must never escape the request workspace |
96
+ | Authentication | — | optional `FLOWJET_API_KEY` (Bearer, constant-time comparison) |
97
+
98
+ Notes:
99
+
100
+ - The server forces `allow_paths_outside_workspace = false` even when the
101
+ loaded `nano.yml` asks for wider access.
102
+ - **The workspace itself is caller-chosen by default.** An ACP client's
103
+ `session/new` `cwd`, or `metadata.workspace` on an HTTP request, is honoured
104
+ even outside `FLOWJET_HOME` (`FLOWJET_ALLOW_EXTERNAL_WORKSPACE=true`). That
105
+ moves the confinement boundary to the caller's directory — it does not
106
+ remove it: tools still cannot escape the selected workspace. Set
107
+ `FLOWJET_ALLOW_EXTERNAL_WORKSPACE=false` to reject external paths and force
108
+ the hashed per-session workspace instead.
109
+ - `FLOWJET_CORS_ORIGINS` defaults to `*` with credentials enabled so browser
110
+ clients work out of the box. Set an explicit origin list in production.
111
+ - `/acp` (WebSocket) is unauthenticated unless `FLOWJET_API_KEY` is set;
112
+ put it behind a reverse proxy if you expose it publicly.
113
+
114
+ ## Concurrency
115
+
116
+ Each session admits one in-flight request at a time; extra requests for the
117
+ same session queue rather than interleave. Requests execute on a persistent
118
+ thread pool (each worker owns an event loop), so long tool calls never block
119
+ the HTTP loop. Tune with the `FLOWJET_THREAD_POOL_*` variables.
120
+
121
+ The session's workspace is the caller's (`session/new` `cwd`, or
122
+ `metadata.workspace`), falling back to `$FLOWJET_HOME/data/workspaces/ws_<hash>`
123
+ when the caller does not name one.
124
+
125
+ ## Deploy
126
+
127
+ Docker image and compose stack (Postgres + pgvector) are in
128
+ [deploy/README.md](../deploy/README.md). The image installs with
129
+ `--extra server` and keeps `CMD ["flowjet-server"]` plus a `:8618/health`
130
+ healthcheck.
131
+
132
+ ## Specification
133
+
134
+ - [RFC-001: OpenAI-Compatible API](specs/RFC-001-openai-compatible-api.md)
135
+ - [RFC-002: Isolated Thread-Pool Runtime](specs/RFC-002-isolated-thread-pool-runtime.md)
136
+ - [RFC-003: Production Isolation Hardening](specs/RFC-003-production-isolation-hardening.md)
@@ -3,7 +3,7 @@
3
3
  **Status**: Draft
4
4
  **Authors**: FlowJet
5
5
  **Created**: 2026-07-31
6
- **Last Updated**: 2026-07-31
6
+ **Last Updated**: 2026-09-17
7
7
  **Depends on**: [RFC-002](RFC-002-isolated-thread-pool-runtime.md)
8
8
  **Supersedes**: —
9
9
  **Kind**: Architecture Design
@@ -104,11 +104,17 @@ After each turn’s stream task finishes (success, cancel, error, timeout), canc
104
104
 
105
105
  ### 5.6 Workspace policy
106
106
 
107
- 1. Default hashed path under `$FLOWJET_HOME/data/workspaces/` — unchanged.
107
+ 1. Default hashed path under `$FLOWJET_HOME/data/workspaces/` — used when the caller names no workspace.
108
108
  2. If `metadata.workspace` is set:
109
- - If `FLOWJET_ALLOW_EXTERNAL_WORKSPACE=true` → resolve/create as today.
109
+ - If `FLOWJET_ALLOW_EXTERNAL_WORKSPACE=true` (**the default**) → resolve/create as today.
110
110
  - Else path MUST resolve under `$FLOWJET_HOME` (or equal home); otherwise reject with a clear runtime/OpenAI error (`invalid_workspace`).
111
111
 
112
+ Revised 2026-09-17: the flag's default flipped from `false` to `true` so a
113
+ desktop ACP client's `session/new` `cwd` is the session workspace without
114
+ requiring configuration. Tool confinement
115
+ (`allow_paths_outside_workspace=false`) is unchanged, so the boundary moves
116
+ to the caller's directory rather than being removed.
117
+
112
118
  ### 5.7 Interaction mode pin
113
119
 
114
120
  First admitted turn for a `session` records `interaction_mode` (`agent`|`ask`). Later turns with a different mode MUST fail with `interaction_mode_conflict` (HTTP 400). Omitted mode continues the pinned value (default `agent` if never set).
@@ -139,7 +145,7 @@ Expose a read-only snapshot: `total`, `idle`, `busy`, `dead`, `requests_complete
139
145
  | `FLOWJET_REUSE_RUNNER` | `true` | Reuse adapter per worker |
140
146
  | `FLOWJET_REQUEST_TIMEOUT` | `0` | Per-run timeout (s); production SHOULD set |
141
147
  | `FLOWJET_READY_TIMEOUT` | `30` | Ready-barrier timeout (s) |
142
- | `FLOWJET_ALLOW_EXTERNAL_WORKSPACE` | `false` | Allow workspace paths outside `FLOWJET_HOME` |
148
+ | `FLOWJET_ALLOW_EXTERNAL_WORKSPACE` | `true` | Honour workspace paths outside `FLOWJET_HOME` (`false` = force hashed per-session workspaces) |
143
149
 
144
150
  ---
145
151
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "flowjet"
7
- version = "2.0.0"
7
+ version = "2.0.2"
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" }
@@ -29,6 +29,9 @@ classifiers = [
29
29
  # lives in the `server` extra, and `flowjet.cli` never imports it at module
30
30
  # scope (see tests/unit/test_cli_no_server_deps.py).
31
31
  dependencies = [
32
+ # Default CLI runtime (FLOWJET_BACKEND=soothe). soothe is a host layer over
33
+ # soothe-nano, so nano stays pinned explicitly: soothe only caps it at <2.
34
+ "soothe>=1.0.12,<2.0.0",
32
35
  "soothe-nano>=1.2.28,<1.3.0",
33
36
  ]
34
37
 
@@ -74,9 +77,9 @@ fjf = "flowjet.cli.cli:main_follow"
74
77
  flowjet-server = "flowjet.server.__main__:main"
75
78
 
76
79
  [project.urls]
77
- Homepage = "https://github.com/caesar0301/flowjet-agent"
78
- Repository = "https://github.com/caesar0301/flowjet-agent"
79
- Issues = "https://github.com/caesar0301/flowjet-agent/issues"
80
+ Homepage = "https://github.com/caesar0301/flowjet"
81
+ Repository = "https://github.com/caesar0301/flowjet"
82
+ Issues = "https://github.com/caesar0301/flowjet/issues"
80
83
 
81
84
  [tool.hatch.build.targets.wheel]
82
85
  packages = ["src/flowjet"]