fruxon 0.13.2__tar.gz → 0.13.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.
Files changed (149) hide show
  1. {fruxon-0.13.2 → fruxon-0.13.4}/HISTORY.md +35 -0
  2. {fruxon-0.13.2 → fruxon-0.13.4}/PKG-INFO +5 -4
  3. {fruxon-0.13.2 → fruxon-0.13.4}/README.md +4 -3
  4. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/_version.py +2 -2
  5. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/__init__.py +10 -0
  6. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/_crash.py +15 -0
  7. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents.py +9 -9
  8. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents_executions.py +2 -1
  9. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents_memory.py +6 -6
  10. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/assets.py +7 -7
  11. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/environments.py +6 -6
  12. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/examples.py +2 -2
  13. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/integrations.py +4 -4
  14. fruxon-0.13.4/src/fruxon/cli/knowledge_bases.py +266 -0
  15. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/participants.py +11 -11
  16. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/fruxon.py +97 -27
  17. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/skills/fruxon-build-agent/SKILL.md +1 -1
  18. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/skills/fruxon-create-integration/SKILL.md +2 -2
  19. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/skills/fruxon-debug-trace/SKILL.md +2 -2
  20. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/skills/fruxon-use-integrations/SKILL.md +1 -1
  21. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_assets.py +2 -2
  22. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_cli.py +7 -7
  23. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_cli_crash.py +21 -2
  24. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_client.py +5 -5
  25. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_environments.py +13 -6
  26. fruxon-0.13.4/tests/test_knowledge_bases.py +278 -0
  27. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_memory.py +12 -4
  28. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_participants.py +8 -8
  29. {fruxon-0.13.2 → fruxon-0.13.4}/.gitignore +0 -0
  30. {fruxon-0.13.2 → fruxon-0.13.4}/LICENSE +0 -0
  31. {fruxon-0.13.2 → fruxon-0.13.4}/pyproject.toml +0 -0
  32. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/__init__.py +0 -0
  33. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/__main__.py +0 -0
  34. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/_ssl.py +0 -0
  35. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/_schema.py +0 -0
  36. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/_shared.py +0 -0
  37. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/_stream.py +0 -0
  38. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents_approvals.py +0 -0
  39. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents_budget.py +0 -0
  40. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents_channels.py +0 -0
  41. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents_draft.py +0 -0
  42. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents_lifecycle.py +0 -0
  43. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents_revisions.py +0 -0
  44. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents_sandbox.py +0 -0
  45. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents_sandbox_test.py +0 -0
  46. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents_slots.py +0 -0
  47. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents_tests.py +0 -0
  48. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/agents_topics.py +0 -0
  49. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/applications.py +0 -0
  50. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/applications_entry_points.py +0 -0
  51. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/auth.py +0 -0
  52. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/capabilities.py +0 -0
  53. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/completion.py +0 -0
  54. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/config.py +0 -0
  55. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/consult_pins.py +0 -0
  56. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/describe.py +0 -0
  57. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/doctor.py +0 -0
  58. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/escalations.py +0 -0
  59. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/guides.py +0 -0
  60. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/keys.py +0 -0
  61. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/llm_providers.py +0 -0
  62. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/messages.py +0 -0
  63. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/metrics.py +0 -0
  64. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/pipelines.py +0 -0
  65. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/secrets.py +0 -0
  66. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/skills.py +0 -0
  67. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/storage.py +0 -0
  68. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/tools.py +0 -0
  69. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/triggers.py +0 -0
  70. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/triggers_ledger.py +0 -0
  71. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/triggers_questions.py +0 -0
  72. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/triggers_shape.py +0 -0
  73. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/cli/workspaces.py +0 -0
  74. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/credentials.py +0 -0
  75. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/device_auth.py +0 -0
  76. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/doctor.py +0 -0
  77. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/exceptions.py +0 -0
  78. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/flow_validation.py +0 -0
  79. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/models.py +0 -0
  80. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/output.py +0 -0
  81. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/params.py +0 -0
  82. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/sandbox_scenario.py +0 -0
  83. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/skills/__init__.py +0 -0
  84. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/skills/fruxon-agent-mode/SKILL.md +0 -0
  85. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/skills/fruxon-meet/SKILL.md +0 -0
  86. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/telemetry.py +0 -0
  87. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/ui.py +0 -0
  88. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/update_check.py +0 -0
  89. {fruxon-0.13.2 → fruxon-0.13.4}/src/fruxon/validation.py +0 -0
  90. {fruxon-0.13.2 → fruxon-0.13.4}/tests/__init__.py +0 -0
  91. {fruxon-0.13.2 → fruxon-0.13.4}/tests/conftest.py +0 -0
  92. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_actor.py +0 -0
  93. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_agent_lifecycle.py +0 -0
  94. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_agent_slots.py +0 -0
  95. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_agents_check_cli.py +0 -0
  96. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_agents_revisions_cli.py +0 -0
  97. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_agents_sandbox.py +0 -0
  98. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_applications.py +0 -0
  99. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_approvals.py +0 -0
  100. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_budgets.py +0 -0
  101. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_capabilities.py +0 -0
  102. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_channels.py +0 -0
  103. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_cli_base_url_routing.py +0 -0
  104. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_connect_nudge.py +0 -0
  105. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_consult.py +0 -0
  106. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_credentials.py +0 -0
  107. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_describe.py +0 -0
  108. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_device_auth.py +0 -0
  109. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_doctor.py +0 -0
  110. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_draft_bootstrap.py +0 -0
  111. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_draft_evaluate_cli.py +0 -0
  112. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_draft_pull_shape.py +0 -0
  113. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_draft_validate_cli.py +0 -0
  114. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_drafts.py +0 -0
  115. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_entry_points.py +0 -0
  116. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_escalations.py +0 -0
  117. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_execution_records.py +0 -0
  118. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_flow_validation.py +0 -0
  119. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_fruxon.py +0 -0
  120. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_guides.py +0 -0
  121. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_integration_triggers_cli.py +0 -0
  122. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_integrations_authorize_cli.py +0 -0
  123. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_kb_trial_cli.py +0 -0
  124. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_llm_provider_configs_cli.py +0 -0
  125. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_messages.py +0 -0
  126. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_metrics.py +0 -0
  127. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_online_secret_refs.py +0 -0
  128. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_output.py +0 -0
  129. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_params.py +0 -0
  130. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_participants_write.py +0 -0
  131. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_pipelines.py +0 -0
  132. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_sandbox_scenario.py +0 -0
  133. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_schema.py +0 -0
  134. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_secrets.py +0 -0
  135. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_skills.py +0 -0
  136. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_ssl.py +0 -0
  137. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_storage.py +0 -0
  138. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_telemetry.py +0 -0
  139. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_test_chats.py +0 -0
  140. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_topics.py +0 -0
  141. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_triggers.py +0 -0
  142. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_triggers_ledger.py +0 -0
  143. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_triggers_questions.py +0 -0
  144. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_triggers_shape.py +0 -0
  145. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_triggers_write.py +0 -0
  146. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_ui.py +0 -0
  147. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_update_check.py +0 -0
  148. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_validation.py +0 -0
  149. {fruxon-0.13.2 → fruxon-0.13.4}/tests/test_workspaces_cli.py +0 -0
@@ -1,5 +1,21 @@
1
1
  # History
2
2
 
3
+ ## Unreleased — A knowledge base can be consolidated
4
+
5
+ Serial merge-per-conversation cannot repair a pair once both halves exist:
6
+ each was written before the other was searchable. The backend now runs a
7
+ pass over the whole corpus (fruxon-backend, `knowledgeBases/{kb}:consolidate`).
8
+
9
+ - **New `fruxon knowledge-bases consolidate <kb>`** — embeds the base's
10
+ live documents, clusters those above a similarity threshold, and prints
11
+ the clusters. Report-only unless `--apply`, which has the base's
12
+ consolidator agent decide each cluster and merge it (survivor keeps the
13
+ union of tags, labels and source conversations; the rest are archived).
14
+ Waits for the report by default; `--no-wait` prints the queued run and
15
+ `fruxon knowledge-bases consolidation <kb> <run>` reads it later.
16
+ - `agents executions list --trigger-type` accepts `KNOWLEDGE_CONSOLIDATION`,
17
+ the trigger the consolidator agent's runs carry.
18
+
3
19
  ## Unreleased — What a listing leaves out, and what a typo returns
4
20
 
5
21
  A patch release from a CLI trial run against a live workspace. Four defects,
@@ -208,6 +224,25 @@ workspace 2026-09-10.
208
224
  inbound wiring is unknown rather than asserting the agent cannot be reached.
209
225
  Triggers and channel bindings count exactly as before.
210
226
 
227
+ ## Unreleased — Free-text filters are called `query`
228
+
229
+ The platform renamed the free-text filter on every list endpoint from `search`
230
+ to `query` (and the storage file list from `q` to `query`), following the
231
+ Google Cloud convention. The SDK follows on the wire and in its own names, with
232
+ no alias — the old spellings are gone.
233
+
234
+ - **Python client**: `list_agents`, `list_memories`, `list_integrations`,
235
+ `list_asset_documents`, `list_participants` and `list_environments` take
236
+ `query=` instead of `search=`, and send `?query=`. `list_participants`
237
+ keeps its tier rule: a `query` without an explicit `tier` searches both
238
+ directory tiers.
239
+
240
+ - **CLI**: `--search` is now `--query` on `agents list`, `agents memory list`,
241
+ `integrations list`, `participants list`, `environments list` and
242
+ `assets documents`. The existing `-q` short alias stays on `participants list`
243
+ and `assets documents`. `agents topics search --query` and
244
+ `assets search -q` were already spelled this way.
245
+
211
246
  ## Unreleased — What a stage's agent will silently not do
212
247
 
213
248
  Two ways a work shape's PROCESS stage is wired wrong that the platform used to
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: fruxon
3
- Version: 0.13.2
3
+ Version: 0.13.4
4
4
  Summary: The Fruxon SDK is a lightweight Python client for integrating with the Fruxon platform.
5
5
  Project-URL: bugs, https://github.com/fruxon-ai/fruxon-sdk/issues
6
6
  Project-URL: changelog, https://github.com/fruxon-ai/fruxon-sdk/blob/main/HISTORY.md
@@ -96,7 +96,7 @@ Execution:
96
96
  | `fruxon agents executions trace <agent> <record-id>` | Step-by-step trace of one execution — LLM/tool calls, durations. `--show-io` also prints each tool step's parameters and result (the payload lives at `steps[].result`, a sibling of `toolTrace` — whose `resultDelivery` carries sizes only). |
97
97
  | `fruxon agents executions result <agent> <record-id>` | The final output one execution produced. |
98
98
  | `fruxon agents approvals list/get/respond/cancel <agent>` | Operate a step's human-in-the-loop gate — see what a run is blocked on and answer it. `respond`/`cancel` confirm first and refuse without `--yes` in agent mode (an LLM must not silently auto-approve). |
99
- | `fruxon agents memory list/subjects/get/forget-subject <agent>` | Inspect and prune what an agent remembers. `list` filters server-side by `--subject`/`--search`/`--scope`; `forget-subject` is a GDPR-style delete (confirms; refuses without `--yes` in agent mode). |
99
+ | `fruxon agents memory list/subjects/get/forget-subject <agent>` | Inspect and prune what an agent remembers. `list` filters server-side by `--subject`/`--query`/`--scope`; `forget-subject` is a GDPR-style delete (confirms; refuses without `--yes` in agent mode). |
100
100
  | `fruxon agents topics list/search/get/messages/sessions <agent>` + `fruxon agents inbox <agent>` | Read the conversation spine — the agent's topics (threads), one topic's transcript, its episodes, and its inbox (what it's focused on). `list`/`search` filter server-side by `--state`/`--participant`/`--query`. Read-only. Each message carries `author` — a human colleague's turn is stored as `ASSISTANT` on purpose, so `role` alone cannot tell their reply from the agent's; `HUMAN_OPERATOR` can. A message the runtime *withheld* is in no transcript at all — see `fruxon messages list`. `sessions` explains a fresh, blind session: a topic outlives its sessions, and `endCause` on the previous one (`CONSOLE_ALREADY_RESOLVED` — a human closed it in the provider's console) is why the next started with no history. |
101
101
  | `fruxon escalations list/history/unhandled/policy/ack` | What happened when an agent handed a conversation to a person. `list` is the queue (live takeovers + degraded escalations nobody was reachable for); `unhandled` is the append-only ledger under it. **`history` is the record of closed console-routed takeovers** — those leave the queue, so `list --status ALL` answers `[]` about a conversation a human worked for half an hour. Read `humanObservedAt` before believing a `RESOLVED`: null means nobody was ever seen picking it up. `policy <agent>` resolves who the *next* escalation would reach — an empty ladder under `NATIVE_HANDOFF` is correct, the console supplies the human. |
102
102
  | `fruxon messages list` | The channel ledger — including inbound an agent was never shown. A **withheld** message (a human owns the chat in the source console, or admission refused the sender) never becomes a conversation turn, so it is in no transcript and the thread reads as a customer being ignored. `--delivery WITHHELD_PENDING` lists the ones nothing has ever acted on; nothing drains them. |
@@ -138,6 +138,7 @@ Integrations + tools:
138
138
  | `fruxon keys list/mint/revoke/delete/history/scopes` | Audit and revoke scoped tokens. Minting opens the dashboard so the secret never enters the CLI process. |
139
139
  | `fruxon llm-providers list/get/models` | Browse LLM providers and models supported at the tenant level. |
140
140
  | `fruxon assets create/list/get/wait/operations/delete` | Manage knowledge-base (RAG) assets a step can query — upload local files, wait for async ingestion, inspect operations, and use the ids for `assetConfig.assetIds`. `delete` confirms + refuses without `--yes` in agent mode. |
141
+ | `fruxon knowledge-bases consolidate/consolidation` | Find the near-duplicate articles a per-conversation merge left in an editable knowledge base and, with `--apply`, have the base's consolidator agent fold each cluster into one (union of tags, labels and sources; the rest archived with a `merged_into` label). Report-only by default; waits for the report unless `--no-wait`. |
141
142
  | `fruxon assets search/documents/chunks` | Reproduce and inspect a retrieval. `search` runs the same query an agent's `search_assets` does (`--mode HYBRID/VECTOR/FULL_TEXT`, `--top-k`, fusion weights) — note `score` is on a different scale per mode, and in hybrid the top hit is always 1.0. `documents` lists what the index contains (a `chunkCount` of 0 means that file yielded no indexable text); `chunks` reads one document's chunks in order. The `documentId` these print is the **index's** id, which is what `chunks` takes — on a knowledge base's backing asset it is not the editable document's id, and it changes whenever a document's body is re-indexed. The `fileName` (`<knowledge document id>.md`) is the document a `knowledge_base` tool would edit. |
142
143
  | `fruxon metrics list` | Browse the evaluation-metric catalog — the ids a step's LLM-judge config (`judge.metrics[]`) binds, with a default weight each. |
143
144
  | `fruxon triggers list/get/create/update/delete/fire/bind/unbind` | Manage triggers — the schedule/event sources that fire agents. `create`/`update` take `--file` (+`--schema`); `create` also takes `--application`, the Application that will own the trigger and must own everything it fires. `bind`/`unbind` wire which agents fire; `fire` runs it now. `fire`/`delete`/`unbind` confirm + refuse without `--yes` in agent mode. The control plane for autonomy. `get` returns the full stored `workShape` and every `scheduleTimes` slot, so `get -o json | jq .workShape` produces a body `update --file` can post straight back — a PATCH replaces the whole shape, so edit what you read. |
@@ -153,11 +154,11 @@ Integrations + tools:
153
154
  | `fruxon triggers set-stages <id> --file` | Replace an automation's stages without rewriting the rest of its work shape (a PATCH replaces the whole shape, so this reads it, splices, and posts). Takes a bare stages array or any document carrying one. Pre-flights the two refusals the server only reports after the write: live items at a stage your list drops, and a `door` that will re-expand `source` on save. `--dry-run` prints the merged shape and the warnings. |
154
155
  | `fruxon triggers revisions list/get/restore` | A trigger's audit history — every mutation writes a snapshot, and `changeReason` separates a config edit from a binding reconcile. `get -o json | jq .workShape` is the shape as it stood, which is how you undo an edit by hand. `restore` replays one and is **not** a universal undo: it runs the same validation a save does, so a snapshot that drops a stage still holding live items is refused. |
155
156
  | `fruxon secrets list/get/grants` | Discover tenant secrets a step can reference — the ids for `allowedSecretIds` and the `{{secret.KEY}}` names, with publish-state and per-agent grants. Metadata only; values are never returned. |
156
- | `fruxon participants list/get/create/update/delete/enable/disable` | Manage agent-network participants (people / groups / agents the network routes to). `list` takes `--search` (matches names **and channel addresses and account ids**, so a phone number or handle resolves to an id, and searches both directory tiers by default), `--kind`, `--tier`, `--agent`, `--environment-id`, and pages up to `--limit` / `--all`. `create`/`update` take `--file` (+`--schema`); `enable`/`disable` toggle routing; `delete` confirms + refuses without `--yes` in agent mode. |
157
+ | `fruxon participants list/get/create/update/delete/enable/disable` | Manage agent-network participants (people / groups / agents the network routes to). `list` takes `--query` (matches names **and channel addresses and account ids**, so a phone number or handle resolves to an id, and searches both directory tiers by default), `--kind`, `--tier`, `--agent`, `--environment-id`, and pages up to `--limit` / `--all`. `create`/`update` take `--file` (+`--schema`); `enable`/`disable` toggle routing; `delete` confirms + refuses without `--yes` in agent mode. |
157
158
  | `fruxon applications roles <id>` | The Application's roster roles — who holds each, who defers to it, and how many holders are `consultable`. The answer to what a `--role` contact binding leaves open: the server takes any role string, so a role with references and no holders refuses at delivery time. `--unheld-only` lists just those. Trust the consultable count — every role path, delivery and consult alike, resolves through the consult-allowed member edges, so a holder without one is tagged but unreachable. |
158
159
  | `fruxon applications list/get` | Inspect Applications — the container that owns agents, workflows and people. Every agent belongs to exactly one, and `agents create` needs its id, so this is where you find it. Creating and re-homing an Application itself stays in the dashboard. |
159
160
  | `fruxon applications entry-points list/get/connect/attach/detach/move/update` | How inbound actually reaches an agent: an Application's claim on an external address. `list` with no Application answers "is this address already taken?". `connect` mints a new doorway (and prints the webhook URL **once**); `attach` adopts an existing one; `move` re-homes a claimed address; `detach` returns it to the Default Network. Writes — `detach`/`move` confirm first. |
160
- | `fruxon environments list/get/create/update/archive` | Manage end-customer environments — the slugs connector bindings and `execute(environmentSlug=…)` attribute runs to (per-customer cost tracking, quotas, analytics). `list --search` filters; `archive` confirms + refuses without `--yes` in agent mode. |
161
+ | `fruxon environments list/get/create/update/archive` | Manage end-customer environments — the slugs connector bindings and `execute(environmentSlug=…)` attribute runs to (per-customer cost tracking, quotas, analytics). `list --query` filters; `archive` confirms + refuses without `--yes` in agent mode. |
161
162
  | `fruxon pipelines list/get` | Read collection pipelines — one Agent or Workflow run per item of a source. An agent's `pipelines.bindings` allowlist names them **by id** and `run_pipeline` refuses any id it does not name, so this is where those ids come from (`get` also lists the reusable `sourceId`s `allowedSourceIds` takes). Read-only. |
162
163
  | `fruxon capabilities list/get/create/update/delete` | Manage the consult-routing vocabulary (capabilities = name/area/description) that roster bindings and pins reference. `create`/`update` take `--file` (+`--schema`); `delete` --yes-gated in agent mode. |
163
164
  | `fruxon participants bind/unbind/roster` + `fruxon agents roster` | Wire a participant onto an agent's consult roster and set its policy (roles / urgency / response policy); `agents roster` reads who advises an agent. `unbind` --yes-gated. |
@@ -63,7 +63,7 @@ Execution:
63
63
  | `fruxon agents executions trace <agent> <record-id>` | Step-by-step trace of one execution — LLM/tool calls, durations. `--show-io` also prints each tool step's parameters and result (the payload lives at `steps[].result`, a sibling of `toolTrace` — whose `resultDelivery` carries sizes only). |
64
64
  | `fruxon agents executions result <agent> <record-id>` | The final output one execution produced. |
65
65
  | `fruxon agents approvals list/get/respond/cancel <agent>` | Operate a step's human-in-the-loop gate — see what a run is blocked on and answer it. `respond`/`cancel` confirm first and refuse without `--yes` in agent mode (an LLM must not silently auto-approve). |
66
- | `fruxon agents memory list/subjects/get/forget-subject <agent>` | Inspect and prune what an agent remembers. `list` filters server-side by `--subject`/`--search`/`--scope`; `forget-subject` is a GDPR-style delete (confirms; refuses without `--yes` in agent mode). |
66
+ | `fruxon agents memory list/subjects/get/forget-subject <agent>` | Inspect and prune what an agent remembers. `list` filters server-side by `--subject`/`--query`/`--scope`; `forget-subject` is a GDPR-style delete (confirms; refuses without `--yes` in agent mode). |
67
67
  | `fruxon agents topics list/search/get/messages/sessions <agent>` + `fruxon agents inbox <agent>` | Read the conversation spine — the agent's topics (threads), one topic's transcript, its episodes, and its inbox (what it's focused on). `list`/`search` filter server-side by `--state`/`--participant`/`--query`. Read-only. Each message carries `author` — a human colleague's turn is stored as `ASSISTANT` on purpose, so `role` alone cannot tell their reply from the agent's; `HUMAN_OPERATOR` can. A message the runtime *withheld* is in no transcript at all — see `fruxon messages list`. `sessions` explains a fresh, blind session: a topic outlives its sessions, and `endCause` on the previous one (`CONSOLE_ALREADY_RESOLVED` — a human closed it in the provider's console) is why the next started with no history. |
68
68
  | `fruxon escalations list/history/unhandled/policy/ack` | What happened when an agent handed a conversation to a person. `list` is the queue (live takeovers + degraded escalations nobody was reachable for); `unhandled` is the append-only ledger under it. **`history` is the record of closed console-routed takeovers** — those leave the queue, so `list --status ALL` answers `[]` about a conversation a human worked for half an hour. Read `humanObservedAt` before believing a `RESOLVED`: null means nobody was ever seen picking it up. `policy <agent>` resolves who the *next* escalation would reach — an empty ladder under `NATIVE_HANDOFF` is correct, the console supplies the human. |
69
69
  | `fruxon messages list` | The channel ledger — including inbound an agent was never shown. A **withheld** message (a human owns the chat in the source console, or admission refused the sender) never becomes a conversation turn, so it is in no transcript and the thread reads as a customer being ignored. `--delivery WITHHELD_PENDING` lists the ones nothing has ever acted on; nothing drains them. |
@@ -105,6 +105,7 @@ Integrations + tools:
105
105
  | `fruxon keys list/mint/revoke/delete/history/scopes` | Audit and revoke scoped tokens. Minting opens the dashboard so the secret never enters the CLI process. |
106
106
  | `fruxon llm-providers list/get/models` | Browse LLM providers and models supported at the tenant level. |
107
107
  | `fruxon assets create/list/get/wait/operations/delete` | Manage knowledge-base (RAG) assets a step can query — upload local files, wait for async ingestion, inspect operations, and use the ids for `assetConfig.assetIds`. `delete` confirms + refuses without `--yes` in agent mode. |
108
+ | `fruxon knowledge-bases consolidate/consolidation` | Find the near-duplicate articles a per-conversation merge left in an editable knowledge base and, with `--apply`, have the base's consolidator agent fold each cluster into one (union of tags, labels and sources; the rest archived with a `merged_into` label). Report-only by default; waits for the report unless `--no-wait`. |
108
109
  | `fruxon assets search/documents/chunks` | Reproduce and inspect a retrieval. `search` runs the same query an agent's `search_assets` does (`--mode HYBRID/VECTOR/FULL_TEXT`, `--top-k`, fusion weights) — note `score` is on a different scale per mode, and in hybrid the top hit is always 1.0. `documents` lists what the index contains (a `chunkCount` of 0 means that file yielded no indexable text); `chunks` reads one document's chunks in order. The `documentId` these print is the **index's** id, which is what `chunks` takes — on a knowledge base's backing asset it is not the editable document's id, and it changes whenever a document's body is re-indexed. The `fileName` (`<knowledge document id>.md`) is the document a `knowledge_base` tool would edit. |
109
110
  | `fruxon metrics list` | Browse the evaluation-metric catalog — the ids a step's LLM-judge config (`judge.metrics[]`) binds, with a default weight each. |
110
111
  | `fruxon triggers list/get/create/update/delete/fire/bind/unbind` | Manage triggers — the schedule/event sources that fire agents. `create`/`update` take `--file` (+`--schema`); `create` also takes `--application`, the Application that will own the trigger and must own everything it fires. `bind`/`unbind` wire which agents fire; `fire` runs it now. `fire`/`delete`/`unbind` confirm + refuse without `--yes` in agent mode. The control plane for autonomy. `get` returns the full stored `workShape` and every `scheduleTimes` slot, so `get -o json | jq .workShape` produces a body `update --file` can post straight back — a PATCH replaces the whole shape, so edit what you read. |
@@ -120,11 +121,11 @@ Integrations + tools:
120
121
  | `fruxon triggers set-stages <id> --file` | Replace an automation's stages without rewriting the rest of its work shape (a PATCH replaces the whole shape, so this reads it, splices, and posts). Takes a bare stages array or any document carrying one. Pre-flights the two refusals the server only reports after the write: live items at a stage your list drops, and a `door` that will re-expand `source` on save. `--dry-run` prints the merged shape and the warnings. |
121
122
  | `fruxon triggers revisions list/get/restore` | A trigger's audit history — every mutation writes a snapshot, and `changeReason` separates a config edit from a binding reconcile. `get -o json | jq .workShape` is the shape as it stood, which is how you undo an edit by hand. `restore` replays one and is **not** a universal undo: it runs the same validation a save does, so a snapshot that drops a stage still holding live items is refused. |
122
123
  | `fruxon secrets list/get/grants` | Discover tenant secrets a step can reference — the ids for `allowedSecretIds` and the `{{secret.KEY}}` names, with publish-state and per-agent grants. Metadata only; values are never returned. |
123
- | `fruxon participants list/get/create/update/delete/enable/disable` | Manage agent-network participants (people / groups / agents the network routes to). `list` takes `--search` (matches names **and channel addresses and account ids**, so a phone number or handle resolves to an id, and searches both directory tiers by default), `--kind`, `--tier`, `--agent`, `--environment-id`, and pages up to `--limit` / `--all`. `create`/`update` take `--file` (+`--schema`); `enable`/`disable` toggle routing; `delete` confirms + refuses without `--yes` in agent mode. |
124
+ | `fruxon participants list/get/create/update/delete/enable/disable` | Manage agent-network participants (people / groups / agents the network routes to). `list` takes `--query` (matches names **and channel addresses and account ids**, so a phone number or handle resolves to an id, and searches both directory tiers by default), `--kind`, `--tier`, `--agent`, `--environment-id`, and pages up to `--limit` / `--all`. `create`/`update` take `--file` (+`--schema`); `enable`/`disable` toggle routing; `delete` confirms + refuses without `--yes` in agent mode. |
124
125
  | `fruxon applications roles <id>` | The Application's roster roles — who holds each, who defers to it, and how many holders are `consultable`. The answer to what a `--role` contact binding leaves open: the server takes any role string, so a role with references and no holders refuses at delivery time. `--unheld-only` lists just those. Trust the consultable count — every role path, delivery and consult alike, resolves through the consult-allowed member edges, so a holder without one is tagged but unreachable. |
125
126
  | `fruxon applications list/get` | Inspect Applications — the container that owns agents, workflows and people. Every agent belongs to exactly one, and `agents create` needs its id, so this is where you find it. Creating and re-homing an Application itself stays in the dashboard. |
126
127
  | `fruxon applications entry-points list/get/connect/attach/detach/move/update` | How inbound actually reaches an agent: an Application's claim on an external address. `list` with no Application answers "is this address already taken?". `connect` mints a new doorway (and prints the webhook URL **once**); `attach` adopts an existing one; `move` re-homes a claimed address; `detach` returns it to the Default Network. Writes — `detach`/`move` confirm first. |
127
- | `fruxon environments list/get/create/update/archive` | Manage end-customer environments — the slugs connector bindings and `execute(environmentSlug=…)` attribute runs to (per-customer cost tracking, quotas, analytics). `list --search` filters; `archive` confirms + refuses without `--yes` in agent mode. |
128
+ | `fruxon environments list/get/create/update/archive` | Manage end-customer environments — the slugs connector bindings and `execute(environmentSlug=…)` attribute runs to (per-customer cost tracking, quotas, analytics). `list --query` filters; `archive` confirms + refuses without `--yes` in agent mode. |
128
129
  | `fruxon pipelines list/get` | Read collection pipelines — one Agent or Workflow run per item of a source. An agent's `pipelines.bindings` allowlist names them **by id** and `run_pipeline` refuses any id it does not name, so this is where those ids come from (`get` also lists the reusable `sourceId`s `allowedSourceIds` takes). Read-only. |
129
130
  | `fruxon capabilities list/get/create/update/delete` | Manage the consult-routing vocabulary (capabilities = name/area/description) that roster bindings and pins reference. `create`/`update` take `--file` (+`--schema`); `delete` --yes-gated in agent mode. |
130
131
  | `fruxon participants bind/unbind/roster` + `fruxon agents roster` | Wire a participant onto an agent's consult roster and set its policy (roles / urgency / response policy); `agents roster` reads who advises an agent. `unbind` --yes-gated. |
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.13.2'
22
- __version_tuple__ = version_tuple = (0, 13, 2)
21
+ __version__ = version = '0.13.4'
22
+ __version_tuple__ = version_tuple = (0, 13, 4)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -247,6 +247,15 @@ class _FruxonTyperGroup(TyperGroup):
247
247
  except BaseException as exc:
248
248
  from fruxon.cli import _crash
249
249
 
250
+ # Click implements help and version as exceptions. A human's bare
251
+ # ``no_args_is_help`` group is another successful discovery path,
252
+ # despite Click retaining its historical exit code 2. Agent mode
253
+ # deliberately turns that same no-subcommand condition into a
254
+ # structured usage error below, so keep it on the failure path.
255
+ if _crash.is_success_exit(exc) or (_crash.is_no_args_help(exc) and not is_agent_mode()):
256
+ succeeded = True
257
+ raise
258
+
250
259
  duration_ms = int((_time.monotonic() - started) * 1000)
251
260
  command_name = self._command_path(ctx, entry_args)
252
261
  unexpected = _crash.is_unexpected(exc)
@@ -599,6 +608,7 @@ from fruxon.cli import examples as _examples # noqa: E402, F401
599
608
  from fruxon.cli import guides as _guides # noqa: E402, F401
600
609
  from fruxon.cli import integrations as _integrations # noqa: E402, F401
601
610
  from fruxon.cli import keys as _keys # noqa: E402, F401
611
+ from fruxon.cli import knowledge_bases as _knowledge_bases # noqa: E402, F401
602
612
  from fruxon.cli import llm_providers as _llm_providers # noqa: E402, F401
603
613
  from fruxon.cli import messages as _messages # noqa: E402, F401
604
614
  from fruxon.cli import metrics as _metrics # noqa: E402, F401
@@ -68,6 +68,21 @@ def is_usage_error(exc: BaseException) -> bool:
68
68
  return _is_click_exception(exc, class_name="UsageError")
69
69
 
70
70
 
71
+ def is_success_exit(exc: BaseException) -> bool:
72
+ """Whether Click/Typer stopped successfully after help or version.
73
+
74
+ ``--help`` and ``--version`` use a zero-code ``Exit`` instead of returning
75
+ normally. Match both Click namespaces because current Typer vendors its
76
+ own copy while older releases use the top-level package.
77
+ """
78
+ return _is_click_exception(exc, class_name="Exit") and getattr(exc, "exit_code", 1) == 0
79
+
80
+
81
+ def is_no_args_help(exc: BaseException) -> bool:
82
+ """Whether a ``no_args_is_help`` command group rendered its help."""
83
+ return _is_click_exception(exc, class_name="NoArgsIsHelpError")
84
+
85
+
71
86
  def _is_click_exception(exc: BaseException, *, class_name: str = "ClickException") -> bool:
72
87
  """Match Click's public exceptions and Typer's vendored equivalents."""
73
88
  import click
@@ -70,9 +70,9 @@ def agents_list(
70
70
  help="Include disabled agents (default: only enabled ones).",
71
71
  ),
72
72
  ] = False,
73
- search: Annotated[
73
+ query: Annotated[
74
74
  str | None,
75
- typer.Option("--search", help="Filter by free-text search (id, name, description)."),
75
+ typer.Option("--query", "-q", help="Filter by free-text query (id, name, description)."),
76
76
  ] = None,
77
77
  application: Annotated[
78
78
  str | None,
@@ -85,14 +85,14 @@ def agents_list(
85
85
  one-ID-per-line output (good for shell loops); ``--output json`` for
86
86
  machine consumption with the full agent payload we expose.
87
87
 
88
- ``--search`` narrows server-side to a case-insensitive substring match on
88
+ ``--query`` narrows server-side to a case-insensitive substring match on
89
89
  the agent id, display name, and description. ``--application`` narrows to
90
90
  one ownership boundary (``fruxon applications list`` for the ids).
91
91
 
92
92
  Examples:
93
93
  fruxon agents list
94
94
  fruxon agents list --include-disabled
95
- fruxon agents list --search invoice
95
+ fruxon agents list --query invoice
96
96
  fruxon agents list --application 6f1c…
97
97
  fruxon agents list --output json
98
98
  fruxon agents list --output id | xargs -n1 fruxon agents get
@@ -112,9 +112,9 @@ def agents_list(
112
112
  try:
113
113
  if stderr.is_terminal and output != "id":
114
114
  with stderr.status("[bold]Fetching agents…[/bold]"):
115
- agents = client.list_agents(search=search, application=application)
115
+ agents = client.list_agents(query=query, application=application)
116
116
  else:
117
- agents = client.list_agents(search=search, application=application)
117
+ agents = client.list_agents(query=query, application=application)
118
118
  except FruxonError as e:
119
119
  fail_from_api_error(e, hint=_hint_for_list_error(e))
120
120
 
@@ -138,11 +138,11 @@ def agents_list(
138
138
  return
139
139
  if output == "id":
140
140
  return
141
- if search:
141
+ if query:
142
142
  # A filter quirk, not an empty workspace — point at the filter, not onboarding.
143
143
  say_info(
144
- f"No agents match [bold]{search}[/bold].",
145
- hint="Broaden the [bold]--search[/bold] term, or drop it to list every agent.",
144
+ f"No agents match [bold]{query}[/bold].",
145
+ hint="Broaden the [bold]--query[/bold] term, or drop it to list every agent.",
146
146
  )
147
147
  return
148
148
  say_info(
@@ -81,6 +81,7 @@ _VALID_TRIGGER_TYPE = frozenset(
81
81
  "PARTICIPANT_REQUEST",
82
82
  "RELEVANCE_CHECK",
83
83
  "DOCUMENT_ENRICHMENT",
84
+ "KNOWLEDGE_CONSOLIDATION",
84
85
  "COLLECTION_ITEM",
85
86
  "TEST",
86
87
  "TOPIC_TURN",
@@ -150,7 +151,7 @@ def executions_list(
150
151
  "--participant",
151
152
  help=(
152
153
  "Only runs served for this participant (Guid). Repeatable. "
153
- "Resolve a phone/handle to an id with `fruxon participants list --search`."
154
+ "Resolve a phone/handle to an id with `fruxon participants list --query`."
154
155
  ),
155
156
  ),
156
157
  ] = None,
@@ -7,7 +7,7 @@ read + GDPR surface over them: query "what does my agent remember about
7
7
  X", and forget everything about a subject.
8
8
 
9
9
  Designed for an LLM driver: ``list`` narrows **server-side** by
10
- ``--subject`` / ``--search`` / ``--scope`` (so the agent asks precisely
10
+ ``--subject`` / ``--query`` / ``--scope`` (so the agent asks precisely
11
11
  instead of dumping everything), and ``forget-subject`` — irreversible —
12
12
  confirms first and refuses without ``--yes`` under agent mode.
13
13
 
@@ -53,7 +53,7 @@ def memory_list(
53
53
  str | None,
54
54
  typer.Option("--subject", help="Only memories about this subject (person / end-user key)."),
55
55
  ] = None,
56
- search: Annotated[str | None, typer.Option("--search", help="Full-text filter over title + content.")] = None,
56
+ query: Annotated[str | None, typer.Option("--query", "-q", help="Full-text filter over title + content.")] = None,
57
57
  scope: Annotated[
58
58
  str | None,
59
59
  typer.Option("--scope", help="AGENT (cross-everyone facts) or SUBJECT (per-person facts)."),
@@ -72,14 +72,14 @@ def memory_list(
72
72
  ),
73
73
  ] = None,
74
74
  ):
75
- """List what an agent remembers — narrow with --subject / --search / --scope.
75
+ """List what an agent remembers — narrow with --subject / --query / --scope.
76
76
 
77
77
  The filters run server-side, so "what does my agent remember about
78
78
  user_42" is `--subject user_42`, not a client-side scan.
79
79
 
80
80
  Examples:
81
81
  fruxon agents memory list my-agent --subject user_42
82
- fruxon agents memory list my-agent --search "dark mode"
82
+ fruxon agents memory list my-agent --query "dark mode"
83
83
  fruxon agents memory list my-agent --scope AGENT --output id
84
84
  """
85
85
  output = resolve_output_format(output, human_default="table", agent_default="json")
@@ -95,9 +95,9 @@ def memory_list(
95
95
  try:
96
96
  if stderr.is_terminal and output != "id":
97
97
  with stderr.status(f"[bold]Fetching memories for [cyan]{agent}[/cyan]…[/bold]"):
98
- memories = client.list_memories(agent, subject=subject, search=search, scope=scope_norm)
98
+ memories = client.list_memories(agent, subject=subject, query=query, scope=scope_norm)
99
99
  else:
100
- memories = client.list_memories(agent, subject=subject, search=search, scope=scope_norm)
100
+ memories = client.list_memories(agent, subject=subject, query=query, scope=scope_norm)
101
101
  except FruxonError as e:
102
102
  fail_from_api_error(e, hint=_hint_for_get_error(e, agent, client))
103
103
 
@@ -1046,9 +1046,9 @@ def _render_explain_hit(
1046
1046
  @assets_app.command("documents")
1047
1047
  def assets_documents(
1048
1048
  asset: Annotated[str, typer.Argument(help="Asset identifier.")],
1049
- search: Annotated[
1049
+ query: Annotated[
1050
1050
  str | None,
1051
- typer.Option("--search", "-q", help="Filter by file name, server-side."),
1051
+ typer.Option("--query", "-q", help="Filter by file name, server-side."),
1052
1052
  ] = None,
1053
1053
  limit: Annotated[
1054
1054
  int,
@@ -1074,7 +1074,7 @@ def assets_documents(
1074
1074
 
1075
1075
  Examples:
1076
1076
  fruxon assets documents 2a03ed53…
1077
- fruxon assets documents 2a03ed53… --search handbook -o id
1077
+ fruxon assets documents 2a03ed53… --query handbook -o id
1078
1078
  """
1079
1079
  output = resolve_output_format(output, human_default="table", agent_default="json")
1080
1080
  if output not in {"table", "json", "id"}:
@@ -1089,7 +1089,7 @@ def assets_documents(
1089
1089
  effective_limit = None if all_pages else limit
1090
1090
  client = build_client(workspace, base_url)
1091
1091
  try:
1092
- documents = client.list_asset_documents(asset, search=search, limit=effective_limit)
1092
+ documents = client.list_asset_documents(asset, query=query, limit=effective_limit)
1093
1093
  except FruxonError as e:
1094
1094
  fail_from_api_error(e, hint=_hint_for_error(e))
1095
1095
 
@@ -1103,10 +1103,10 @@ def assets_documents(
1103
1103
 
1104
1104
  if not documents:
1105
1105
  say_info(
1106
- "No documents matched." if search else "This asset has no indexed documents.",
1106
+ "No documents matched." if query else "This asset has no indexed documents.",
1107
1107
  hint=(
1108
- "Drop --search to see everything."
1109
- if search
1108
+ "Drop --query to see everything."
1109
+ if query
1110
1110
  else f"If it was created recently, check [bold]fruxon assets operations {asset}[/bold]."
1111
1111
  ),
1112
1112
  )
@@ -46,9 +46,9 @@ app.add_typer(environments_app, name="environments")
46
46
 
47
47
  @environments_app.command("list")
48
48
  def environments_list(
49
- search: Annotated[
49
+ query: Annotated[
50
50
  str | None,
51
- typer.Option("--search", help="Case-insensitive substring filter on name, slug, and external id."),
51
+ typer.Option("--query", "-q", help="Case-insensitive substring filter on name, slug, and external id."),
52
52
  ] = None,
53
53
  group: Annotated[
54
54
  str | None,
@@ -76,7 +76,7 @@ def environments_list(
76
76
 
77
77
  Examples:
78
78
  fruxon environments list
79
- fruxon environments list --search acme
79
+ fruxon environments list --query acme
80
80
  fruxon environments list --group "Emek Group"
81
81
  fruxon environments list -o json | jq '.[] | select(.isSystem|not) | .slug'
82
82
  """
@@ -92,9 +92,9 @@ def environments_list(
92
92
  try:
93
93
  if stderr.is_terminal and output != "id":
94
94
  with stderr.status("[bold]Fetching environments…[/bold]"):
95
- environments = client.list_environments(search=search, group=group)
95
+ environments = client.list_environments(query=query, group=group)
96
96
  else:
97
- environments = client.list_environments(search=search, group=group)
97
+ environments = client.list_environments(query=query, group=group)
98
98
  except FruxonError as e:
99
99
  fail_from_api_error(e, hint=_hint_for_error(e))
100
100
 
@@ -104,7 +104,7 @@ def environments_list(
104
104
  return
105
105
  if output == "id":
106
106
  return
107
- filtered = bool(search or group)
107
+ filtered = bool(query or group)
108
108
  say_info(
109
109
  "No environments match." if filtered else "No environments in this workspace yet.",
110
110
  hint=None if filtered else "Create one with [bold]fruxon environments create <name>[/bold].",
@@ -175,7 +175,7 @@ _EXAMPLES: dict[str, list[tuple[str, str]]] = {
175
175
  ],
176
176
  "memory": [
177
177
  ("fruxon agents memory list my-agent --subject user_42", "What the agent remembers about one person"),
178
- ("fruxon agents memory list my-agent --search 'dark mode'", "Full-text over its memories"),
178
+ ("fruxon agents memory list my-agent --query 'dark mode'", "Full-text over its memories"),
179
179
  ("fruxon agents memory subjects my-agent", "Which subjects it has memories about (+ counts)"),
180
180
  ("fruxon agents memory forget-subject my-agent user_42 --yes", "GDPR-forget everything about a subject"),
181
181
  ],
@@ -259,7 +259,7 @@ _EXAMPLES: dict[str, list[tuple[str, str]]] = {
259
259
  ],
260
260
  "environments": [
261
261
  ("fruxon environments list", "Browse end-customer environments (slugs runs attribute to)"),
262
- ("fruxon environments list --search acme", "Filter by name / slug / external id"),
262
+ ("fruxon environments list --query acme", "Filter by name / slug / external id"),
263
263
  ('fruxon environments create "Acme Corp"', "Add one — the slug is generated from the name"),
264
264
  (
265
265
  'fruxon environments update 6f1c… --agent-context "VIP customer — prioritize."',
@@ -57,7 +57,7 @@ integrations_app.add_typer(mcp_app, name="mcp")
57
57
 
58
58
  @integrations_app.command("list")
59
59
  def integrations_list(
60
- search: Annotated[str | None, typer.Option("--search", help="Filter by free-text search.")] = None,
60
+ query: Annotated[str | None, typer.Option("--query", "-q", help="Filter by free-text query.")] = None,
61
61
  type_: Annotated[
62
62
  list[str] | None,
63
63
  typer.Option("--type", help="Filter by integration type. Repeatable."),
@@ -110,7 +110,7 @@ def integrations_list(
110
110
  if stderr.is_terminal and output != "id":
111
111
  with stderr.status("[bold]Fetching integrations…[/bold]"):
112
112
  integrations = client.list_integrations(
113
- search=search,
113
+ query=query,
114
114
  types=type_,
115
115
  tags=tag,
116
116
  has_configs=has_configs,
@@ -119,7 +119,7 @@ def integrations_list(
119
119
  )
120
120
  else:
121
121
  integrations = client.list_integrations(
122
- search=search,
122
+ query=query,
123
123
  types=type_,
124
124
  tags=tag,
125
125
  has_configs=has_configs,
@@ -137,7 +137,7 @@ def integrations_list(
137
137
  return
138
138
  say_info(
139
139
  "No integrations match."
140
- if (search or type_ or tag or has_configs or has_triggers or has_channels)
140
+ if (query or type_ or tag or has_configs or has_triggers or has_channels)
141
141
  else "No integrations in this workspace yet.",
142
142
  hint="Create one with [bold]fruxon integrations create --file <int.json>[/bold].",
143
143
  )