chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:12:33 +08:00
commit aacb60a4af
3387 changed files with 981307 additions and 0 deletions
+99
View File
@@ -0,0 +1,99 @@
# OpenSquilla Documentation
This directory is the user-facing product documentation set. It complements the
root release README with task-oriented guides.
## Read First
1. [`quickstart.md`](quickstart.md) - install, configure, run, and open the Web UI.
2. [`use-cases.md`](use-cases.md) - task-oriented recipes for common goals.
3. [`gateway.md`](gateway.md) - gateway lifecycle, host/port, safety, and status.
4. [`configuration.md`](configuration.md) - provider, router, search, channel,
memory, and permission configuration.
5. [`cli.md`](cli.md) - command groups and common CLI workflows.
6. [`tui.md`](tui.md) - terminal chat usage, slash commands, files, sessions,
and the OpenTUI preview.
7. [`web-ui.md`](web-ui.md) - local control console and chat UI.
8. [`sessions.md`](sessions.md) - session continuity, export, resume, abort,
and cleanup.
9. [`glossary.md`](glossary.md) - user-facing terminology.
## Feature Guides
- [`features.md`](features.md) - capability catalog.
- [`features/squilla-router.md`](features/squilla-router.md) - model routing.
- [`features/tui-frontend.md`](features/tui-frontend.md) - terminal backend
architecture, plugin slots, Router HUD, and OpenTUI evaluation.
- [`features/tool-compression.md`](features/tool-compression.md) - compact tool
results and handles.
- [`features/meta-skills.md`](features/meta-skills.md) - reusable workflow skills.
- [`features/meta-skill-user-guide.md`](features/meta-skill-user-guide.md) -
user-facing MetaSkill guide.
- [`authoring/meta-skills.md`](authoring/meta-skills.md) - MetaSkill authoring
guide.
- [`features/memory.md`](features/memory.md) - durable memory and recall.
- [`features/skills.md`](features/skills.md) - skill discovery, install, and
authoring.
- [`features/compaction-and-cache.md`](features/compaction-and-cache.md) -
long-session compaction and prompt-cache continuity.
## Surfaces and Operations
- [`releases/0.5.0rc3.md`](releases/0.5.0rc3.md) - OpenSquilla 0.5.0 Preview 3 release notes.
- [`releases/0.5.0rc2.md`](releases/0.5.0rc2.md) - OpenSquilla 0.5.0 Preview 2 release notes.
- [`releases/0.5.0rc1.md`](releases/0.5.0rc1.md) - OpenSquilla 0.5.0 Preview 1 release notes.
- [`releases/0.4.1.md`](releases/0.4.1.md) - OpenSquilla 0.4.1 release notes.
- [`releases/0.4.0.md`](releases/0.4.0.md) - OpenSquilla 0.4.0 release notes.
- [`releases/0.3.0.md`](releases/0.3.0.md) - OpenSquilla 0.3.0 release notes.
- [`channels.md`](channels.md) - supported messaging channels and setup flow.
- [`providers-and-models.md`](providers-and-models.md) - LLM provider catalog,
model selection, and runtime-backed model inspection.
- [`search.md`](search.md) - web search providers and query workflow.
- [`artifacts-and-media.md`](artifacts-and-media.md) - artifacts, generated
files, images, PDF, and TTS.
- [`tools-and-sandbox.md`](tools-and-sandbox.md) - built-in tools, approvals,
sandbox posture, and write policy.
- [`approvals-and-permissions.md`](approvals-and-permissions.md) - permission
profiles, approval commands, workspace containment, and sandbox posture.
- [`agents.md`](agents.md) - durable named agents and workspace defaults.
- [`scheduling.md`](scheduling.md) - recurring and one-time scheduled work.
- [`mcp-server.md`](mcp-server.md) - MCP server bridge for MCP-capable clients.
- [`usage-and-cost.md`](usage-and-cost.md) - token usage, estimated cost, and
cost investigation workflow.
- [`diagnostics-and-replay.md`](diagnostics-and-replay.md) - diagnostics,
raw capture guidance, read-only turn replay, and developer replay benchmarks.
- [`tui-real-terminal-harness.md`](tui-real-terminal-harness.md) - maintainer
real-terminal TUI integration harness and evidence capture.
- [`experiments.md`](experiments.md) - opt-in runtime toggle conventions and
the delivery-verification tooling in `scripts/experiments/`.
- [`docker.md`](docker.md) - Docker/Compose deployment on home servers and
NAS: prebuilt GHCR images, LAN exposure with token auth, and upgrades.
- [`operations.md`](operations.md) - sessions, cron, usage, diagnostics,
migration, MCP server, and install inventory commands.
- [`troubleshooting.md`](troubleshooting.md) - common install/runtime issues.
- [`glossary.md`](glossary.md) - short definitions for product terms.
## Improve These Docs
Documentation improvements are welcome. Start with
[`contributing-docs.md`](contributing-docs.md) for docs-specific guidance, then
open a small pull request against `main`.
Fast paths:
- Report a stale command, broken link, or confusing page with the
[documentation issue template](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml).
- Edit the affected Markdown page on GitHub and open a focused pull request
against `main`.
- For new feature documentation, keep independent features on independent pages
under `docs/features/`.
## Design Principle
OpenSquilla documentation should help users run the product first, then
understand its special advantages. Mechanism-heavy runtime detail belongs in
developer design notes or source comments, not in the first-run path.
---
[Product guide](../README.product.md) · [中文](../README.zh-Hans.md) · [日本語](../README.ja.md) · [Français](../README.fr.md) · [Deutsch](../README.de.md) · [Español](../README.es.md) · [Improve these docs](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml) · [Contributing](../CONTRIBUTING.md)
+96
View File
@@ -0,0 +1,96 @@
# Durable Agents
OpenSquilla agents are named runtime profiles. Use them when different work
streams need different defaults, such as a research workspace, a writing
workspace, or a channel-facing assistant.
The built-in `main` agent is always available. Additional agents are configured
with `opensquilla agents`.
## When to Create an Agent
Create a durable agent when you want a stable identity for:
- a dedicated workspace;
- a default model choice;
- a separate channel or automation target;
- a recurring task profile;
- a specialized assistant name and description.
Do not create a new agent for every conversation. Use sessions for ordinary
conversation continuity.
## List Agents
```sh
opensquilla agents list
opensquilla agents list --json
```
## Add an Agent
```sh
opensquilla agents add research \
--name Research \
--description "Research and synthesis workspace" \
--workspace /path/to/research \
--model gpt-5.4-mini
```
Agent changes are written to configuration. Restart the gateway before relying
on the updated agent list:
```sh
opensquilla gateway restart
```
## Use an Agent With Sessions
Filter sessions by agent:
```sh
opensquilla sessions list --agent research
```
Create scheduled work for an agent:
```sh
opensquilla cron add \
--agent research \
--every 1h \
--text "Summarize new research notes" \
--name research-hourly-summary
```
Channel configuration can also route incoming messages to configured agents
depending on the channel setup.
## Delete an Agent
```sh
opensquilla agents delete research
opensquilla agents delete research --force
```
Deleting an agent entry leaves workspace files and state untouched. Clean those
up separately only when you are sure they are no longer needed.
## Agents vs Sessions vs Skills
| Concept | Use for |
| --- | --- |
| Agent | Durable identity and defaults for a work stream. |
| Session | Conversation history and active task continuity. |
| Skill | Reusable workflow instructions or tool routines. |
| Meta-skill | A composed workflow made from multiple skill steps. |
Read next:
- [`sessions.md`](sessions.md)
- [`features/skills.md`](features/skills.md)
- [`features/meta-skills.md`](features/meta-skills.md)
- [`channels.md`](channels.md)
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+137
View File
@@ -0,0 +1,137 @@
# Approvals and Permissions
Approvals and permissions control how OpenSquilla tools are allowed to act.
They matter most when an agent can write files, run shell commands, publish
artifacts, post into channels, or call external services.
Use this page before running unattended automation or giving a channel-connected
agent broad tool access.
## Permission Profiles
Single-shot automation accepts an explicit permission profile:
```sh
opensquilla agent --permissions restricted -m "Inspect this repo"
opensquilla agent --permissions on -m "Run with host execution and approvals"
opensquilla agent --permissions bypass -m "Trusted local automation"
opensquilla agent --permissions full -m "Fully trusted local automation"
```
Practical meaning:
| Profile | Use when |
| --- | --- |
| `restricted` / `off` | The task should stay conservative and avoid elevated execution. |
| `on` | Host execution is allowed, but approval checks still matter. |
| `bypass` | You trust the task enough to auto-grant approvals while keeping sensitive-path checks. |
| `full` | You fully trust the task and environment. Use sparingly. |
For automation, prefer the narrowest profile that can complete the task.
## Workspace Containment
Set a workspace for file and shell work:
```sh
opensquilla agent \
--workspace /path/to/project \
--workspace-strict \
-m "Summarize this repo"
```
Contain writes to the workspace or scratch directory:
```sh
opensquilla agent \
--workspace /path/to/project \
--workspace-lockdown \
--scratch-dir /path/to/project/.scratch \
-m "Investigate and prepare a minimal patch"
```
Use `--workspace-lockdown` for unattended runs where accidental writes outside
the project would be unacceptable.
## Interactive Approvals
Interactive chat surfaces can pause sensitive tool calls for a human decision.
Gateway-backed terminal chat supports:
```text
/approvals
/approvals reset
/permissions status
/permissions on
/permissions off
/permissions bypass
/permissions full
/forget
```
Use these commands when you need to inspect or reset cached approval decisions
during a chat.
The Web UI also provides an approvals surface for reviewing pending actions
outside the message scrollback.
## Sandbox Posture
Inspect sandbox posture:
```sh
opensquilla sandbox status
opensquilla sandbox status --json
```
Set posture:
```sh
opensquilla sandbox on
opensquilla sandbox bypass
opensquilla sandbox full
opensquilla sandbox reset
```
Restart the gateway after changing global sandbox posture:
```sh
opensquilla gateway restart
```
## Recommended Defaults
| Situation | Recommended approach |
| --- | --- |
| First run in a repo | `--workspace` plus `--workspace-strict` |
| Read-only investigation | `--permissions restricted` |
| Local patch with tests | `--workspace-lockdown` plus a scratch directory |
| Web UI task with writes | Keep approvals visible and review sensitive actions |
| Channel-connected agent | Conservative permissions and explicit channel setup |
| Unattended automation | Bound timeout/iterations and choose the narrowest workable permissions |
## Troubleshooting
If a tool is denied:
```sh
opensquilla sandbox status
opensquilla doctor
```
Then check:
- whether the surface supports live approvals;
- whether the workspace path is correct;
- whether cached approvals need to be reset;
- whether the task should run with a different permission profile.
Read next:
- [`tools-and-sandbox.md`](tools-and-sandbox.md)
- [`web-ui.md`](web-ui.md)
- [`channels.md`](channels.md)
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+121
View File
@@ -0,0 +1,121 @@
# Artifacts and Media
OpenSquilla can create and deliver files as part of agent work: reports, HTML
files, PDFs, slide decks, spreadsheets, generated images, and other artifacts.
Use artifacts when the output is too large, visual, structured, or important to
leave only in chat text.
## Artifacts
Artifacts are user-visible files created during a session. In Web UI chat they
appear as artifact cards when the runtime publishes them. In CLI runs, artifact
events can include file names, ids, and download URLs.
Common use cases:
- generate a report;
- create a standalone HTML prototype;
- build a CSV/XLSX workbook;
- create a PDF briefing;
- produce a slide deck;
- package generated output for channel delivery.
Ask directly:
```text
Create a one-page HTML dashboard from this data and publish it as an artifact.
```
```text
Generate a PDF briefing with sources and publish the final file.
```
## When to Use Artifacts Instead of Chat
Use artifacts for:
- files the user should download or share;
- tables or reports that need layout;
- generated apps, dashboards, or prototypes;
- long output that would be awkward in chat;
- channel delivery where the platform supports file upload.
Use chat text for short answers, decisions, and next steps.
## Document Skills
OpenSquilla includes skills for common document formats:
- `docx` for Word documents;
- `pptx` for PowerPoint decks;
- `xlsx` for Excel workbooks;
- `pdf-toolkit` for structured PDF work;
- `html-to-pdf` for styled PDF rendering.
Discover them:
```sh
opensquilla skills search pdf
opensquilla skills view pptx
opensquilla skills view xlsx
```
Some document features require optional native/system dependencies. Use
`opensquilla skills list` and `opensquilla doctor` to check readiness.
## Image Input and Generation
In terminal chat, send an image for analysis:
```text
/image /path/to/screenshot.png Describe what is wrong with this UI.
```
Configure image generation:
```sh
opensquilla configure image-generation
```
Then ask for images in chat:
```text
Generate a clean product mockup image for this landing page.
```
Image provider support depends on configured provider credentials, optional
dependencies, and runtime policy.
## Text to Speech and Media Helpers
The media tool family includes image, PDF, and TTS helpers. Availability can
depend on provider config, optional dependencies, and runtime policy.
Use media helpers when the requested output is naturally a file or asset rather
than a plain text answer.
## Channel Delivery
Channels differ in file-size limits, threading behavior, and upload APIs. If a
channel cannot deliver an artifact directly, use the Web UI artifact card or
session export as the recovery surface.
For channel setup, see [`channels.md`](channels.md).
## Troubleshooting
If an artifact does not appear:
1. Check the chat or CLI output for artifact events.
2. Open the Web UI session and inspect artifact cards.
3. Export the session if you need durable evidence:
```sh
opensquilla sessions export <session-key>
```
4. Run `opensquilla doctor` if a document or media dependency appears missing.
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+496
View File
@@ -0,0 +1,496 @@
# Meta-Skill Authoring Guide
This guide is for authors and maintainers who write, validate, and review
OpenSquilla MetaSkills. For user-facing guidance, read
[`../features/meta-skill-user-guide.md`](../features/meta-skill-user-guide.md).
## What a MetaSkill Is
A MetaSkill is a `SKILL.md` file with:
- `kind: meta`;
- one or more natural-language `triggers`;
- a `composition:` block that defines a directed acyclic graph of steps.
At runtime, the model may call:
```text
meta_invoke(name="<meta-skill-name>")
```
OpenSquilla then executes the declared composition step by step and returns the
final result to the user. The model chooses the workflow, but the runtime
enforces dependency order, template rendering, risk metadata, recursion guards,
tool gates, pauses, and final text selection.
Operators can disable model-visible MetaSkill behavior globally:
```toml
[meta_skill]
enabled = false
```
When disabled, MetaSkills remain installed for inventory and historical run
inspection, but they are not injected into prompts, `meta_invoke` is not
surfaced to the model, and explicit `meta_invoke` calls are rejected.
## When to Use a MetaSkill
Use a MetaSkill when a task is repeatable and naturally decomposes into a small
workflow, for example:
- classify the user request, then route to the right specialist skill;
- run two independent analysis skills, then merge their outputs;
- search or inspect context, then summarize it into a user-facing answer;
- execute a deterministic CLI-backed skill, then review or persist the result;
- pause for structured user input before continuing.
Do not use a MetaSkill for one-off instructions, open-ended planning that should
remain conversational, or flows that need arbitrary recursion. A MetaSkill
cannot compose another MetaSkill.
## Where to Put a MetaSkill
For local managed skills, create:
```text
~/.opensquilla/skills/<skill-name>/SKILL.md
```
For repository-bundled skills, place the skill under the bundled skills tree:
```text
src/opensquilla/skills/bundled/<skill-name>/SKILL.md
```
Generated proposals are reviewed before installation. After accepting a
proposal, OpenSquilla promotes it into the managed skills directory and refreshes
the live skill loader.
## Basic Authoring Flow
1. Define the task contract: inputs, output, boundaries, false positives, and
user-confirmation points.
2. Write a conservative `name`, `description`, and `triggers`.
3. Split the workflow into steps such as intake, collect, analyze, draft, audit,
and deliver.
4. Add `depends_on` whenever a step needs output from earlier steps.
5. Filter all user input and previous step output in templates.
6. Declare risk metadata and capabilities.
7. Run deterministic and soft-activation checks.
8. Inspect proposal and auto-enable audit output before accepting or enabling.
Users can activate a MetaSkill in two ways:
- Soft activation: ask naturally, and let the model choose the right
`meta_invoke` call.
- Explicit activation: ask for the named MetaSkill when debugging or testing.
## Required Frontmatter
Every MetaSkill should declare:
```yaml
---
name: short-stable-name
kind: meta
description: One sentence that tells the model when this workflow applies.
triggers:
- short phrase users naturally type
meta_priority: 50
always: false
final_text_mode: auto
metadata:
opensquilla:
risk: low
capabilities: []
composition:
steps: []
---
```
The fields have these meanings:
- `name`: stable identifier used by `meta_invoke`.
- `kind`: must be `meta`.
- `description`: model-facing description for when to use the workflow.
- `triggers`: phrases used by deterministic and model-assisted activation.
- `meta_priority`: sort key when multiple MetaSkills may match.
- `always`: normally `false`; MetaSkills should not be injected unconditionally.
- `final_text_mode`: how the final answer is derived.
- `metadata.opensquilla.risk`: highest unattended auto-enable risk.
- `metadata.opensquilla.capabilities`: explicit side-effect capabilities.
- `composition.steps`: ordered DAG definition.
## Risk Metadata
Use `metadata.opensquilla.risk` to declare the highest risk level required by
the workflow:
- `low`: read-only reasoning, classification, summarization, or safe local
inspection.
- `medium`: local file or artifact writes, deterministic document generation, or
network reads.
- `high`: shell/process control, credential use, network writes, external side
effects, or direct tool calls that can alter state.
Use `metadata.opensquilla.capabilities` to make side effects explicit. Common
capabilities include:
- `filesystem-write`;
- `artifact-write`;
- `document-export`;
- `network`;
- `network-read`;
- `network-write`;
- `external-side-effect`;
- `credential-use`;
- `process-control`;
- `shell`.
If a referenced sub-skill lacks risk metadata, unattended auto-enable treats the
dependency conservatively. New skills should declare risk and capabilities
instead of relying on legacy compatibility fallbacks.
## Step Types
MetaSkill steps support these execution kinds.
### `agent`
Use `agent` for a normal skill-backed sub-agent turn. This is the best default
for user-facing reasoning and synthesis.
```yaml
- id: summarize
kind: agent
skill: summarize
with:
text: "{{ outputs.search | truncate(2000) }}"
```
### `llm_chat`
Use `llm_chat` for one bounded LLM generation step with no tool loop. This is
useful for intake normalization, compact drafting, final audit, and lightweight
synthesis.
```yaml
- id: normalize
kind: llm_chat
with:
system: "Extract the request fields. Do not ask a question."
task: "{{ inputs.user_message | xml_escape | truncate(1000) }}"
```
### `llm_classify`
Use `llm_classify` when the step should return exactly one value from a closed
set. This is useful for routing, triage, and compact decisions.
```yaml
- id: classify
kind: llm_classify
output_choices: [BUG, FEATURE, QUESTION]
with:
text: "{{ inputs.user_message | xml_escape | truncate(512) }}"
```
### `user_input`
Use `user_input` when the workflow should pause and collect structured data from
the user. The step requires a `clarify:` schema.
```yaml
- id: collect_project
kind: user_input
when: "'NEEDS_CLARIFICATION: yes' in outputs.intake"
clarify:
mode: form
intro: "A few fields are needed before this workflow can continue."
nl_extract: true
fields:
- name: topic
type: string
required: true
prompt: "Topic"
max_chars: 200
```
The supported field types are `string`, `enum`, `int`, and `bool`. Use
`skip_if` or `when` to avoid pausing when intake has enough information.
### `tool_call`
Use `tool_call` only for deterministic direct tool execution. Declare a
`tool_allowlist`, keep arguments narrow, and mark the MetaSkill as high risk when
the tool can change state.
```yaml
- id: persist
kind: tool_call
tool: memory_save
tool_allowlist: [memory_save]
tool_args:
text: "{{ outputs.summary | truncate(2000) }}"
```
### `skill_exec`
Use `skill_exec` for a skill with an `entrypoint:` manifest that should run as a
subprocess. This is appropriate for deterministic CLI-backed skills such as
document conversion or report generation.
```yaml
- id: render
kind: skill_exec
skill: html-to-pdf
with:
html: "{{ outputs.report | truncate(12000) }}"
```
## Step Labels and Progress
Two optional step-level fields drive the WebUI run progress ribbon
(see [`../features/meta-skill-user-guide.md`](../features/meta-skill-user-guide.md)
"Run Progress Ribbon"):
- `label`: a short, human-readable name for the step. The ribbon renders
this as the chip text. If omitted, the WebUI humanizes the step `id`
(e.g. `intake``Intake`).
- `progress_emits`: whether the step's executor may publish live
`status_text` updates to the ribbon. Defaults by kind:
- `agent` / `skill_exec`: `true`
- `tool_call`: `false`
- `llm_chat` / `llm_classify` / `user_input`: ignored
Example:
```yaml
composition:
steps:
- id: intake
kind: llm_chat
label: 意图提取
with: { ... }
- id: search
kind: agent
skill: web-research
label: 检索证据
progress_emits: true
with: { ... }
```
Keep labels short (2-6 chars in CJK, 1-2 words in English). Long labels
get truncated in the ribbon header.
## Dependencies and Parallelism
Steps without dependencies may run in parallel. A step with `depends_on` waits
for all named steps to finish.
```yaml
composition:
steps:
- id: inspect_code
kind: agent
skill: code-reviewer
with:
request: "{{ inputs.user_message | xml_escape | truncate(512) }}"
- id: inspect_tests
kind: agent
skill: test-engineer
with:
request: "{{ inputs.user_message | xml_escape | truncate(512) }}"
- id: merge
kind: agent
skill: summarize
depends_on: [inspect_code, inspect_tests]
with:
text: |
Code review:
{{ outputs.inspect_code | truncate(2000) }}
Test review:
{{ outputs.inspect_tests | truncate(2000) }}
```
The graph must be acyclic. A step may only depend on step ids declared in the
same composition.
## Routing and Failure Handling
Use `route` when an `agent` or `skill_exec` step should choose a skill based on
previous outputs:
```yaml
- id: classify
kind: llm_classify
output_choices: [DOCS, BUG, SECURITY]
with:
text: "{{ inputs.user_message | xml_escape | truncate(512) }}"
- id: handle
kind: agent
skill: summarize
depends_on: [classify]
route:
- when: "outputs.classify == 'DOCS'"
to: writer
- when: "outputs.classify == 'BUG'"
to: debugger
- when: "outputs.classify == 'SECURITY'"
to: security-reviewer
with:
request: "{{ inputs.user_message | xml_escape | truncate(512) }}"
```
Use `on_failure` for a single substitute step. The substitute must exist in the
same plan, must not have its own dependencies, and must not have its own
`on_failure`.
## Final Text Modes
Use `final_text_mode` to control the final user-facing result:
- `auto`: default. The orchestrator summarizes step outputs into a concise final
answer.
- `raw`: return the last non-substitute step output verbatim.
- `step:<step_id>`: return one specific step output verbatim.
Examples:
```yaml
final_text_mode: auto
final_text_mode: raw
final_text_mode: "step:summarize"
```
Use `step:<step_id>` when one step is the intended deliverable. Use `raw` when
the final step already formats a complete report. Use `auto` when the workflow
produces several intermediate outputs that need a compact user-facing summary.
## Template Safety
Templates are Jinja expressions. Treat user input and previous step output as
untrusted:
- For user text, start with `xml_escape` or `slugify`, then bound it with
`truncate`.
- For `outputs.<step_id>`, always bound or encode with `truncate`, `xml_escape`,
`slugify`, or `tojson`.
- Do not pass raw `{{ inputs.user_message }}` into a downstream step.
- Do not pass raw `{{ outputs.some_step }}` into another step.
- Keep prompt-shaped strings explicit, short, and task-specific.
Safe examples:
```yaml
query: "{{ inputs.user_message | xml_escape | truncate(512) }}"
text: "{{ outputs.search | truncate(2000) }}"
slug: "{{ inputs.user_message | slugify | truncate(80) }}"
payload: "{{ outputs.plan | tojson }}"
```
Unsafe examples:
```yaml
query: "{{ inputs.user_message }}"
text: "{{ outputs.search }}"
```
## Activation Guidance
MetaSkills are manual-only by default in normal product use. Users launch them
with `/meta <name>`, so trigger and soft-activation checks are needed only when
you are intentionally supporting `meta_skill.auto_trigger = true`.
When maintaining auto-trigger compatibility, write triggers as short phrases
users naturally type:
- Prefer: `summarize recent history`
- Prefer: `review current diff`
- Avoid: `run the internal OpenSquilla DAG composition meta skill`
Use two to five triggers unless a production workflow has a tested reason to use
more. Avoid triggers that collide with explanation questions such as "how does
this meta-skill work?" A user asking about a MetaSkill should not accidentally
run it when auto-trigger compatibility is enabled.
Set `description` to explain when the model should choose the workflow in
auto-trigger mode. Do not hide critical constraints in the body only; the model
primarily sees the frontmatter and injected skill summary when auto-trigger is
enabled.
## Validation Checklist
Before sharing or enabling a MetaSkill:
1. Confirm the frontmatter parses as YAML.
2. Confirm `kind: meta` and `composition.steps` are present.
3. Confirm all `depends_on`, `route.to`, and `on_failure` references point to
valid steps or skills.
4. Confirm the graph has no cycles.
5. Confirm all user input and step outputs are filtered.
6. Confirm `metadata.opensquilla.risk` and `metadata.opensquilla.capabilities`
reflect the workflow's true side effects.
7. If supporting `meta_skill.auto_trigger = true`, run deterministic trigger
checks with `scripts/meta_trigger_accuracy.py`.
8. If supporting `meta_skill.auto_trigger = true`, run model-decision soft
activation checks with
`scripts/live_meta_soft_activation_e2e.py --env-file /path/to/.env`.
9. For generated skills, inspect the Web UI proposal detail and its auto-enable
audit before accepting or enabling.
## Troubleshooting
If the MetaSkill does not appear to run:
- Check that the `SKILL.md` is under a loaded skill directory.
- Refresh or restart the gateway if the skill was added outside the proposal
accept flow.
- Confirm you ran it with `/meta <name>` on a surface that supports MetaSkill
runs.
- Confirm `disable-model-invocation` is not set for a MetaSkill you expect the
model to invoke.
- If you expect natural-language auto-triggering, confirm
`meta_skill.auto_trigger = true`.
- Confirm the skill has `kind: meta` and a non-empty `composition.steps` list.
- Confirm the user wording matches the triggers or description.
If parsing fails:
- Check duplicate step ids.
- Check unknown `kind` values.
- Check missing `skill` for `agent` or `skill_exec` steps.
- Check missing `output_choices` for `llm_classify`.
- Check missing `clarify.fields` for `user_input`.
- Check missing `tool`, invalid `tool_args`, or mismatched `tool_allowlist` for
`tool_call`.
- Check cycles and undefined `depends_on` references.
If auto-enable is skipped:
- Inspect the proposal's auto-enable audit in the Web UI.
- Add missing risk metadata to referenced sub-skills.
- Lower the workflow's side effects, or require manual review for medium/high
risk workflows.
## Test Prompts
At minimum include:
- English positive trigger;
- explicit invocation;
- pasted-history negative case;
- neighboring-domain negative case;
- output-quality judge rubric.
Use realistic user phrasing with a clear subject and goal. Avoid operator-style
phrases that users would not naturally type.
---
[Docs index](../README.md) · [Product guide](../../README.product.md) · [Improve this page](../contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+165
View File
@@ -0,0 +1,165 @@
# Channels
Channels let OpenSquilla run from messaging platforms while sharing the same
agent runtime as the CLI and Web UI. Use channels when you want the same agent
to answer from Slack, Telegram, Feishu/Lark, Discord, DingTalk, WeCom, Matrix,
QQ, or another supported adapter.
## Supported Channel Types
Inspect your local install:
```sh
opensquilla channels types
opensquilla channels types --json
opensquilla channels describe feishu
```
This build exposes the following channel families:
| Type | Label | Transport | Public URL needed |
| --- | --- | --- | :---: |
| `dingtalk` | DingTalk | websocket | no |
| `discord` | Discord | websocket | no |
| `feishu` | Feishu / Lark | mixed | depends on mode |
| `matrix` | Matrix | websocket | no |
| `qq` | QQ Bot | websocket | no |
| `slack` | Slack | mixed | depends on mode |
| `telegram` | Telegram | mixed | depends on mode |
| `wecom` | WeCom | webhook | yes |
The local `channels describe <type>` output is the source of truth for required
fields, secrets, extras, and restart behavior.
## Setup Flow
Interactive setup:
```sh
opensquilla configure channels
```
Add a channel explicitly:
```sh
opensquilla channels add telegram --name personal
```
Add provider-specific fields as needed. Slack supports two modes:
```sh
# Slack Socket Mode: outbound websocket, no public URL.
opensquilla channels add slack --name team \
--field connection_mode=socket \
--field app_token=xapp-... \
--token xoxb-...
# Slack Events API webhook: requires a public Request URL and signing secret.
opensquilla channels add slack --name team-webhook \
--field connection_mode=webhook \
--field signing_secret=... \
--token xoxb-...
```
Restart the gateway process after config edits:
```sh
opensquilla gateway restart
```
Verify runtime connection:
```sh
opensquilla channels status
opensquilla channels status personal --json
```
Saving a channel proves the config was written. `channels status` proves whether
the running gateway loaded and connected it.
## Manage Channels
```sh
opensquilla channels list
opensquilla channels enable <name>
opensquilla channels disable <name>
opensquilla channels edit <name>
opensquilla channels restart <name>
opensquilla channels logout <name>
opensquilla channels remove <name>
```
Use `gateway restart` after config changes. Use `channels restart <name>` only
for an already-loaded live adapter.
## Slack Modes
Slack Socket Mode uses an outbound websocket and does not require a public
Request URL. It requires the bot token (`xoxb-...`) plus an app-level token
(`xapp-...`) saved as `app_token`.
Slack webhook mode uses the Events API Request URL. It requires the bot token
plus `signing_secret`, and the gateway must be reachable by Slack.
Leave `slack_channel_id` empty when the adapter should reply to the incoming
conversation. Set it only when you want a default fallback channel. Enable
`reply_in_thread` when replies should stay in Slack threads.
## Webhook Channels
Slack webhook mode and WeCom require a public, provider-reachable URL. Feishu
and Telegram may require one depending on mode.
For public channels:
- bind the gateway to a reachable interface;
- place it behind a trusted reverse proxy or tunnel;
- configure auth;
- check provider callback URLs and secrets carefully.
Example bind for a controlled network:
```sh
opensquilla gateway run --listen 0.0.0.0 --port 18791
```
Do not expose an unauthenticated gateway to the public internet.
## Attachments and Artifacts
Channel adapters can differ in attachment and artifact delivery behavior.
OpenSquilla normalizes agent execution through the same runtime path, but the
platform transport still controls file size limits, message threading, and
download/upload capabilities.
When a channel cannot deliver a large artifact directly, use the Web UI artifact
card or session export as the recovery path.
## Troubleshooting
If a channel does not respond:
1. Check config entries:
```sh
opensquilla channels list
```
2. Check runtime status:
```sh
opensquilla channels status <name> --json
```
3. Restart the gateway process after config changes:
```sh
opensquilla gateway restart
```
4. For webhook channels, confirm the public URL, provider callback secret, and
gateway auth/network boundary.
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+330
View File
@@ -0,0 +1,330 @@
# CLI Reference
The `opensquilla` CLI is the fastest way to configure, run, inspect, and
automate OpenSquilla.
Run:
```sh
opensquilla --help
opensquilla <command> --help
```
## Main Commands
| Command | Purpose |
| --- | --- |
| `opensquilla init` | Initialize a workspace. |
| `opensquilla doctor` | Diagnose readiness and print recovery steps. |
| `opensquilla uninstall` | Remove OpenSquilla; keeps your data by default (`--purge-*` to delete). |
| `opensquilla onboard` | Run or inspect first-run setup. |
| `opensquilla configure` | Reconfigure provider, router, channels, search, image generation, or memory embedding. |
| `opensquilla gateway` | Run and manage the gateway server. |
| `opensquilla chat` | Start interactive terminal chat. |
| `opensquilla agent` | Run a single automation-friendly agent turn. |
| `opensquilla code-task` | Run a guarded coding task through Coding mode's host workflow. |
| `opensquilla sessions` | List, inspect, resume, abort, delete, or export sessions. |
| `opensquilla skills` | List, search, view, install, update, publish, and inspect skills. |
| `opensquilla memory` | Inspect and maintain memory. |
| `opensquilla channels` | Configure and inspect messaging channels. |
| `opensquilla providers` | Configure and inspect LLM providers. |
| `opensquilla search` | Configure and use web search. |
| `opensquilla sandbox` | Inspect or change default sandbox posture. |
| `opensquilla cron` | Manage scheduled OpenSquilla runs. |
| `opensquilla cost` | Inspect usage and estimated cost. |
| `opensquilla diagnostics` | Enable or disable runtime diagnostics logging. |
| `opensquilla replay` | Replay a recorded turn from the decision log. |
| `opensquilla migrate` | Import state from external agent runtimes. |
| `opensquilla models` | Inspect available models. |
| `opensquilla agents` | Manage durable agents. |
| `opensquilla mcp-server` | Run the OpenSquilla MCP server bridge. |
| `opensquilla swebench` | Run optional SWE-bench solve/eval workflows. |
| `opensquilla dist` | Emit a reproducible workspace-state inventory. |
| `opensquilla reset` | Reset a session and flush memory synchronously. |
## Run Surfaces
Web UI and gateway:
```sh
opensquilla gateway run
opensquilla gateway start --json
opensquilla gateway status
opensquilla gateway restart
opensquilla gateway stop
```
Terminal chat:
```sh
opensquilla chat
opensquilla chat --model gpt-5.4-mini
opensquilla chat --session <session-key>
opensquilla chat --standalone --workspace /path/to/project
```
Terminal chat uses the stable Python-native terminal backend by default.
OpenTUI is a preview backend selected explicitly with
`OPENSQUILLA_TUI_BACKEND=opentui` when evaluating that backend. Normal terminal
chat does not require Bun or OpenTUI node modules. The OpenTUI preview is for
source checkouts with local Bun dependencies installed:
```sh
bun install --frozen-lockfile --cwd=src/opensquilla/cli/tui/opentui/package
OPENSQUILLA_TUI_BACKEND=opentui uv run opensquilla chat
```
Legacy backend values are rejected before launch. Read [`tui.md`](tui.md) for
terminal chat usage and [`features/tui-frontend.md`](features/tui-frontend.md)
for backend architecture, plugin slots, Router HUD, and replay benchmark
workflow.
Web chat and the CLI gateway TUI support `/meta` for manual MetaSkill launch:
`/meta` lists available workflows and `/meta <name>` runs one. Channel surfaces
can list MetaSkills with `/meta`, but they do not launch MetaSkill runs
directly. Standalone CLI chat requires gateway mode for `/meta`.
One-shot automation:
```sh
opensquilla agent -m "Review the current directory"
opensquilla agent --json -m "Return a short machine-readable summary"
opensquilla agent --workspace /path/to/project --workspace-strict -m "Inspect this repo"
opensquilla agent --timeout 600 --max-iterations 30 -m "Run a bounded investigation"
```
Useful automation flags:
| Flag | Purpose |
| --- | --- |
| `--workspace` | Set the workspace root. |
| `--workspace-strict` | Restrict read-side file tools to the workspace. |
| `--workspace-lockdown` | Contain writes to workspace or scratch directory. |
| `--scratch-dir` | Place temporary scripts/logs/candidate patches in a known directory. |
| `--timeout` | Set total agent wall-clock timeout. |
| `--max-iterations` | Bound the model/tool loop. |
| `--max-provider-retries` | Bound transient provider retries. |
| `--length-capped-continuations` | Bound automatic continuations after length-limited provider output. |
| `--thinking` | Override reasoning level. |
| `--permissions` | Select restricted, bypass, or full permission posture. |
| `--transcript-path` | Write a JSONL transcript for automation. |
| `--usage-path` | Write usage JSON. |
| `--session-db-path` | Persist session replay across invocations. |
## Coding Mode and Code-Task
Coding mode routes code modification work through the `code-task` workflow. It
is designed for trusted repositories: `code-task` runs an OpenSquilla agent on
the host, may install dependencies, and is not an OS sandbox.
```sh
opensquilla code-task solve --repo /path/to/repo --task-file task.md --yes
opensquilla code-task solve --repo https://github.com/org/project.git --issue 123
opensquilla code-task solve --verification-mode scratch --task "Create a small CLI parser" --yes
opensquilla code-task solve --repo /path/to/app --task-file task.md --verification-mode build --yes
```
Use exactly one task source: `--issue`, `--task`, or `--task-file`.
Non-interactive callers must pass `--yes` to acknowledge the trusted-host
boundary. Work happens in an isolated run directory under the OpenSquilla state
tree; the source repo is updated only after the workflow collects and verifies a
productive change.
`--verification-mode red-green` is the default for existing repositories.
`--verification-mode build` is for app or artifact delivery checks.
`--verification-mode scratch` creates an empty throwaway repo and must not be
combined with `--repo`.
## SWE-Bench
`opensquilla swebench` is an optional evaluation surface, not part of the normal
install path. It requires Docker plus the `swebench` extra.
```sh
uv tool install --python 3.12 "opensquilla[recommended,swebench] @ https://github.com/opensquilla/opensquilla/releases/download/v0.5.0rc3/opensquilla-0.5.0rc3-py3-none-any.whl"
opensquilla swebench pull django__django-16429 --dataset verified
opensquilla swebench solve django__django-16429 --dataset verified --json
opensquilla swebench eval predictions.jsonl --dataset verified
```
Use `opensquilla code-task` for trusted real-repository coding tasks when you do
not need the Docker-based SWE-bench harness.
## Configuration Commands
Provider and router:
```sh
opensquilla onboard
opensquilla onboard status
opensquilla configure provider --provider openrouter --api-key-env OPENROUTER_API_KEY
opensquilla configure router --router recommended
opensquilla providers list
opensquilla providers configure openrouter
opensquilla providers status
```
Search:
```sh
opensquilla search list
opensquilla search configure duckduckgo
opensquilla search query "latest OpenSquilla release"
opensquilla configure search --search-provider duckduckgo
```
Channels:
```sh
opensquilla channels types
opensquilla channels describe telegram
opensquilla channels add telegram --name personal
opensquilla channels list
opensquilla channels status
opensquilla channels enable personal
opensquilla channels disable personal
opensquilla channels restart personal
opensquilla channels remove personal
```
Raw config:
```sh
opensquilla config get llm.provider
opensquilla config set gateway.port 18791
```
More detail:
- [`configuration.md`](configuration.md)
- [`providers-and-models.md`](providers-and-models.md)
- [`search.md`](search.md)
- [`channels.md`](channels.md)
## Skills and Meta-Skills
```sh
opensquilla skills list
opensquilla skills search pdf
opensquilla skills view pdf-toolkit
opensquilla skills install <skill-name>
opensquilla skills update --all
opensquilla skills uninstall <skill-name>
opensquilla skills inspect meta-skill-creator
opensquilla skills meta proposals list
opensquilla skills meta runs list
opensquilla skills meta runs show <run-id>
opensquilla skills meta runs steps <run-id>
opensquilla skills meta runs replay <run-id> --dry-run
```
Use `skills inspect` when you want to see the compiled step plan for a
meta-skill before invoking it.
MetaSkills are manual-only by default. In web chat and the CLI gateway TUI,
run `/meta` to list workflows and `/meta <name>` to launch one. Natural-language
auto-triggering is disabled unless `meta_skill.auto_trigger = true` is set in
configuration for compatibility with older behavior.
Read:
- [`features/skills.md`](features/skills.md)
- [`features/meta-skills.md`](features/meta-skills.md)
- [`features/meta-skill-user-guide.md`](features/meta-skill-user-guide.md)
- [`authoring/meta-skills.md`](authoring/meta-skills.md)
## Sessions and History
```sh
opensquilla sessions list
opensquilla sessions show <session-key>
opensquilla sessions resume <session-key>
opensquilla sessions abort <session-key>
opensquilla sessions export <session-key>
opensquilla sessions delete <session-key>
```
Read: [`sessions.md`](sessions.md)
## Memory
```sh
opensquilla memory status
opensquilla memory index
opensquilla memory list
opensquilla memory search "preference"
opensquilla memory show <path>
opensquilla memory dream
opensquilla memory flush-session <session-key>
opensquilla memory repair list
opensquilla memory raw-fallbacks list
```
Read: [`features/memory.md`](features/memory.md)
## Durable Agents and Scheduling
```sh
opensquilla agents list
opensquilla agents add research --name Research --workspace /path/to/research
opensquilla agents delete research
opensquilla cron list
opensquilla cron add --every 1h --text "Summarize important updates" --name hourly-summary
opensquilla cron status <job-id>
opensquilla cron runs <job-id>
```
Read:
- [`agents.md`](agents.md)
- [`scheduling.md`](scheduling.md)
## Cost, Diagnostics, and Replay
```sh
opensquilla cost
opensquilla diagnostics status
opensquilla diagnostics on
opensquilla diagnostics off
opensquilla replay --session <session-key> --turn <turn-id>
```
Use diagnostics and replay when you need to understand why a turn behaved a
certain way.
Read:
- [`usage-and-cost.md`](usage-and-cost.md)
- [`diagnostics-and-replay.md`](diagnostics-and-replay.md)
## MCP Server Bridge
```sh
opensquilla mcp-server run
opensquilla mcp-server run --gateway ws://localhost:18792/ws
```
Read: [`mcp-server.md`](mcp-server.md)
## Uninstall
```sh
opensquilla uninstall --dry-run # preview what is removed and kept
opensquilla uninstall # remove the program, keep your data
opensquilla uninstall --purge-state # also delete runtime state (sessions, logs, cache)
opensquilla uninstall --purge-config # also delete config and secrets
opensquilla uninstall --purge-all # delete ALL OpenSquilla data (needs a typed phrase)
opensquilla uninstall --json # machine-readable plan/result
```
Your data is kept by default; `--purge-*` opts into deletion, and `--purge-all`
requires typing a confirmation phrase (or `--confirm-purge-all "delete
everything"` on non-interactive surfaces). The running gateway is drained and
stopped before anything is removed, and deletion is contained to the OpenSquilla
home — a relocated or shared root is refused. Docker and desktop installs print
guided removal steps instead of deleting an image layer or app bundle; source
installs never delete your checkout.
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+124
View File
@@ -0,0 +1,124 @@
# OpenSquilla Code Signing Policy
This policy documents the current code signing status for OpenSquilla release
artifacts and the rules for any future signing workflow.
## Current Status
Windows release builds are currently unsigned. The Windows desktop installer,
updater metadata, and checksums are built and published without a Windows
code-signing certificate. Download pages and release notes must not claim Windows code signing
until a signing workflow has been approved, enabled, and verified for the
specific release artifact.
macOS release packaging is handled separately through the Apple signing and
notarization path configured by maintainers for macOS artifacts. This document's
planned SignPath section applies to Windows code signing for open-source
community release artifacts.
## User Verification
Users should download OpenSquilla release artifacts from the official GitHub
Releases page and compare file hashes against the published `SHA256SUMS` file
for the same release. A matching checksum verifies that the downloaded bytes
match the bytes published by the project; it does not imply Windows Authenticode
code signing while Windows builds remain unsigned.
## Future SignPath Foundation Plan
OpenSquilla is preparing to apply for free open-source Windows code signing
through SignPath Foundation. This is not enabled yet.
If the project is approved and signing is enabled, the affected open-source
community release artifacts may show `SignPath Foundation` as the Windows
publisher. Because approval is still pending, the following attribution is a
planned signing disclosure and does not claim that current Windows artifacts are
signed:
Free code signing provided by SignPath.io, certificate by SignPath Foundation.
The SignPath Foundation path will apply only to OpenSquilla open-source
community artifacts that are released under the project's OSI-approved license
and that do not include proprietary or commercial-only components.
## Privacy Policy
OpenSquilla's privacy policy is published at [`PRIVACY.md`](../PRIVACY.md). It
describes local data, provider requests, network observability, logs, release
downloads, and deletion. Non-user-initiated network observability can be
disabled before startup with:
```sh
OPENSQUILLA_PRIVACY_DISABLE_NETWORK_OBSERVABILITY=true
```
or with:
```toml
[privacy]
disable_network_observability = true
```
Legacy compatibility environment variables remain honored:
```sh
OPENSQUILLA_TELEMETRY_DISABLED=true
OPENSQUILLA_UPDATE_CHECK_DISABLED=true
```
## Commercial Builds
This policy does not restrict future commercial editions, enterprise builds,
hosted services, support offerings, or proprietary add-ons from using a
separate commercial code-signing certificate or a separate commercial signing
service. Commercial or proprietary release artifacts must not be signed with
the SignPath Foundation certificate path unless they independently satisfy the
foundation program requirements.
## Release Build Requirements
Any future Windows signing workflow must run before updater metadata, blockmaps,
and `SHA256SUMS` are finalized. Signing an `.exe` after `latest.yml`,
`.blockmap`, or `SHA256SUMS` has been generated changes the installer bytes and
invalidates those release metadata files.
Before enabling Windows signing, maintainers must verify:
- the signing provider and certificate are approved for the exact artifact type
- the build runs from the trusted release workflow
- release signing requires maintainer approval
- team members with release or signing access use multi-factor authentication
- if network observability or any other non-user-specified network transfer
remains enabled by default, the installer displays the privacy policy and
exposes the unified network observability disable switch before startup
- signed artifacts, updater metadata, blockmaps, and checksums are generated
from the same final bytes
- release notes and download pages accurately describe the signing status
## Roles And Approval
Repository: <https://github.com/opensquilla/opensquilla>
Initial committers and reviewers:
- [@Open-Squilla](https://github.com/Open-Squilla)
Initial SignPath approvers:
- [@Open-Squilla](https://github.com/Open-Squilla)
OpenSquilla maintainers are responsible for release approval, release notes, and
final publication. If SignPath signing is enabled later, SignPath approvers will
approve signing requests only for the open-source community artifacts covered by
this policy. Additional committers, reviewers, or SignPath approvers must be
listed in this policy before they approve release signing requests. All
committers, reviewers, and approvers must use multi-factor authentication for
GitHub and SignPath access.
## Revocation Or Incident Response
If a signed artifact is found to be incorrect, compromised, or outside the
approved signing scope, maintainers will stop distributing the affected asset,
publish a corrected release or advisory, and request revocation through the
signing provider when appropriate. Unsigned artifacts remain covered by the
project's normal release correction and checksum replacement process.
+394
View File
@@ -0,0 +1,394 @@
# Configuration
OpenSquilla can be configured from the onboarding wizard, the Web UI setup
flow, CLI commands, environment variables, and TOML files. Use CLI commands for
routine setup and edit TOML only for advanced or scripted deployments.
## Config Load Order
OpenSquilla reads configuration in this order:
1. `OPENSQUILLA_GATEWAY_CONFIG_PATH`
2. `./opensquilla.toml`
3. `~/.opensquilla/config.toml`
4. built-in defaults
Use `--config ./opensquilla.toml` when you want to write or inspect a
project-local config file.
## Secret Handling
Prefer environment-variable references for secrets:
```sh
export OPENROUTER_API_KEY="sk-..."
opensquilla configure provider --provider openrouter --api-key-env OPENROUTER_API_KEY
```
Avoid committing raw API keys to TOML files, shell history, examples, or issue
reports.
## First-Run Wizard
```sh
opensquilla onboard
```
Common options:
```sh
opensquilla onboard --if-needed
opensquilla onboard --minimal
opensquilla onboard --provider openrouter --api-key-env OPENROUTER_API_KEY
opensquilla onboard --provider openai --model gpt-5.4-mini --api-key-env OPENAI_API_KEY
opensquilla onboard --provider ollama --model llama3.1
opensquilla onboard status
```
The router mode defaults to `recommended`. Use `--router disabled` when you want
direct single-model routing.
## Reconfigure One Section
The `configure` command edits a selected section:
```sh
opensquilla configure provider --provider openrouter --api-key-env OPENROUTER_API_KEY
opensquilla configure router --router recommended
opensquilla configure router --router openrouter-mix
opensquilla configure router --router disabled
opensquilla configure search --search-provider duckduckgo
opensquilla configure search --search-provider tavily --api-key-env TAVILY_API_KEY
opensquilla configure channels
opensquilla configure image-generation
opensquilla configure memory-embedding
```
Supported sections:
- `provider`
- `router`
- `channels`
- `search`
- `image-generation`
- `memory-embedding`
## Configuration Decision Table
| Need | Preferred command |
| --- | --- |
| First setup | `opensquilla onboard` |
| CI or install scripts | `opensquilla onboard --if-needed` |
| Change provider | `opensquilla configure provider ...` |
| Enable or disable routing | `opensquilla configure router ...` |
| Configure web search | `opensquilla configure search ...` |
| Configure messaging platforms | `opensquilla configure channels` |
| Inspect current values | `opensquilla config get` |
| Persist an advanced key | `opensquilla config set <key> <value> --config <path>` |
## Tool Policy
Advanced scripted runs can narrow the model-visible tool surface with `[tools]`.
To compare tool surfaces across otherwise identical runs, keep the calling
harness unchanged and express the tool difference in config:
```toml
[tools]
profile = "coding"
also_allow = ["retrieve_tool_result"]
deny = ["execute_code", "background_process", "process"]
file_edit_requires_fresh_read = true
file_edit_flexible_recovery = true
```
`profile = "coding"` keeps filesystem, search, shell, session, and memory tools
available, and enables fresh `read_file` context before existing workspace file
edits. The `deny` list above removes the extra Python/background process
surfaces for a narrowed run; omit it for the default coding surface.
`file_edit_flexible_recovery` defaults to `true`: after an exact `old_text`
miss, `edit_file` may apply a unique whitespace/indentation recovery and records
used or rejected recovery events for diagnostics.
## Provider Configuration
Inspect provider support:
```sh
opensquilla providers list
opensquilla providers configure openrouter
opensquilla providers status
```
Onboarding-verified providers include:
- TokenRhythm
- OpenRouter
- OpenAI
- Anthropic
- Ollama
- DeepSeek
- Gemini
- DashScope / Qwen
- Moonshot AI
- Zhipu / Z.AI
- Baidu Qianfan
- Volcengine Ark
OpenSquilla also carries provider registry entries for additional
OpenAI-compatible or self-hosted backends. Use `opensquilla providers list` on
your install to see the current catalog.
Read: [`providers-and-models.md`](providers-and-models.md)
## Router Configuration
Router modes:
| Mode | Use when |
| --- | --- |
| `recommended` | You want the selected provider's default routing profile. |
| `openrouter-mix` | You want OpenRouter mixed-model defaults. |
| `disabled` | You want one configured provider/model for every turn. |
Commands:
```sh
opensquilla configure router --router recommended
opensquilla configure router --router openrouter-mix
opensquilla configure router --router disabled
```
Router-supported provider profiles depend on the installed build and configured
provider. Read [`features/squilla-router.md`](features/squilla-router.md) before
using direct model runs for evaluation.
## Search Configuration
Inspect search providers:
```sh
opensquilla search list
opensquilla search status
opensquilla search query "OpenSquilla release notes"
```
Configure search:
```sh
opensquilla configure search --search-provider duckduckgo
opensquilla configure search --search-provider bocha --api-key-env BOCHA_SEARCH_API_KEY
opensquilla configure search --search-provider brave --api-key-env BRAVE_SEARCH_API_KEY
opensquilla configure search --search-provider tavily --api-key-env TAVILY_API_KEY
opensquilla configure search --search-provider exa --api-key-env EXA_API_KEY
opensquilla configure search --search-provider iqs --api-key-env IQS_SEARCH_API_KEY
```
Runtime-supported search providers in this build include DuckDuckGo, Bocha,
Brave Search, Alibaba Cloud IQS, Tavily, and Exa. DuckDuckGo is the no-key path.
A partial-key setup can configure only one keyed provider; an all-key setup can
expose `BOCHA_SEARCH_API_KEY`, `BRAVE_SEARCH_API_KEY`, `IQS_SEARCH_API_KEY`,
`TAVILY_API_KEY`, and `EXA_API_KEY` so runtime provider selection can choose by
mode and capability unless a request names an explicit provider.
`search_provider` is the credential
anchor for `search_api_key` and `search_api_key_env`; it is not a hard routing
promise for automatic searches.
Additional provider metadata may be present for future or
not-yet-runtime-supported integrations.
Read: [`search.md`](search.md)
## Channel Configuration
List supported channel types:
```sh
opensquilla channels types --json
opensquilla channels describe feishu
opensquilla channels add telegram --name personal
opensquilla channels status
```
Channel saves update configuration. Restart the gateway after edits:
```sh
opensquilla gateway restart
opensquilla channels status <name> --json
```
See [`channels.md`](channels.md) for details.
## Attachments
Attachment ingestion accepts **any file type**. Rendered families (images,
PDF, text, Office documents, email) are extracted or inlined for the model;
everything else is an *opaque* attachment: the bytes are staged into the agent
workspace for tool access and are never parsed, decompressed, or inlined into
a provider prompt.
```toml
[attachments]
# Admit opaque (non-rendered) attachment types: archives, binaries,
# audio/video, unknown formats. false restores the legacy fail-closed
# rendered-types-only admission gate on every surface.
accept_opaque = true
# Per-file ceiling for opaque attachments (bytes).
opaque_max_bytes = 31457280 # 30 MiB
# Aggregate RAM ceiling for the in-memory staged-upload store. When reached,
# new uploads get HTTP 507 UPLOAD_STORE_FULL (retryable; staged entries
# expire within the 10-minute TTL); a payload larger than the cap itself is a
# permanent 413. Non-positive or invalid values fall back to the default —
# this cap can be raised but not disabled. Requires a gateway restart.
upload_store_max_total_bytes = 314572800 # 300 MiB
# Disk budget for attachment copies materialized into an agent workspace
# (<workspace>/.opensquilla/attachments). When exceeded, new materializations
# degrade to an unavailable marker; existing files are never evicted. Set to
# 0 (or any non-positive value) to disable the budget entirely.
workspace_attachment_disk_budget_bytes = 1073741824 # 1 GiB
# Persist attachment bytes with session transcripts.
persist_transcripts = true
# media_root = "" # default: resolved from the cache dir
transcript_disk_budget_bytes = 2147483648 # 2 GiB
artifact_max_bytes = 31457280 # 30 MiB
artifact_disk_budget_bytes = 536870912 # 512 MiB
```
Env overrides use the `OPENSQUILLA_ATTACHMENTS_` prefix
(`OPENSQUILLA_ATTACHMENTS_ACCEPT_OPAQUE`, `OPENSQUILLA_ATTACHMENTS_OPAQUE_MAX_BYTES`, …).
Size policy at a glance: inline attachments up to 2 MB ride the RPC message;
larger files stage through `POST /api/v1/files/upload` (10-minute TTL) up to
30 MiB per file for text (whole-payload UTF-8 proven), PDF, Office, and opaque
types. Email is always capped at the 2 MB text limit and never stages. Per
turn: at most 10 attachments and 60 MiB total.
Behavior notes:
- With `accept_opaque = true` (the default), the upload endpoint no longer
returns HTTP 415 `UNSUPPORTED_MEDIA_TYPE` for unrendered types, and
`sessions.send` no longer rejects them; strict deployments that disable the
flag keep the legacy errors and codes unchanged.
- Opaque files reach the model only as an escaped metadata envelope plus a
workspace path marker; the agent inspects or converts them with filesystem,
shell, or code tools under the active safety tier and approval policy. On
platforms without a sandbox backend those tool actions rely on approvals.
## Memory Configuration
Useful commands:
```sh
opensquilla memory status
opensquilla memory index
opensquilla memory list
opensquilla memory search "project preference"
opensquilla memory show <path>
opensquilla memory dream
opensquilla memory flush-session <session-key>
```
Configure embedding behavior:
```sh
opensquilla configure memory-embedding
```
Memory can combine Markdown-backed sources with SQLite keyword and semantic
indexes. The exact memory shape depends on the configured provider and local
embedding support.
Read: [`features/memory.md`](features/memory.md)
## Sandbox and Permissions
Inspect or change posture:
```sh
opensquilla sandbox status
opensquilla sandbox on
opensquilla sandbox full
opensquilla sandbox bypass
opensquilla sandbox reset
```
Single-shot automation permissions:
```sh
opensquilla agent --permissions restricted -m "Read the repo and summarize it"
opensquilla agent --permissions full -m "Make a local patch and run tests"
```
For unattended automation that must stay inside a workspace:
```sh
opensquilla agent \
--workspace /path/to/project \
--workspace-lockdown \
--scratch-dir /path/to/project/.scratch \
-m "Investigate and propose the smallest fix"
```
Read: [`tools-and-sandbox.md`](tools-and-sandbox.md)
## Outbound URL Filtering And Fake-IP DNS
URL-fetching tools validate resolved addresses through the shared SSRF guard in
`opensquilla.tools.ssrf`. Private, loopback, link-local, and reserved ranges are
blocked by default.
Some trusted proxy or fake-IP DNS setups resolve public hostnames such as
`github.com` to addresses in the RFC 2544 benchmark range `198.18.0.0/15`.
OpenSquilla keeps blocking those addresses unless the operator explicitly opts
in:
```toml
[tools]
trusted_fake_ip_cidrs = ["198.18.0.0/15"]
```
Only subnets of `198.18.0.0/15` are accepted in this setting. Loopback, RFC
1918 private ranges, link-local addresses, and other internal ranges remain
hard-blocked even if configured. If a public hostname resolves to one of those
hard-blocked ranges, fix the DNS or proxy setup instead of bypassing the guard.
## Gateway Binding
Foreground:
```sh
opensquilla gateway run --listen 127.0.0.1 --port 18791
```
Managed:
```sh
opensquilla gateway start --json
opensquilla gateway status
opensquilla gateway stop
opensquilla gateway restart
```
Bind precedence:
1. `--listen`
2. `--bind`
3. `OPENSQUILLA_LISTEN`
4. `OPENSQUILLA_GATEWAY_HOST`
5. config host
6. `127.0.0.1`
## Raw Config Editing
For advanced settings, inspect `opensquilla.toml.example` and edit the active
config file directly. Use CLI commands for routine provider, router, search,
channel, and sandbox changes because they avoid common key-shape mistakes.
After changing files by hand, restart the gateway and run:
```sh
opensquilla doctor
opensquilla gateway status
```
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+69
View File
@@ -0,0 +1,69 @@
# Contributing to the Documentation
OpenSquilla welcomes documentation improvements from users and contributors.
Good documentation changes help people install the product, choose the right
feature, and recover from common problems without needing maintainer context.
## What to Improve
Useful documentation pull requests include:
- clearer install or setup steps;
- runnable command examples;
- screenshots or wording that make the Web UI easier to understand;
- missing provider, channel, memory, skill, or tool workflows;
- troubleshooting notes for common failures;
- corrections when a command, option, or behavior has changed.
Keep feature guides focused on user value and usage. Avoid adding deep runtime
internals unless the detail is needed to help users operate the product.
## How to Edit
1. If the problem is small, open the affected Markdown page on GitHub and use
the pencil edit flow to propose a change. Contributors without repository
write access will submit this through a fork and pull request.
2. If you are not sure of the fix, open a
[documentation issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
with the affected page and expected outcome.
3. Open documentation pull requests against `main`.
4. Keep docs changes small and topic-focused.
5. Use relative links for repository pages.
6. Prefer concrete commands and examples over abstract descriptions.
7. If a page describes a CLI command, verify the command name against the local
CLI or an existing reference page.
For general contribution rules, see [`../CONTRIBUTING.md`](../CONTRIBUTING.md).
## Docs-Only Checks
For documentation-only changes, at minimum check:
- links point to existing repository files;
- Markdown code fences are balanced;
- examples do not include private paths, secrets, or real provider keys;
- screenshots or UI wording match the current product surface;
- product claims stay user-facing and do not expose unnecessary implementation
details.
If a documentation change also changes code, tests, packaging, provider
behavior, gateway behavior, channels, or browser UI behavior, follow the full
project checklist in [`../CONTRIBUTING.md`](../CONTRIBUTING.md).
## Page Structure
Most user-facing pages should answer:
1. What is this feature for?
2. When should I use it?
3. How do I configure or run it?
4. What should I check when it does not work?
5. Where should I go next?
Independent features should stay on independent pages. For example, memory,
skills, meta-skills, SquillaRouter, tool compression, compaction, channels, and
artifacts should not be merged into one broad mechanism page.
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml) · [Contributing](../CONTRIBUTING.md)
+121
View File
@@ -0,0 +1,121 @@
# Diagnostics and Replay
Diagnostics and replay help explain what happened during an OpenSquilla turn.
Use them when a result was surprising, slow, expensive, interrupted, or hard to
reproduce from the chat transcript alone.
## Diagnostics
Diagnostics are runtime logging controls exposed through the gateway.
Check status:
```sh
opensquilla diagnostics status
opensquilla diagnostics status --json
```
Enable diagnostics:
```sh
opensquilla diagnostics on
```
Enable raw turn-call capture when a maintainer asks for deeper provider request
evidence:
```sh
opensquilla diagnostics on --raw
```
Turn diagnostics off after collecting enough evidence:
```sh
opensquilla diagnostics off
```
## When to Use Diagnostics
Use diagnostics for:
- provider retries, timeouts, or empty responses;
- SquillaRouter model decisions;
- prompt-cache or cache-break investigation;
- compaction lifecycle events;
- large tool-result compression;
- channel delivery failures;
- unusually high cost or latency.
Avoid leaving raw diagnostics on longer than needed. Raw captures may contain
private prompts, tool outputs, local paths, or provider-visible content.
## Replay a Recorded Turn
Replay reads a recorded turn from the decision log and prints a human-readable
transcript. It is read-only: it does not re-run tools.
```sh
opensquilla replay --session <session-key> --turn <turn-id>
```
Use replay when:
- a chat has moved on but you need to inspect an earlier turn;
- a bug report needs concise reproduction evidence;
- you want to compare transcript output with diagnostics and cost data.
## TUI Replay Benchmarks
Developers can replay deterministic terminal-chat fixtures without a live
provider:
```sh
uv run python scripts/bench_tui_replay.py --renderer opentui --fixture long-stream --summary-json .artifacts/tui/opentui-long-stream.json
uv run python scripts/bench_tui_replay.py --renderer opentui --fixture dense-history --summary-json .artifacts/tui/opentui-dense-history.json
```
Benchmark summaries include renderer availability, event counts, text size,
tool and router-decision counts, wall time, flush counts, maximum buffered text,
coalescing ratio, transcript item counts, visible viewport counts, expanded tool
counts, viewport projection time, final text match status, plugin error count,
and errors.
Read [`features/tui-frontend.md`](features/tui-frontend.md) for backend status
and [`tui-real-terminal-harness.md`](tui-real-terminal-harness.md) for
maintainer terminal-level launch evidence.
## Pair Replay With Sessions
Find the session first:
```sh
opensquilla sessions list
opensquilla sessions show <session-key>
```
Export the full session if exact context matters:
```sh
opensquilla sessions export <session-key> --output session.md
```
## Safe Sharing
Before sharing diagnostics, replay output, or exported sessions publicly,
remove:
- provider keys and bearer tokens;
- private local paths;
- private channel identifiers;
- customer, project, or account names that should not be public;
- raw provider prompts or tool outputs that include confidential content.
Read next:
- [`sessions.md`](sessions.md)
- [`usage-and-cost.md`](usage-and-cost.md)
- [`troubleshooting.md`](troubleshooting.md)
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+262
View File
@@ -0,0 +1,262 @@
# Docker Deployment
Run the OpenSquilla gateway as a container on a machine that stays on — a home
server, a NAS, or a small VPS. This page uses Debian 12 as the worked example,
but any host with Docker Engine works the same way, on both `amd64` and `arm64`.
Docker is the right install path when:
- the host has no Python 3.12+ toolchain (or you do not want one),
- you want the gateway to survive reboots and upgrade by pulling a new image,
- you deploy on a NAS or headless server and use the Web UI from another device.
For a desktop machine, the [quickstart](quickstart.md) installs are simpler.
## Prerequisites
Install Docker Engine with the Compose plugin. On Debian 12, follow the
[official Docker instructions](https://docs.docker.com/engine/install/debian/),
then verify:
```sh
docker --version
docker compose version
```
Nothing else is required on the host for the prebuilt-image path — no
Python, no Git, no build tools.
## Quick Start with the Prebuilt Image
Prebuilt multi-arch images are published to
[`ghcr.io/opensquilla/opensquilla`](https://github.com/opensquilla/opensquilla/pkgs/container/opensquilla)
for each release tag. The immutable `v0.5.0rc3` tag identifies Preview 3, while
`latest` follows the most recently pushed release tag, including previews and
backports. If a backport moves `latest`, the newest release workflow is rerun to
restore the intended ordering. If the release you want predates image
publishing, use
[Build the Image Yourself](#build-the-image-yourself) instead. A pull that
fails with `denied` or `manifest unknown` means the image for that tag has
not been published (or the package is not public yet) — check the package
page for available tags, or build from source.
Create a directory for the deployment and write this `compose.yaml`:
```yaml
services:
gateway:
# Pin v0.5.0rc3 for reproducibility; latest follows the most recent tag push.
image: ghcr.io/opensquilla/opensquilla:latest
environment:
# In-container bind. Keep it 0.0.0.0 — what the network can reach is
# decided by `ports` below, not by this value.
OPENSQUILLA_LISTEN: "0.0.0.0"
# Token auth is required to administer a containerized gateway through
# the Web UI, even from the same host. Generate a token with:
# openssl rand -hex 32
OPENSQUILLA_AUTH_MODE: token
OPENSQUILLA_AUTH_TOKEN: ${OPENSQUILLA_AUTH_TOKEN:?generate one with openssl rand -hex 32}
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY:-}
TZ: ${TZ:-UTC}
volumes:
# All state — config, session DBs, memory, logs, workspace — lives under
# /var/lib/opensquilla. The named volume makes it survive recreates.
- opensquilla-state:/var/lib/opensquilla
ports:
# Loopback-only: reachable from this host, invisible to the network.
# For NAS/LAN access see "Reach the Web UI from Your LAN" below.
- "127.0.0.1:18791:18791"
restart: unless-stopped
volumes:
opensquilla-state:
```
Put the two secrets in a `.env` file next to `compose.yaml` (Compose reads it
automatically; keep it out of version control and private: `chmod 600 .env`):
```sh
OPENSQUILLA_AUTH_TOKEN=<output of: openssl rand -hex 32>
OPENROUTER_API_KEY=<your provider key>
```
Start it:
```sh
docker compose up -d
docker compose logs -f gateway
```
Then open the Web UI with the token in the URL:
```text
http://127.0.0.1:18791/control/?token=<your OPENSQUILLA_AUTH_TOKEN>
```
The token is consumed once and stored for the browser session. The first
request also writes the token into the gateway access log, so treat
`docker compose logs` output as sensitive — or open `/control/` without the
query parameter and paste the token into the connection panel instead. From
there, finish provider onboarding and configuration in the Web UI — provider
changes apply immediately and persist in the state volume.
Why token auth is not optional here: the container binds a wildcard address,
so the gateway treats every browser — including one on the same host — as a
remote operator. Remote operators without a token can chat but cannot
administer configuration or onboarding (only a small allowlist of safe
runtime toggles stays writable). With `OPENSQUILLA_AUTH_MODE=token` the token
grants the operator scopes that Web UI administration needs. Use `token` mode
specifically; `password` and `trusted-proxy` modes do not support the Web UI
connection.
## Reach the Web UI from Your LAN
On a headless NAS you will use the Web UI from another device. Two rules:
1. Publish the port on all interfaces by changing the `ports` entry — do
**not** change `OPENSQUILLA_LISTEN`:
```yaml
ports:
- "18791:18791"
```
2. Keep token auth configured (already true if you followed the quick start).
The gateway warns, but does not refuse, when it is network-reachable —
exposure is your call, auth is not.
Recreate the container (`docker compose up -d`) and open
`http://<server-address>:18791/control/?token=<token>` from your device.
If the host runs a firewall, allow inbound TCP 18791 from your LAN only.
LAN traffic to the gateway is plain HTTP, so the token is visible to anyone
who can observe that network — if your LAN is not fully trusted, put the
gateway behind a TLS reverse proxy or use the VPN option below.
Do not forward the gateway port to the internet. For remote access away from
home, use a VPN (WireGuard, Tailscale) or a reverse proxy with TLS and its own
authentication in front. See the safety defaults in [`gateway.md`](gateway.md).
## Keep State on Your Own Storage (Bind Mount)
The named volume is the safest default. If you prefer a directory you manage
(RAID storage, backup tooling), bind-mount it — but the container runs as
non-root UID 10001, so give it ownership first or the gateway fails at boot:
```sh
sudo mkdir -p /srv/opensquilla
sudo chown -R 10001:10001 /srv/opensquilla
```
```yaml
volumes:
- /srv/opensquilla:/var/lib/opensquilla
```
Everything worth backing up is under that one directory: `config.toml`,
`state/` (session and scheduler databases), `logs/`, `workspace/`, `media/`,
and an optional `.env`.
## Configure Providers and Secrets
Three ways, in order of preference:
1. **Web UI** — provider onboarding and most config changes at `/control/`
hot-apply and persist to `config.toml` in the state volume. Channel,
memory-embedding, and sandbox-posture changes need a restart — the Web UI
marks these, and `docker compose restart gateway` applies them.
2. **Compose `environment`** — pass provider keys by env-var name, as in the
quick start. Environment values always win over `.env` files.
3. **A `.env` inside the state volume** — the gateway loads
`/var/lib/opensquilla/.env` at startup, so keys survive image upgrades
without appearing in `compose.yaml`. On a bind mount, keep it owned by the
container user and private: `chown 10001:10001 .env && chmod 600 .env`.
Caveat: a key listed under `environment:` in `compose.yaml` shadows the
state-volume `.env` even when the host variable is unset (Compose passes
an empty value through) — remove it from `environment:` if you manage it
in the state volume.
One precedence caveat for auth: values saved to `config.toml` — for example
by the Web UI — take precedence over environment variables at boot. If the
`OPENSQUILLA_AUTH_*` variables stop taking effect after configuring through
the Web UI, `config.toml` now owns the `[auth]` settings; rotate the token
there (or in the Web UI) and restart.
Hand-edits to `/var/lib/opensquilla/config.toml` are read at boot only —
restart to apply them:
```sh
docker compose restart gateway
```
## Change the Published Port
Change the host side of the mapping and keep the container side at 18791:
```yaml
ports:
- "127.0.0.1:8080:18791"
```
Setting `OPENSQUILLA_GATEWAY_PORT` does **not** change the listen port of the
container entrypoint — the port lives in the mapping above.
## Health and CLI Access
`/healthz` answers liveness without auth, and `/readyz` returns 503 until the
gateway is fully ready. The image ships a healthcheck; inspect it with:
```sh
docker inspect --format '{{.State.Health.Status}}' $(docker compose ps -q gateway)
```
The full CLI is available inside the container:
```sh
docker compose exec gateway opensquilla doctor
docker compose exec gateway opensquilla gateway status
```
## Upgrade and Roll Back
State lives in the volume, so containers are disposable:
```sh
docker compose pull
docker compose up -d
```
To roll back, pin the previous release tag in `image:` and `docker compose up
-d` again. Pinned tags plus a state backup make both directions routine.
## Build the Image Yourself
The source checkout ships the same `Dockerfile` and a `compose.yaml` that
defaults to a self-built `opensquilla:local` image (override with
`OPENSQUILLA_GATEWAY_IMAGE` to use the GHCR image instead). Building needs
`git`, `git-lfs`, and the Git LFS router assets:
```sh
sudo apt install -y git git-lfs
git clone https://github.com/opensquilla/opensquilla.git
cd opensquilla
git lfs pull --include="src/opensquilla/squilla_router/models/**"
docker build -t opensquilla:local .
docker compose up -d
```
On a low-power or `arm64` NAS this build is slow; prefer the prebuilt image
and keep source builds for development machines.
## If Something Fails
- `docker compose logs gateway` shows boot errors, including an unwritable
state directory (fix ownership as above).
- `docker compose exec gateway opensquilla doctor` reports readiness and
recovery steps.
- The Docker sections in [`troubleshooting.md`](troubleshooting.md) cover the
common failures: unreachable Web UI, rejected configuration changes,
bind-mount permissions, and LFS-related build errors.
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+63
View File
@@ -0,0 +1,63 @@
# Runtime experiment toggles ("levers")
OpenSquilla exposes a family of opt-in runtime behaviors that scripted or
harness-controlled runs can enable per run without changing code or config
files. This page records the conventions those toggles must follow and how a
calling harness can verify that a toggle it requested was actually delivered.
The companion tooling lives in `scripts/experiments/`.
## Conventions
- **Naming**: `OPENSQUILLA_<AREA>_<KNOB>` (e.g.
`OPENSQUILLA_PROVIDER_HISTORY_DEDUP`,
`OPENSQUILLA_TOOL_REPEAT_NUDGE_THRESHOLD`).
- **Single parse site**: environment values are parsed only in
`engine/turn_runner/agent_bootstrap_stage.py` (`_*_from_env` helpers), flow
into `AgentConfig` fields, and are consumed by runtime resolvers. Nothing
else in the engine reads these variables directly.
- **Default off**: with no toggle set, the runtime behaves like stock
OpenSquilla. A toggle must never change behavior for users who have not set
it.
- **Strict values**: unrecognized values raise instead of being silently
ignored, so a run manifest cannot record an override the run did not
actually apply.
- **Provider differences live in policy tables**: per-provider behavior
belongs in `OpenAICompatPolicy`, `ProviderContextProfile`, or
`reasoning_dialects` fields — never in model-name conditionals at call
sites.
## Delivery verification
A harness that sets toggles can verify delivery end to end:
1. The harness allowlist decides which variables are passed into the
container (`docker exec -e ...`).
2. The harness echoes the delivered environment into the run's
`metadata.json` under `agent.controls.progress_watchdog_env`. This echo is
written by the harness adapter unconditionally — it does not depend on any
runtime toggle, including the watchdog mode itself.
3. `scripts/experiments/exp_finalize.py` gates a finished run on the expected
environment (`AGENT_ENV_DELIVERY_VARS`), and
`scripts/experiments/check_treatment_delivery.py` asserts the resulting
provider payload shape (e.g. expected proof budget, reasoning effort, and
a bounded number of reasoning fallbacks).
## Adding a new toggle
A new toggle must:
1. be added to the calling harness's allowlist,
2. default off, and
3. be added to `AGENT_ENV_DELIVERY_VARS` if it can affect task outcomes, so
the delivery gate covers it.
## Reproducing older behavior
Two defaults were flipped to off when this code was merged; runs that want
the previous behavior should pin them explicitly:
- `OPENSQUILLA_PROGRESS_WATCHDOG_MODE=warn_model` (merged default: `off`;
other values: `log`, `block`). Harness-controlled runs should always pin
this mode explicitly rather than relying on the default.
- `OPENSQUILLA_TOOL_REPEAT_NUDGE_THRESHOLD=3` (merged default: `0`,
disabled).
+189
View File
@@ -0,0 +1,189 @@
# Feature Catalog
OpenSquilla combines a personal-agent runtime with model routing, tools, memory,
channels, scheduling, and reusable skills.
## Product Surfaces
| Surface | What it is for |
| --- | --- |
| Web UI | Local control console, setup, chat sessions, approvals, logs, channels, and usage surfaces. |
| CLI chat | Interactive terminal agent work. |
| CLI agent | Single-turn automation, CI-like runs, and benchmark-style invocations. |
| Gateway RPC | Local server surface for Web UI, CLI clients, channels, and external clients. |
| Channels | Telegram, Slack, Feishu/Lark, Discord, DingTalk, WeCom, Matrix, QQ, terminal, and websocket-style integrations. |
## Distinctive Features
### SquillaRouter
Local routing for model tier selection. It is designed to keep easy turns cheap
and reserve expensive models for work that needs them.
Read: [`features/squilla-router.md`](features/squilla-router.md)
### TUI Frontend
Terminal chat uses a streaming plane for token deltas and a structured UI plane
for plugin snapshots such as the Router HUD.
Read: [`tui.md`](tui.md) for user-facing terminal chat usage and
[`features/tui-frontend.md`](features/tui-frontend.md) for backend details.
### Tool Compression
Large tool outputs are projected into compact provider-visible previews while
the runtime can keep richer raw results out-of-band.
Read: [`features/tool-compression.md`](features/tool-compression.md)
### Meta-Skills
Repeatable multi-step workflows can be represented as skills, inspected,
proposed, replayed, and reused. By default, users launch them manually on
supported chat surfaces with `/meta` and `/meta <name>`.
Read: [`features/meta-skills.md`](features/meta-skills.md) and
[`features/meta-skill-user-guide.md`](features/meta-skill-user-guide.md)
### Memory
Durable memory lets OpenSquilla recall useful user preferences, project notes,
and previous task traces without forcing every old transcript into the active
prompt.
Read: [`features/memory.md`](features/memory.md)
### Skills
Skills package task-specific guidance and scripts so the agent can load the
right operating instructions only when a task needs them.
Read: [`features/skills.md`](features/skills.md)
### Compaction and Cache Continuity
Long sessions can compact old context, preserve recent task state, and report
compaction lifecycle events.
Read: [`features/compaction-and-cache.md`](features/compaction-and-cache.md)
### Sessions and Durable Agents
Sessions preserve conversation continuity, exports, and running-task control.
Durable agents provide named identities and defaults for recurring workstreams.
Read: [`sessions.md`](sessions.md) and [`agents.md`](agents.md)
### Usage, Diagnostics, and Permissions
Usage reports explain recent model spend. Diagnostics and replay help inspect a
turn after it runs. Permission and approval controls keep tool access matched to
the task.
Read: [`usage-and-cost.md`](usage-and-cost.md),
[`diagnostics-and-replay.md`](diagnostics-and-replay.md), and
[`approvals-and-permissions.md`](approvals-and-permissions.md)
## Core Runtime Capabilities
- Unified `TurnRunner` path across Web UI, CLI, and channels.
- Provider abstraction for OpenAI-compatible APIs, Anthropic, Ollama, and other
configured backends.
- Streaming responses, tool calls, retries, approvals, artifacts, and final
usage accounting.
- Durable session storage with transcript, summaries, context states, and
replay support.
- Per-agent workspaces and durable agent entries.
- Subagent support for bounded delegation.
## Tools
OpenSquilla includes tools for:
- Filesystem read/write/edit/list/glob/grep.
- Shell commands, background processes, and code execution.
- Git status, diff, log, and commit.
- Web search and web fetch.
- Memory search/save/get/delete.
- Session search, session spawn/send/history/status.
- Artifact publication.
- Image generation, PDF, TTS, and media workflows.
- Spreadsheet, PPTX, DOCX, CSV, and PDF authoring through bundled skills.
- Feishu/Lark docs, chat, drive, wiki, permissions, and media upload.
- Cron and gateway administration.
- Skill listing, viewing, creating, editing, installing dependencies, and
meta-skill invocation.
Read: [`tools-and-sandbox.md`](tools-and-sandbox.md)
## Skills
Bundled user-facing skills include:
- `deep-research`
- `summarize`
- `memory`
- `cron`
- `github`
- `docx`
- `pptx`
- `xlsx`
- `pdf-toolkit`
- `html-to-pdf`
- `multi-search-engine`
- `weather`
- `tmux`
- `sub-agent`
- `skill-creator`
Retained bundled MetaSkills include `meta-kid-project-planner`,
`meta-paper-write`, `meta-short-drama`, and `meta-skill-creator`. Experimental
MetaSkills may exist in development trees, but they are not presented as stable
built-in product capabilities.
Read: [`features/skills.md`](features/skills.md)
## Scheduling
The `cron` command group manages scheduled OpenSquilla runs:
```sh
opensquilla cron list
opensquilla cron add \
--every 1h \
--text "Summarize important project updates" \
--name hourly-project-check
opensquilla cron status <job-id>
opensquilla cron run <job-id>
opensquilla cron runs <job-id>
```
Scheduled jobs can deliver work through configured surfaces such as channels or
webhooks depending on the configured job.
Read: [`scheduling.md`](scheduling.md)
## Migration
OpenSquilla can import compatible state from OpenClaw and Hermes Agent. It can
also copy a complete supported CLI/Desktop profile, or historical Windows
Portable data, into a separately owned OpenSquilla profile:
```sh
opensquilla migrate openclaw --json
opensquilla migrate openclaw --apply
opensquilla migrate hermes --json
opensquilla migrate hermes --apply
opensquilla migrate opensquilla --source PATH --json
opensquilla migrate opensquilla --source PATH --apply
```
Same-product imports always require explicit source selection. A populated
target is never merged: it can only be kept or fully backed up and replaced.
Read: [`../MIGRATION.md`](../MIGRATION.md).
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+453
View File
@@ -0,0 +1,453 @@
# LLM Ensemble Design: Static Lineups & Dynamic Router Selection
`llm_ensemble` runs a **B5 fusion** turn: several *proposer* models each draft
an answer, and one *aggregator* model fuses those drafts into the final
response. This document describes how the **set of models** is chosen for a
turn. It does not cover the ensemble runtime mechanics (streaming, timeouts,
quorum, fallback) — only model selection.
## Why an ensemble instead of a single model
Any single model has a fixed set of blind spots: the failure modes of its
training data, its decoding randomness, and its particular biases. Asking that
one model again doesn't remove them — it re-rolls the *same* distribution. An
ensemble attacks the problem from a different angle: draft an answer with
several *different* models, then have an aggregator reconcile them. The wins
over a single-model turn:
- **Error cancellation / higher accuracy.** Independent models rarely make the
*same* mistake on the same input. When drafts disagree, the aggregator can
cross-check them and keep the answer the majority supports; when they agree,
that agreement is real signal that the answer is solid. Idiosyncratic
one-off errors get outvoted instead of shipped.
- **Coverage through diversity.** Different vendors/families/architectures have
genuinely different strengths — one is better at code, another at long-form
reasoning, another at careful instruction-following. A lineup that spans them
covers more of the input space than any single model's strong suit. This is
exactly why selection *rewards diversity* (distinct vendor/family/
architecture) rather than picking the top-N by raw quality.
- **Robustness & availability.** A single model is a single point of failure —
one timeout, rate-limit, or degraded response fails the whole turn. With a
quorum of proposers the turn still succeeds as long as *enough* drafts come
back, and the aggregator simply fuses what arrived.
- **Reduced variance.** Fusing several drafts smooths out per-call sampling
noise, so repeated runs of the same prompt are more stable and less
sensitive to an unlucky roll of the dice on any one model.
- **A critic pass, not just a vote.** The aggregator is a model in its own
right: it can spot a draft that's confidently wrong, prefer the
better-reasoned answer over the more verbose one, and synthesize the best
parts of several drafts — a step a single-model turn never gets.
The cost is real — an N-proposer turn spends roughly N+1 model calls and its
latency is bounded by the slowest proposer plus the aggregator. The selection
strategies below exist to spend that budget well: match ensemble size and
composition to how hard the turn actually is, rather than always paying for the
largest lineup. Lower-difficulty turns get a small, cheap lineup; harder turns
get more proposers and stronger critics.
## Selection strategies
There are three selection strategies, dispatched by
`llm_ensemble.selection_mode` in
`build_ensemble_provider_from_config`
(`src/opensquilla/provider/ensemble.py`):
| `selection_mode` | Family | Status |
|------------------|--------|--------|
| `static_openrouter_b5` | Static lineup | Default for fresh configs |
| `static_tokenrhythm_b5` | Static lineup | Supported |
| `custom_b5` | Static lineup (user-authored) | Supported |
| `router_dynamic` | Dynamic selection | Legacy |
The first two families are **static**: the lineup is fixed ahead of the turn,
either from a packaged preset or from an explicit user-authored list. The last
is **dynamic**: the lineup is scored and assembled per turn from the router's
own tier decision.
Fresh configs default to `static_openrouter_b5`. The Web UI offers only the
static families (preset + custom); `router_dynamic` is no longer offered there
and stored configs surface a one-click migration to `custom_b5`. Direct
TOML/RPC configuration keeps working for every mode.
---
# Part 1 — Static Lineups (current design)
A static lineup is fixed before the turn runs: a set of proposer models plus one
aggregator model, all known ahead of time. No per-turn scoring happens. Two
variants share this shape:
- **Presets** — `static_openrouter_b5` / `static_tokenrhythm_b5`: packaged,
hard-coded lineups on a single provider.
- **Custom** — `custom_b5`: an explicit user-authored lineup with
role-labelled candidates and a single aggregator.
Both variants belong to the same **fixed-lineup defaults family**
(`is_static_b5` in the builder) and therefore inherit the same runtime defaults
(quorum, timeouts, no shuffle, quorum grace) — see
[Shared fixed-lineup defaults](#shared-fixed-lineup-defaults).
## 1.1 Static presets
Source: `_build_static_b5_members`, `STATIC_B5_PROFILES`
(`src/opensquilla/provider/ensemble.py`).
Each preset is a `StaticB5Profile` — four fixed proposers plus one aggregator,
all bound to a single provider:
| Profile | Provider | Proposers | Aggregator |
|---------|----------|-----------|------------|
| `static_openrouter_b5` | `openrouter` | `deepseek/deepseek-v4-pro`, `z-ai/glm-5.2`, `moonshotai/kimi-k2.7-code`, `qwen/qwen3.7-max` | `z-ai/glm-5.2` |
| `static_tokenrhythm_b5` | `tokenrhythm` | `deepseek-v4-pro`, `glm-5.2`, `kimi-k2.7-code`, `qwen3.7-max` | `glm-5.2` |
The TokenRhythm profile is a mirror of the OpenRouter one: same aggregation
shape and defaults, the same four models, only the provider and the model-id
naming differ (OpenRouter-style `vendor/model` slugs vs. TokenRhythm's bare
names).
`_build_static_b5_members` simply materializes the profile: each proposer model
becomes an `EnsembleMemberConfig` labeled `proposer_1..N`, the aggregator model
becomes one labeled `aggregator`, and the selection plan records the profile
name, proposer/aggregator models, and proposer count. There is nothing to score
— the lineup is the profile.
### Credential gate
`static_b5_credential_available` decides whether the ensemble may run: it
resolves an API key for every member (all four proposers + aggregator) using the
same key-resolution order as the runtime (see
[Member provider resolution](#member-provider-resolution)). A user whose active
provider differs but whose environment carries the profile provider's env key
(e.g. `OPENROUTER_API_KEY`, `TOKENRHYTHM_API_KEY`) is treated as opted in. If any
member cannot resolve a key, the ensemble is skipped rather than posting a turn
upstream with an empty bearer token.
## 1.2 Custom lineup (`custom_b5`)
Source: `_build_custom_b5_members`, `_custom_b5_candidates`
(`src/opensquilla/provider/ensemble.py`); schema `LlmEnsembleCandidateConfig`
(`src/opensquilla/gateway/config.py`).
`custom_b5` lets an operator author the lineup explicitly via
`llm_ensemble.candidates`. Each candidate row carries:
- **`provider`** / **`model`** — required, non-empty; provider is lower-cased.
- **`role`** — advisory label, one of `""` (unassigned), `primary`, `contrast`,
`fast_check`, `critic`, or the structural `aggregator`. Unknown values coerce
to `""` instead of failing, so a hand-edited config never blocks boot.
- **`enabled`** — disabled rows are kept for read compatibility but never
counted or run.
Lineup assembly (`_build_custom_b5_members`):
1. Every enabled row whose role is **not** `aggregator` runs as a proposer,
labeled by its role (or `proposer_N` when unassigned).
2. The single row with role `aggregator` fuses the drafts. Proposer rows dedupe
on `(provider, model)`; the aggregator row may legitimately reuse a
proposer's model (a model both drafts and fuses).
3. **Fallback:** if no `aggregator` row exists, the aggregator falls back to the
currently routed model — the same model the user would have gotten without
the ensemble — so a proposer-only config still runs instead of erroring at
turn time. The plan records `aggregator.source` as `candidate_role` or
`inherited_model` accordingly.
### Lineup bounds & validation
Enforced by `LlmEnsembleConfig._validate_custom_b5_lineup`
(`src/opensquilla/gateway/config.py`), checked **only** when
`selection_mode == "custom_b5"` (presets carry fixed lineups; `router_dynamic`
selects per turn):
- At most **one** enabled candidate may carry role `aggregator`.
- Enabled proposer count must stay within
`[CUSTOM_B5_MIN_PROPOSERS=2, CUSTOM_B5_MAX_PROPOSERS=6]`.
- Total per-turn calls are capped at `CUSTOM_B5_MAX_TOTAL_CALLS=8`
(proposers + aggregator).
### Readiness gate
`custom_b5_lineup_ready` returns `(ready, reason)` before wrapping the turn. It
fails closed with a machine-readable reason when the lineup is not runnable:
`no_proposers`, `unknown_provider:<p>`, or `missing_credential:<p>` (a member
whose provider requires a key but resolves none). This mirrors the static-preset
gate — a member with an empty bearer token would post the conversation upstream
unauthenticated, so the wrap is skipped.
## 1.3 Shared fixed-lineup defaults
Both static families set `is_static_b5 = True` in
`build_ensemble_provider_from_config`, which swaps the legacy per-turn defaults
for the fixed-lineup family defaults. The swap is **only** applied when the
configured value still equals the legacy default (`_static_default_if_legacy`),
so any operator override is preserved:
| Parameter | Legacy (`router_dynamic`) | Fixed-lineup default |
|-----------|---------------------------|----------------------|
| `min_successful_proposers` | 1 | 3 (presets) / `N-1` (custom, "all but one") |
| `proposer_timeout_seconds` | 3600 | 300 |
| `aggregator_timeout_seconds` | 3600 | 480 |
| `shuffle_candidates` | `True` | `False` |
| `quorum_grace_seconds` | 0 | 30 |
`min_successful_proposers` is additionally clamped down to the actual proposer
count. Both the configured and effective values (min-success, timeouts, shuffle)
are recorded in the selection plan for debugging.
## 1.4 Member provider resolution
Every member (static or custom) resolves its concrete `ProviderConfig` through
`_member_provider_config`, which layers member intent over the inherited/routed
provider config:
- **API key** — a member-level `api_key_env` env var if set; else the inherited
key when the member's provider matches the active provider; else the provider
registry's env key (e.g. `OPENROUTER_API_KEY`).
- **`base_url`** — member override, else the inherited base URL (same provider)
or the provider spec's default base URL.
- **`proxy` / `org_id` / `provider_routing`** — inherited only when the member
shares the active provider; otherwise reset.
This is what lets a static/custom lineup run against a provider the user isn't
actively routing to, as long as that provider's credential is present in the
environment.
## 1.5 Configuration surface
```toml
[llm_ensemble]
enabled = true
selection_mode = "static_openrouter_b5" # or static_tokenrhythm_b5 / custom_b5
```
Custom lineup:
```toml
[llm_ensemble]
enabled = true
selection_mode = "custom_b5"
[[llm_ensemble.candidates]]
provider = "openrouter"
model = "deepseek/deepseek-v4-pro"
role = "primary"
[[llm_ensemble.candidates]]
provider = "openrouter"
model = "z-ai/glm-5.2"
role = "contrast"
[[llm_ensemble.candidates]]
provider = "openrouter"
model = "z-ai/glm-5.2"
role = "aggregator"
```
Static presets expose no lineup tuning — the models are fixed in code. Custom
lineups are tuned entirely through the `candidates` list (subject to the bounds
above). Both share the fixed-lineup runtime defaults, which an operator may
still override explicitly (`min_successful_proposers`,
`proposer_timeout_seconds`, `aggregator_timeout_seconds`, `shuffle_candidates`).
---
# Part 2 — `router_dynamic` Selection (legacy)
> **Status: legacy.** `router_dynamic` remains fully supported for existing
> configs but is no longer offered in the Web UI. Stored `router_dynamic`
> configs surface a one-click migration to `custom_b5`. Direct TOML/RPC
> configuration keeps working as described below.
`router_dynamic` is the dynamic model-selection strategy: instead of a fixed
lineup, it picks proposers and the aggregator **per turn**, driven by
SquillaRouter's tier decision for that turn. Enable it with
`llm_ensemble.selection_mode = "router_dynamic"`.
Source: `src/opensquilla/provider/ensemble.py`
(`_candidate_pool`, `_score_dynamic_candidate`, `_select_dynamic_candidate`,
`_build_router_dynamic_members`).
## 2.1 Why dynamic selection
A fixed proposer/aggregator list can't adapt to the model actually chosen for a
turn, and forces operators to hand-tune which models pair well together at each
router tier. `router_dynamic` instead:
- reuses the model SquillaRouter already picked for the turn as the **anchor**
proposer, so the ensemble never contradicts the router's own tier decision;
- fills the remaining proposer slots and the aggregator slot by scoring a pool
of candidate models against a per-tier "slot template";
- penalizes re-selecting a model that's already in the ensemble, so proposers
stay diverse instead of collapsing onto a few high-quality models.
## 2.2 Inputs
`_build_router_dynamic_members` takes three things:
1. **`inherited_provider_config`** — the provider/model SquillaRouter already
resolved for this turn (becomes the anchor).
2. **`turn_metadata`** — carries `routed_tier` (`c0``c3`), `routing_confidence`
(0.01.0), and `routing_extra` (`final_tier`/`base_tier` fallbacks used if
`routed_tier` is missing). Defaults to tier `c1` if nothing usable is found.
3. **`config`** — `llm_ensemble.model_options` and `squilla_router.tiers`,
used to build the candidate pool.
## 2.3 Candidate pool
`_candidate_pool` assembles a deduplicated list of `(provider, model)`
candidates, in this order:
1. **Router anchor** — the inherited provider/model (`source="router_anchor"`).
This is always `pool[0]` and always becomes the first proposer.
2. **`llm_ensemble.model_options`** — the operator-configured candidate list
(`source="model_options"`). If a model string contains `/` it's assumed to
be an OpenRouter-style id and routed via `openrouter`; otherwise it inherits
the anchor's provider.
3. **`squilla_router.tiers[*].model`** — every model configured for a
SquillaRouter tier (`source="router_tier:<tier>"`), so tier-specific models
the operator has wired into the router are eligible even if not listed in
`model_options`.
Each candidate is annotated with priors from `_DYNAMIC_MODEL_CATALOG` — a
built-in table of ~14 known models with `tier`, `quality` (01), `cost_latency`
(01, higher = cheaper/faster), `family`, `vendor`, and `architecture`. Models
not in the catalog fall back to tier-average priors (`_tier_quality_prior`,
`_tier_cost_latency_prior`) derived from the model string or tier hint.
## 2.4 Slot templates
Each router tier maps to an ordered list of proposer "slots"
(`_DYNAMIC_TIER_SLOTS`):
| Tier | Slots |
|------|-------|
| `c0` | `anchor`, `cheap_contrast` |
| `c1` | `anchor`, `balanced_contrast` |
| `c2` | `anchor`, `adjacent_tier_check`, `orthogonal_family` |
| `c3` | `anchor`, `strong_critic`, `orthogonal_family`, `fast_sanity` |
Lower tiers (cheap/simple turns) get a small, cost-biased ensemble; higher
tiers (hard turns) get more proposers with slots biased toward quality and
contrast. The `anchor` slot is always filled by the router's own model and is
never scored — it's taken as-is.
Each tier also maps to an aggregator slot (`_DYNAMIC_AGGREGATOR_SLOT`):
`c0→aggregator_fast`, `c1→aggregator_balanced`, `c2`/`c3→aggregator_strong`.
## 2.5 Scoring a candidate for a slot
For every non-anchor slot, every pool candidate is scored and the best one is
selected (`_select_dynamic_candidate``_score_dynamic_candidate`):
```
score = weights.quality * quality_prior
+ weights.affinity * router_affinity_score
+ weights.diversity * diversity_score
+ weights.cost * cost_latency_prior
+ weights.role * role_match_score(slot)
- duplicate_penalty
```
Each slot has its own weight vector (`_DYNAMIC_SLOT_WEIGHTS`), e.g.
`cheap_contrast` weights `cost` and `role` heavily and `affinity` lightly,
while `strong_critic` weights `quality` and `role` heavily and `cost` almost
not at all.
### Score components
- **`router_affinity_score`** — how close the candidate's tier prior is to the
turn's `routed_tier`, scaled by `routing_confidence`. Low router confidence
relaxes tier matching instead of forcing a brittle lock, since a
low-confidence route is itself uncertain about the right tier.
- **`diversity_score`** — rewards a candidate whose family/vendor/provider/
tier/architecture aren't already represented among the proposers picked so
far in this turn (checked incrementally, slot by slot).
- **`role_match_score`** — slot-specific logic (see below), combining tier
targeting, contrast against the anchor, quality, or cost depending on what
that slot is supposed to contribute.
- **`duplicate_penalty`** — `_DYNAMIC_SELECTED_PENALTY[slot] * times_already_selected`.
Selecting the same `(provider, model)` again is allowed but costs
increasingly more as the same model keeps winning slots.
### Role match by slot
`_role_match_score` differs by slot — this is where each slot's intent is
actually encoded:
- **`cheap_contrast`** — favors tier `c0`/`c1`, contrast with the anchor, and
cost/latency. A cheap "second opinion."
- **`balanced_contrast`** — favors tier `c1`/`c2`, contrast, and quality.
- **`adjacent_tier_check`** — favors a tier one step above/below the routed
tier (`adjacent_distance == 1`), plus quality. Checks whether a
slightly-different-strength model agrees.
- **`orthogonal_family`** — favors contrast and diversity above all — a
model from a different vendor/family/architecture than the anchor.
- **`strong_critic`** — favors tier `c3` and quality heavily — the strongest
available model as a critic, used only at higher tiers.
- **`fast_sanity`** — favors tier `c0`/`c1` and cost/latency — a fast,
cheap sanity check, used only at `c3`.
- **`aggregator_fast` / `aggregator_balanced` / `aggregator_strong`** — each
balances tier targeting and quality differently; `aggregator_strong`
weights quality highest and cost lowest, since the aggregator's output is
the final response.
### Tie-breaking
Candidates are sorted by `(score, quality_prior, cost_latency_prior,
-pool_index)` descending, so ties fall back to higher quality, then higher
cost/latency score, then earlier pool position (closer to the anchor/operator-
configured list) wins.
## 2.6 Selection order
`_build_router_dynamic_members` runs slots in the tier's template order:
1. `anchor` — taken directly, no scoring.
2. Remaining proposer slots, in order — each selection is added to `selected`
and `selected_counts` before the next slot is scored, so later slots see
updated diversity/duplicate state.
3. The aggregator slot, scored last, against the same accumulated `selected`
state as the proposers (so it also gets a duplicate penalty if it repeats
a proposer's model).
## 2.7 Output
The function returns `(profile_name, proposers, aggregator, selection_plan)`:
- `profile_name``"router_dynamic/<tier>"`, e.g. `"router_dynamic/c2"`.
- `proposers` — one `EnsembleMemberConfig` per slot, labeled by slot name
(`anchor`, `cheap_contrast`, ...).
- `aggregator` — one `EnsembleMemberConfig`, labeled `aggregator`.
- `selection_plan` — a full trace for observability, including the resolved
tier/confidence, the anchor, the slot template, per-slot score breakdowns
(`_score_trace`, including the top-3 scored candidates per slot for
debugging near-misses), the aggregator's score breakdown, the full
candidate pool, and `duplicate_policy: "selected_penalty"`.
`build_ensemble_provider_from_config` (the public entrypoint) additionally
clamps `min_successful_proposers` down to `len(proposers)` if the configured
value exceeds how many proposer slots the tier's template actually produced
— e.g. configuring `min_successful_proposers=4` at tier `c0` (2 slots) yields
an effective minimum of 2. Both the configured and effective values are
recorded in `selection_plan` for debugging.
## 2.8 Configuration surface
```toml
[llm_ensemble]
enabled = true
selection_mode = "router_dynamic"
```
What operators can tune:
- `llm_ensemble.model_options` — extends the candidate pool beyond the router
anchor and configured router tiers.
- `llm_ensemble.min_successful_proposers` — desired minimum successful
proposers (clamped per-turn as described above).
- `squilla_router.tiers[*].model` — indirectly expands the candidate pool and
determines which model becomes the anchor for a given tier.
There is no operator control over slot templates, weights, or the model
catalog priors — those are fixed in code. Unlike the static families,
`router_dynamic` keeps the legacy runtime defaults (timeouts 3600s,
`shuffle_candidates=True`, `min_successful_proposers=1`).
@@ -0,0 +1,395 @@
# Attachment Drag-and-Drop Upload Spec
Date: 2026-06-29
Status: Draft
## Problem
OpenSquilla should let users attach files by dragging them into the chat surface
in both the browser Web UI and the Electron desktop client. The behavior must be
consistent across surfaces and must use the existing gateway attachment
ingestion path rather than adding a parallel desktop-only file pipeline.
The current code already contains most of the upload path:
- `opensquilla-webui/src/views/ChatView.vue` listens for drag/drop on the chat
thread and passes dropped files to `addAttachment`.
- `opensquilla-webui/src/composables/chat/useChatAttachments.ts` validates file
type and size, inlines small files, and stages large files through
`/api/v1/files/upload`.
- `opensquilla-webui/src/composables/chat/useChatSend.ts` sends staged files as
`{ type, file_uuid, mime, name }`.
- `src/opensquilla/gateway/uploads.py` exposes the multipart upload route and
stores staged bytes behind an opaque `file_uuid`.
- `src/opensquilla/gateway/attachment_ingest.py` resolves `file_uuid` entries
into transcript material references before a turn runs.
- `desktop/electron/src/main.ts` creates a sandboxed, context-isolated browser
window; `desktop/electron/src/preload.cts` exposes only explicit desktop APIs.
The missing product-quality layer is a complete, reviewed drag-upload UX and
test contract that covers both browser and desktop surfaces, including auth,
error states, retry behavior, and cross-platform desktop validation.
## Goals
- Support dragging files from the OS/browser file picker into the Web UI chat
surface.
- Support the same drag behavior in the Electron desktop client without a
separate upload implementation.
- Preserve the existing attachment policy: max count, per-category size caps,
total size cap, MIME sniffing, and staged upload TTL. Any file type is
admitted; the MIME set only routes representation (rendered families are
extracted or inlined, everything else stages as an opaque workspace file).
- Make upload progress and failure states visible in the composer.
- Prevent sending while any attachment is still reading or uploading.
- Ensure token-authenticated gateways can upload files by using the same bearer
token source as the WebSocket/RPC client.
- Keep raw local file paths out of renderer code and out of chat payloads.
- Persist only stable transcript material references after `chat.send` accepts
the turn; do not persist `file_uuid` in transcripts.
## Non-Goals
- Do not implement folder drag-and-drop.
- Do not upload directory trees or recursively enumerate local paths.
- Do not expose arbitrary local filesystem reads through Electron preload.
- Do not make Electron bypass the gateway upload endpoint.
- Do not add resumable/chunked uploads in this iteration.
- Do not add per-type client-side gating: admission is any-type (opaque
staging), and rejections happen only on size/count policy, mirroring the
gateway's category router in `contracts/attachments.py`.
- Do not support remote URL drag/drop as file upload unless the browser supplies
a real `File` object.
## Existing Surfaces
### Web UI
- `ChatView.vue` owns high-level chat surface events, including drag/drop and
paste.
- `ChatComposer.vue` renders pending attachment chips and the file input.
- `useChatAttachments.ts` owns attachment state, MIME resolution, inline reads,
staged uploads, and local validation.
- `useChatSend.ts` serializes pending attachments into the `chat.send` RPC
payload.
### Gateway
- `contracts/attachments.py` defines allowed media types and size limits.
- `uploads.py` handles multipart staging and returns `file_uuid`.
- `attachment_ingest.py` validates inline and staged attachments, writes
transcript material, and returns consumed staged UUIDs.
- `rpc_sessions.py` evicts consumed `file_uuid` values only after the turn has
been accepted into the runtime.
### Desktop
- The Electron renderer runs the same Vue Web UI as the browser.
- The Electron window is sandboxed and context-isolated.
- The preload API currently exposes gateway status, settings, onboarding, and
artifact open helpers; it does not expose raw file reads.
## Recommended Design
Use one shared Web UI upload path for browser and Electron:
```text
User drops files
-> ChatView drop handler
-> useChatAttachments.addAttachments(files)
-> inline small files OR POST large files to /api/v1/files/upload
-> ChatComposer renders pending chips
-> useChatSend serializes attachments
-> chat.send RPC
-> gateway attachment_ingest resolves file_uuid
-> turn runtime receives stable attachment refs
```
Electron should not get a special upload bridge in the first iteration. When a
file is dragged from the OS into the Electron browser window, Chromium exposes
it to renderer code as a `File`. That is the same object shape the browser path
uses, so the renderer can call the same composable.
Add a desktop-specific bridge only if manual validation proves a platform cannot
produce usable `DataTransfer.files`, or if a later feature explicitly needs
native behavior such as folder selection, revealing local file paths, or
watching local files for changes.
## User Experience
### Drop Zone
The primary drop zone is the chat thread/composer area.
Expected behavior:
- `dragenter` / `dragover` with at least one file item shows a visible drop
affordance.
- `dragleave` uses a drag-depth counter or equivalent containment check so the
affordance does not flicker when moving across child elements.
- `drop` extracts only `File` objects and ignores non-file drag data.
- Dropping files focuses the composer and appends attachments to the pending
list.
- Unsupported items produce a toast and do not block valid files in the same
drop.
### Attachment Chips
Each pending attachment chip should show:
- name;
- MIME or concise type label;
- size;
- state: reading, uploading, ready, failed;
- thumbnail for image inline attachments when available;
- remove button;
- retry button for staged upload failures.
Sending is disabled while any attachment is `reading` or `uploading`.
### Empty Message Behavior
If the user sends with attachments and no text, the existing fallback message
`Describe these attachments` remains acceptable.
The visible bubble should still show the user's display text when present and
attachment chips/previews when attachments exist.
## Attachment State Model
Use an explicit state machine in `useChatAttachments.ts`.
Recommended internal states:
| State | Meaning | Sendable |
| --- | --- | --- |
| `inline_pending` | FileReader is reading a small file. | No |
| `inline` | Base64 data is ready in the pending payload. | Yes |
| `uploading` | Multipart upload is in progress. | No |
| `staged` | Gateway returned a `file_uuid`. | Yes |
| `failed` | Read or upload failed and can be removed or retried. | No |
The public type may keep the existing names, but code paths should treat them as
states rather than ad-hoc variants.
`addAttachment(file)` should be implemented in terms of
`addAttachments(files: File[])` so file picker, paste, and drag/drop share batch
validation behavior.
## Data Contracts
### Inline Attachment Payload
Small files are sent through `chat.send` as:
```json
{
"type": "image/png",
"mime": "image/png",
"name": "screenshot.png",
"data": "<base64>"
}
```
### Staged Upload Request
Large files are uploaded first:
```http
POST /api/v1/files/upload
Content-Type: multipart/form-data
Authorization: Bearer <token>
```
Multipart fields:
- `file`: the file bytes and filename;
- `mime`: the client-resolved MIME, used only as a claim; gateway revalidates.
Expected success response:
```json
{
"file_uuid": "u-...",
"filename": "report.pdf",
"mime": "application/pdf",
"size": 12345
}
```
### Staged `chat.send` Payload
After staging, `chat.send` sends:
```json
{
"type": "application/pdf",
"mime": "application/pdf",
"name": "report.pdf",
"file_uuid": "u-..."
}
```
The gateway resolves this into a stable attachment ref and must not persist
`file_uuid` into transcript envelopes.
## Auth Requirements
The multipart upload route intentionally requires header-based auth in token
mode. Query-string token auth must remain rejected for uploads.
Vue upload requests must therefore include the same token source used by the
WebSocket/RPC connection:
- read `sessionStorage.getItem("opensquilla.wsToken")`;
- when present, set `Authorization: Bearer <token>`;
- keep `credentials: "same-origin"` for same-origin cookies and browser policy;
- never place the token in the upload URL.
This is important because the current Vue staged upload path uses
`credentials: "same-origin"` but does not include an authorization header. The
legacy static chat upload path already includes the bearer token and should be
used as the behavior reference.
## Security and Safety Rules
- Frontend validation is advisory UX only; gateway validation remains
authoritative.
- The renderer must never send local filesystem paths in chat payloads.
- Electron preload must not expose an arbitrary `readFile(path)` API for this
feature.
- `file_uuid` is a short-lived upload-store identifier, not a durable reference.
- Staged upload bytes are evicted only after the turn is accepted.
- Failed `chat.send` after successful staging must keep the staged file retryable
until TTL expiry.
- MIME sniffing mismatches are handled by gateway policy, not by trusting the
browser-provided `File.type`.
- Directory entries and zero-byte files should be rejected with clear UX.
## Implementation Plan
### Frontend
1. Add `addAttachments(files: File[])` in `useChatAttachments.ts`.
2. Route file picker, paste, and drop through `addAttachments`.
3. Add drag-depth or containment-safe drop-zone state in `ChatView.vue`.
4. Show a drop affordance only when the drag payload contains files.
5. Add upload auth headers to staged upload requests.
6. Add retry handling for staged upload failures.
7. Keep `ChatComposer.vue` presentational: props down, events up.
8. Ensure `useChatSend.ts` does not clear failed attachments as if they were
successfully queued.
### Gateway
1. Keep `/api/v1/files/upload` as the only staged upload endpoint.
2. Keep the upload route header-token requirement unchanged.
3. Confirm `UploadStore` and `attachment_ingest` reject unsupported MIME, over
size, unknown UUID, restart-lost UUID, and total size overflow.
4. Add targeted tests only where the new frontend contract exposes gaps.
### Desktop
1. Validate drag/drop in packaged or dev Electron on macOS, Windows, and Linux
where available.
2. Keep Electron preload unchanged unless validation proves native bridging is
required.
3. If a bridge becomes required, expose only a narrow capability such as
`stageDroppedFile(handle)` and keep all byte validation in the gateway.
## Test Plan
### Frontend Unit Tests
- `resolveAttachmentMime()` prefers allowed browser MIME and falls back to
extension.
- Unknown UTF-8 text degrades to `text/plain`.
- Unknown binary files are rejected.
- Oversize files are rejected by per-MIME cap.
- `addAttachments()` handles mixed valid and invalid files without dropping the
valid ones.
- Inline files transition from `inline_pending` to `inline`.
- Large stageable files transition from `uploading` to `staged`.
- Failed staged upload leaves a failed/removable state.
- Upload requests include `Authorization: Bearer <token>` when the token exists.
- Upload requests do not put the token in the URL.
### Vue Component Tests
- Dragging files over the chat surface shows the drop affordance.
- Dragging non-file data does not show the drop affordance.
- Dropping files calls the attachment composable once with all dropped files.
- Sending is disabled while any attachment is reading or uploading.
- Removing an attachment updates the pending list without mutating child props.
### Gateway Tests
- Multipart upload rejects missing auth header in token mode.
- Multipart upload accepts bearer token in token mode.
- Multipart upload rejects query-token-only auth.
- Staged `file_uuid` resolution returns an attachment ref with no `file_uuid` or
inline `data`.
- Restart-lost UUID produces the re-upload error path.
- Successful turn acceptance evicts consumed UUIDs.
- Failed turn acceptance does not evict consumed UUIDs.
### Browser E2E
- Drop one small image into Web UI, send, and assert `chat.send` carries inline
base64 attachment data.
- Drop one large PDF into Web UI, wait for staged chip, send, and assert
`chat.send` carries `file_uuid`.
- Drop a valid file and an invalid file together; valid file remains pending and
invalid file produces a toast.
- Verify mobile and desktop layouts do not overflow with long filenames or wide
image thumbnails.
### Desktop Manual Smoke
Run on Electron dev and packaged builds:
1. Start the desktop client.
2. Drag a small PNG from the OS file manager into the chat thread.
3. Confirm the composer shows a thumbnail chip.
4. Send and confirm the user bubble renders the attachment.
5. Drag a PDF larger than the inline threshold.
6. Confirm upload progress changes to staged/ready.
7. Send and confirm the gateway accepts the turn.
8. Repeat with token auth enabled.
9. Confirm no local file path appears in the chat payload, transcript, or logs.
## Acceptance Criteria
- Browser Web UI supports drag-and-drop upload for every MIME currently allowed
by `contracts/attachments.py`.
- Electron desktop supports the same drag-and-drop behavior without a separate
upload code path.
- Token-authenticated uploads succeed because the frontend sends bearer auth
headers.
- Query-token-only multipart upload remains rejected.
- Users cannot send while attachments are still reading or uploading.
- Failed uploads are visible and removable or retryable.
- Staged attachments are sent as `file_uuid` and are materialized into stable
transcript attachment refs before runtime execution.
- `file_uuid` never appears in persisted transcript envelopes.
- Successful turn acceptance evicts consumed staged uploads.
- Frontend and backend tests cover valid, invalid, oversize, auth, retry, and
layout cases.
## Rollout
- Ship behind the normal chat composer behavior with no user-facing setting.
- Keep existing file input and paste upload behavior working during rollout.
- Validate Web UI first, then Electron dev, then packaged desktop.
- Add troubleshooting guidance only if desktop platform differences require
user-visible explanation.
## Open Questions
- Should failed staged upload chips offer retry, or should failure remove the
chip and rely on toast only?
- Should duplicate files in the same drop be deduplicated by
`name + size + lastModified`, or should duplicates be allowed?
- Should the drop affordance cover only the chat thread or the full chat view?
- Should future folder drag support be handled through a separate desktop-only
import flow rather than this attachment pipeline?
@@ -0,0 +1,198 @@
# Bocha Search Provider Design
Date: 2026-06-25
## Goal
Add Bocha as a first-class OpenSquilla search provider using the existing search
runtime, provider catalog, onboarding, settings, diagnostics, and test surfaces.
The user experience should be: configure a Bocha key, then normal `web_search`
and `web_discover` flows can use it automatically when it is the best available
provider.
This design intentionally avoids a visible China-region strategy or profile. Bocha
is a normal provider with capabilities, credentials, ordering, and diagnostics.
## Non-Goals
- Do not add a visible `cn`, `domestic`, or region routing profile.
- Do not add Zhipu, a separate reader abstraction, or multi-provider result fusion.
- Do not change `search_provider` into a hard routing promise. It remains the
credential anchor for `search_api_key` and `search_api_key_env`.
- Do not add user-facing provider priority controls in the MVP.
- Do not broaden fallback to empty-result or low-quality-result retries by default.
## Existing Runtime Boundaries
OpenSquilla already has the right extension points:
- Provider specs and provider factories live in `opensquilla.search.registry`.
- Runtime availability and provider ordering live in `SearchRuntimeConfig` and
`ResolvedSearchRuntime`.
- `web_search` uses the canonical search pipeline.
- `web_discover` has a lighter provider path and must be updated separately.
- Onboarding and settings consume the provider catalog payload.
- `search_fallback_policy` currently supports `off` and `network`.
The implementation should use those surfaces instead of introducing a second
search router.
## Provider Behavior
Add `BochaSearchProvider` under `src/opensquilla/search/providers/bocha.py`.
Expected API shape:
- Endpoint: `https://api.bochaai.com/v1/web-search`
- Authentication: `Authorization: Bearer <api key>`
- Default environment variable: `BOCHA_SEARCH_API_KEY`
- Request options:
- query text
- max result count
- freshness mapping when `SearchOptions.recency` is set
- summary enabled when supported
The provider should normalize Bocha results into `SearchResult` fields:
- title from `name`
- url from `url`
- snippet from `snippet`
- provider content from `summary` when present
- published timestamp from `datePublished`
- source/site metadata from `siteName`, `displayUrl`, or equivalent fields
Bocha summaries should count as useful provider content so the canonical pipeline
does not fetch pages unnecessarily when Bocha already returned enough source
text.
## Provider Spec
Register Bocha with a `SearchProviderSpec`:
```python
SearchProviderSpec(
provider_id="bocha",
requires_api_key=True,
env_key="BOCHA_SEARCH_API_KEY",
capabilities=frozenset({"web", "freshness", "content"}),
)
```
Do not claim `domain_filter` unless the Bocha API supports an equivalent feature
and tests cover it.
## Runtime Ordering
Bocha should participate in the existing automatic ordering. Suggested MVP
ordering:
```python
_GENERAL_TIE_BREAKER = ("bocha", "tavily", "brave", "exa", "duckduckgo")
_TECHNICAL_TIE_BREAKER = ("exa", "bocha", "brave", "tavily", "duckduckgo")
_FRESHNESS_TIE_BREAKER = ("bocha", "tavily", "brave", "exa")
```
Rationale:
- General and freshness searches should prefer Bocha when it is configured,
because it is the targeted improvement for reliable China-accessible search.
- Technical searches should keep Exa first because its existing role is stronger
for semantic and content-oriented research.
- No-key and partial-key users are protected by the existing availability filter:
unavailable keyed providers are skipped before ordering is returned.
## Fallback Policy
Keep fallback semantics narrow:
- `off`: surface the original provider error.
- `network`: fallback only after network, timeout, rate-limit, retryable, or HTTP
provider errors.
Do not fallback on:
- empty results
- low-quality results
- parse errors, unless those are explicitly classified as retryable provider
failures later
This preserves cost, latency, and predictability for users who configured
multiple paid providers.
## Configuration And Setup
Supported key resolution should remain layered:
1. active provider inline configured key
2. active provider configured env var
3. provider spec default env var
Bocha should support all existing search setup paths:
- CLI configuration
- onboarding setup engine
- gateway setup payload
- desktop settings provider catalog
- web UI setup provider catalog
The MVP should update fallback/static provider lists where the UI has offline
defaults, but the canonical source of truth remains the backend provider catalog.
## Diagnostics
Search runtime status should show Bocha like other providers:
- available/unavailable
- credential source
- credential configured boolean
- skipped reason
- capabilities
Diagnostics must not expose the raw API key.
A live provider probe can be added later, but it is not required for the MVP if
existing status remains buildability/configuration based.
## Testing
Required tests:
- Provider response normalization from a representative Bocha payload.
- Missing-key behavior and credential source resolution for Bocha.
- Runtime ordering for:
- no keyed providers
- only Bocha configured
- Bocha plus existing keyed providers
- technical mode
- freshness/news mode
- `web_search` accepts `provider="bocha"` and `provider="auto"` can select Bocha.
- `web_discover` accepts and can build Bocha when configured.
- Onboarding catalog includes Bocha with `BOCHA_SEARCH_API_KEY`.
- Documentation and frontend catalog contract tests include Bocha.
Optional live tests:
- A manually gated Bocha smoke test using `BOCHA_SEARCH_API_KEY`.
- The live test must be opt-in and must not run in normal CI.
## Documentation
Update:
- `docs/search.md`
- `docs/configuration.md`
- relevant onboarding or setup docs if provider lists are repeated there
Document Bocha as a normal runtime-supported provider. Avoid describing it as a
region strategy.
## Acceptance Criteria
- A user with only `BOCHA_SEARCH_API_KEY` configured can run normal automatic web
search successfully.
- Existing users with only Brave, Tavily, Exa, or DuckDuckGo keep the same
behavior except for Bocha appearing in provider catalogs when available.
- All current fallback semantics remain unchanged.
- Bocha appears in CLI/onboarding/settings provider lists.
- Tests cover provider mapping, ordering, configuration, and documentation
contracts.
+114
View File
@@ -0,0 +1,114 @@
# Compaction and Cache Continuity
Long agent sessions need context management. OpenSquilla uses compaction,
bounded history, tool-result projection, and cache-aware prompt placement to
keep long-running tasks moving.
Compaction is separate from memory. Memory is durable recall. Compaction is an
active-session continuity tool.
## What Compaction Does
When session history approaches the configured context budget, OpenSquilla can
compact older transcript entries into a durable summary and keep the recent
tail active.
The goal is to preserve:
- user goal;
- current status;
- open steps;
- changed files and artifacts;
- known failures;
- important tool results;
- next action.
Compaction is not a guarantee that every old word remains model-visible. Export
sessions or save files when exact historical text matters.
## User-Visible Lifecycle
Depending on surface and trigger, users may see:
- compaction started;
- compaction skipped;
- compaction completed;
- compaction failed.
When no compaction is needed, OpenSquilla uses this stable message:
```text
Already within context budget; no compact was applied
```
That message is a no-op, not a failure.
## When to Compact Manually
Manual compaction is useful when:
- the session is long and you are about to start a new phase;
- a previous tool-heavy turn produced a lot of context;
- the UI indicates context pressure;
- you want the next answer to focus on the current state rather than the whole
transcript.
Avoid compact loops when the runtime says the session is already within budget.
## Passive Compaction
Passive compaction can happen when OpenSquilla detects context pressure before
or during agent work. The exact trigger depends on model context limits,
configured budgets, current history, and tool output size.
If passive compaction fails, the safest user response is usually:
1. let the current turn finish or fail cleanly;
2. export the session if exact history matters;
3. retry with a narrower request or manually save key artifacts;
4. enable diagnostics if the failure repeats.
## Prompt Cache Continuity
Prompt caching works best when stable prompt parts stay stable. OpenSquilla
tries to keep:
- stable system prompt and tool definitions early;
- current request, volatile runtime context, retrieved history, and tool results
near the tail;
- model/provider switches visible through diagnostics when they may affect
cache continuity.
Cache continuity is best-effort. Routing, tools, attachments, provider changes,
or a large new context can reduce cache reuse.
## Related Commands and Surfaces
Manual compaction is primarily surfaced in chat and Web UI flows. For
inspection and recovery:
```sh
opensquilla sessions show <session-key>
opensquilla sessions export <session-key>
opensquilla diagnostics on
```
For memory repair surfaces related to degraded compaction records:
```sh
opensquilla memory repair list
opensquilla memory repair show --summary-id <id>
opensquilla memory raw-fallbacks list
```
## Best Practices
- Keep important final artifacts in files or published artifacts.
- Use memory for durable preferences and reusable project facts.
- Use session export for exact old transcripts.
- Use manual compaction before a new phase in a very long session.
- Do not repeatedly compact a short or already-within-budget session.
---
[Docs index](../README.md) · [Product guide](../../README.product.md) · [Improve this page](../contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
@@ -0,0 +1,207 @@
# Desktop DMG Startup Window Recovery Spec
## Background
Users reported two macOS DMG installation issues:
1. After installing the latest DMG, the first launch shows no window.
2. In an earlier DMG, closing the client window with the red close button leaves the OpenSquilla app running in the Dock, but clicking the Dock icon does not reopen any window.
This spec covers the desktop startup and packaging fix. It is separate from the gateway/yoyo migration lock recovery spec, although both can surface during first-run gateway startup.
## Evidence
Local packaged logs showed the bundled gateway crashing during first launch:
```text
AttributeError: '_AsyncConnection' object has no attribute 'create_function'
```
The crash path is:
```text
opensquilla/session/storage.py -> SessionStorage.connect()
```
The packaged runtime under the built app was missing `create_function` in `opensquilla.compat.aiosqlite._AsyncConnection`, while current source has the compatibility method.
The packaged Electron app also still had this startup order:
```ts
const gateway = await startGateway()
const window = await createMainWindow()
```
That means any gateway crash or long wait can prevent the first visible desktop window from being created.
For the Dock behavior, macOS intentionally keeps the application process alive after all windows are closed. The existing behavior is acceptable only if `activate` reliably recreates or focuses the main window and reuses the already-running gateway instead of trying to perform a full duplicate startup.
## Goals
- Show a desktop window immediately on launch and Dock activation, before gateway startup can block or fail.
- Surface gateway startup failure inside the desktop UI instead of leaving the user with no visible window.
- Ensure the packaged gateway runtime contains the aiosqlite compatibility API needed by session storage.
- Reuse an already-owned, healthy gateway on Dock activation instead of spawning a duplicate process.
- Prevent duplicate gateway startup while a startup attempt is already in progress.
- Make the release validation catch stale packaged runtime contents before distributing a DMG.
## Non-Goals
- Do not change macOS close-button semantics by default. Closing the last window may keep the app running unless product decides to switch to quit-on-close.
- Do not disable yoyo migration locking.
- Do not change gateway state directory, auth token, or persistence layout.
- Do not treat a previously built DMG as fixed unless it is rebuilt from the fixed source and revalidated.
- Do not treat unsigned local validation as equivalent to a distributable release validation.
## Root Causes
### 1. Packaged Gateway Runtime Was Stale
The built app included a runtime copy of `opensquilla.compat.aiosqlite` without `_AsyncConnection.create_function`. Source had moved forward, but the packaged runtime did not contain that fix.
When session storage calls `create_function`, the packaged gateway crashes before becoming healthy.
### 2. Electron Created the Window After Gateway Startup
The app waited for `startGateway()` before calling `createMainWindow()`. If gateway startup crashes, hangs, or waits on a lock, the desktop app can remain running without any visible window.
### 3. macOS Activation Path Did Not Reliably Resume UI
On macOS, `window-all-closed` does not quit the app. After the red close button, the Dock dot remains because the app process and gateway may still be alive.
Clicking the Dock icon must focus an existing window or create a new one and attach it to the existing gateway state. If activation re-enters a full startup path, it can wait unnecessarily, hit duplicate startup guards, or fail silently.
## Design
### Electron Startup
`bootDesktopApp()` must create the main window before gateway startup:
```ts
const window = await createMainWindow()
const gateway = await startGateway()
```
The initial window should display a boot/loading state. If gateway startup succeeds, it loads the gateway URL. If gateway startup fails, it renders the existing startup error state with log details and retry actions.
### Idempotent Gateway Startup
`startGateway()` should become explicitly idempotent:
- If an owned gateway process is already healthy, return the existing `gatewayState`.
- If startup is already in progress, do not spawn another gateway. Focus or keep the boot window visible.
- If the owned process exited, clear stale owned state before starting a new process.
- If a gateway URL is present, health-check it before deciding to reuse it.
This prevents Dock activation, second-instance activation, and retry actions from racing into duplicate gateway processes.
### Dock Activation
The `activate` handler should call a single helper that:
1. Focuses an existing non-destroyed main window, or creates a new boot window.
2. If `gatewayState.status === "ready"` and the URL passes health check, loads that URL.
3. If startup is in progress, keeps the boot window visible.
4. Otherwise starts gateway once and then loads or shows an error state.
The same helper should be used by `second-instance` handling so a second launch focuses the original instance and does not start another gateway against the same state directory.
### Window Close Semantics
The macOS red close button can keep the process alive, but the implementation must clear stale window references on `closed` and make activation recreate the window.
If product later chooses quit-on-close, that should be a separate product decision. It changes expected macOS app behavior and gateway lifetime, so it should not be bundled into this bug fix.
### Gateway Runtime Compatibility
The compatibility layer must provide `create_function` on both the protocol and wrapper implementation:
```py
class Connection(Protocol):
async def create_function(...)
class _AsyncConnection:
async def create_function(...)
```
The wrapper should delegate to the underlying sqlite connection in the same thread-safe style as the other compatibility methods.
### Packaging Guard
Before building a distributable DMG:
1. Rebuild the gateway runtime from current source.
2. Fail the release if `desktop/electron/runtime/gateway` is empty or stale.
3. Build the Electron app from current source.
4. Inspect the packaged runtime and assert `create_function` exists.
5. Inspect packaged `app.asar` and assert the main window is created before gateway startup.
6. Sign, notarize, staple, and validate the final DMG.
The previously generated DMG in `dist/desktop-electron` should be treated as stale for this bug because it was built before the latest desktop/runtime fixes.
### Unsigned Functional Testing
It is acceptable to build an unsigned or ad-hoc-signed DMG first for fast local functional testing. This phase should verify application behavior only:
- first launch shows a window immediately;
- advanced configuration can start the gateway;
- closing the window with the red close button and clicking the Dock icon reopens the UI;
- no duplicate gateway process is created;
- logs do not contain the `create_function` crash or duplicate lock failures.
Code signing and notarization do not rewrite Electron or Python business logic, so they should not change the intended desktop/gateway behavior. However, they can change the effective macOS runtime environment through Gatekeeper, quarantine handling, Hardened Runtime, entitlements, nested executable signing, dynamic library loading, and child process launch policy.
Therefore, unsigned validation is only a pre-release smoke test. The final artifact sent to external users must still be rebuilt, signed, notarized, stapled, and validated end to end.
The final release must not sign only the outer `.dmg`. The `.app` bundle and nested executables must be signed before creating/signing/notarizing the DMG.
## Validation Plan
### Automated
- Run gateway compatibility tests covering `_AsyncConnection.create_function`.
- Run gateway startup/lock tests to ensure duplicate startup and stale yoyo lock handling still work.
- Add or keep an Electron-side regression check for startup order, ideally asserting `createMainWindow()` runs before `startGateway()` in the desktop boot path.
- Add an Electron-side test or factored helper test for activation reuse:
- ready gateway state is reused;
- startup-in-progress does not spawn a second gateway;
- exited owned process is cleared before restart.
### Manual DMG Smoke Test
For the first local pass, this test may use an unsigned or ad-hoc-signed DMG. For external distribution, repeat the same test with a freshly built, signed, notarized, and stapled DMG.
1. Remove or move aside existing user data for a clean first-run test.
2. Install the app from the DMG.
3. Launch from `/Applications`; a window must appear immediately.
4. Complete or enter advanced configuration; the gateway should start and the UI should load.
5. Close the window with the red close button.
6. Confirm the Dock dot remains.
7. Click the Dock icon; the window must reopen and load the existing gateway UI.
8. Confirm only one `opensquilla-gateway` process is running.
9. Confirm logs do not contain the `create_function` AttributeError.
10. Confirm logs do not show duplicate gateway state-dir lock failures during Dock activation.
### Release Validation
Release validation applies only to the final signed and notarized artifact.
Run these checks on the final artifact:
```bash
spctl --assess --type open --context context:primary-signature -v dist/desktop-electron/OpenSquilla-*.dmg
spctl --assess --type execute -v dist/desktop-electron/mac-arm64/OpenSquilla.app
xcrun stapler validate dist/desktop-electron/OpenSquilla-*.dmg
hdiutil verify dist/desktop-electron/OpenSquilla-*.dmg
```
Also mount the DMG and inspect the installation window layout.
## Acceptance Criteria
- First launch from a clean DMG install always shows a desktop window before gateway health checks finish.
- Gateway startup failures are visible in the app window with actionable error UI.
- Packaged gateway runtime contains `_AsyncConnection.create_function`.
- Dock activation after red-window-close reopens the UI and reuses the existing healthy gateway.
- Second launch/focus behavior does not spawn a duplicate gateway process.
- Final DMG is signed, notarized, stapled, and passes Gatekeeper validation.
@@ -0,0 +1,219 @@
# Gateway Startup Locking Spec
Date: 2026-06-27
Status: Draft
## Problem
Desktop first-run startup can leave the bundled gateway unable to boot when the
initial process is interrupted or a second gateway process is started while the
first process is still in schema migration.
The observed failure pattern is:
- A fresh desktop state starts successfully enough to seed the agent workspace.
- The first bundled gateway process does not reach `gateway.started`.
- Later gateway processes fail in `apply_pending()` with yoyo `LockTimeout`.
- The yoyo error reports the same earlier process id for every retry.
The direct failure is a stale or active row in the yoyo migration lock table for
the desktop `sessions.db`. Once this state exists, repeated desktop retries do
not recover by themselves.
## Goals
- Prevent the Electron shell from launching duplicate gateway processes for the
same desktop profile.
- Keep the gateway pid lock alive for the full server lifetime and release it
on graceful shutdown.
- Recover from a stale yoyo migration lock only when the recorded pid is proven
dead.
- Preserve yoyo's safety guarantee when another process may still be migrating.
- Surface actionable startup errors instead of an opaque PyInstaller traceback.
## Non-Goals
- Do not disable yoyo migration locking.
- Do not blindly run `break-lock` on every migration lock timeout.
- Do not change the session database schema as part of this fix.
- Do not make the desktop gateway share a process with Electron.
- Do not broaden gateway binding or auth behavior.
## Existing Surfaces
- Electron launches the bundled gateway in `desktop/electron/src/main.ts` via
`spawn(...)`.
- Electron waits up to 45 seconds for `/healthz` before reporting that the
gateway did not become healthy.
- The gateway acquires `GatewayPidLock` before `build_services()` and before
session database migration.
- `build_services()` runs `apply_pending(session_db_path, migrations_dir)` before
opening `SessionStorage`.
- `apply_pending()` delegates locking to `with backend.lock():`.
- yoyo implements the migration lock as a row in `yoyo_lock`, keyed by pid, and
removes it in a `finally` block. A hard process exit can leave the row behind.
## Design
Implement three defensive layers. Each layer addresses a different failure mode
and should be independently testable.
### Layer 1: Electron Single Instance Guard
Add `app.requestSingleInstanceLock()` near Electron app startup, before any
gateway startup work can run.
Expected behavior:
- If the lock cannot be acquired, the new Electron process exits immediately.
- On `second-instance`, the existing main window is restored and focused.
- `bootDesktopApp()` must not run in the second Electron process.
- The existing process remains the only owner allowed to spawn a gateway.
This reduces duplicate gateway starts caused by double-clicking the app,
reopening from Finder, or launching from a DMG while a first run is still in
progress.
### Layer 2: Gateway PID Lock Lifetime
Store the acquired `GatewayPidLock` on the returned `GatewayServer` object and
release it in `GatewayServer.close()`.
Expected behavior:
- `start_gateway_server()` acquires the lock before database migration, as it
does today.
- The lock object remains strongly referenced for the whole server lifetime.
- `GatewayServer.close()` calls `release()` exactly once, after shutdown work is
complete enough that a new gateway may safely start.
- `release()` remains idempotent.
- Existing `atexit` and signal cleanup remain as best-effort fallback paths.
This makes normal gateway shutdown explicit instead of relying only on process
exit behavior.
### Layer 3: Conservative Yoyo Stale Lock Recovery
Wrap yoyo `LockTimeout` handling inside `apply_pending()`.
When yoyo reports a lock timeout:
1. Inspect the lock table for recorded pids.
2. If any recorded pid is alive, fail without clearing the lock.
3. If every recorded pid is dead or invalid, delete the yoyo lock rows.
4. Retry migration once.
5. If the retry fails, surface the second failure without another recovery loop.
The liveness check should use platform-appropriate process probing:
- POSIX: `os.kill(pid, 0)`.
- Windows: `OpenProcess` or equivalent existing helper behavior.
The lock recovery path must log structured events:
- `migrator.lock_timeout`
- `migrator.lock_held_by_live_process`
- `migrator.stale_lock_cleared`
- `migrator.stale_lock_retry_failed`
The operator-facing error should explain whether the gateway is still starting,
another gateway is running, or a stale migration lock could not be recovered.
## Safety Rules
- Never clear a yoyo lock held by a live pid.
- Never clear the lock if the database cannot be inspected safely.
- Never retry migration more than once after clearing a stale lock.
- Keep migration failure loud if schema state is uncertain.
- Prefer false negatives over false positives: failing startup is safer than
corrupting a migration.
## Implementation Notes
Electron:
- Add single-instance handling in `desktop/electron/src/main.ts`.
- Keep the current `startupInProgress` guard for the existing process.
- On a second instance, restore and focus `mainWindow` if it exists.
Gateway:
- Extend `GatewayServer` with an optional pid lock field.
- Assign the acquired lock after `GatewayPidLock.acquire()` succeeds.
- Release the lock in `GatewayServer.close()` in a `finally`-safe path.
Migrator:
- Import yoyo `LockTimeout` explicitly.
- Add a small helper to query `yoyo_lock` rows through the yoyo backend or a
separate SQLite connection to the same local database.
- Add a small helper to clear the yoyo lock table.
- Keep `:memory:` behavior unchanged.
- Keep normal no-pending migration behavior unchanged.
## Test Plan
### Unit Tests
- `GatewayPidLock` rejects a second lock acquisition for the same state dir while
the first lock is held.
- `GatewayServer.close()` releases the stored gateway pid lock.
- `apply_pending()` does not clear a yoyo lock for a live pid.
- `apply_pending()` clears a yoyo lock for a dead pid and retries once.
- `apply_pending()` does not enter an unbounded retry loop after stale-lock
recovery fails.
- `apply_pending()` preserves normal migration success and no-op behavior.
### Electron Tests
- A second Electron instance does not call `bootDesktopApp()`.
- A second Electron instance focuses the existing window.
- Desktop retry does not spawn a new gateway while startup is already in
progress.
### Integration Tests
- Create a temporary desktop state with `sessions.db` containing a stale
`yoyo_lock` row. Gateway startup clears it and completes migration.
- Create a temporary desktop state with a live helper process recorded in
`yoyo_lock`. Gateway startup fails with a clear, non-destructive error.
- Start two gateway processes against the same state dir. The second process
fails before database migration.
### Manual DMG Smoke
- Install the DMG into `/Applications`.
- Start from a clean desktop user data directory.
- Double-click the app repeatedly during first-run startup.
- Confirm only one gateway process is launched.
- Confirm the app becomes ready or surfaces a clear single startup error.
- Force quit during first-run migration, relaunch, and confirm stale-lock
recovery works when the recorded pid is no longer alive.
## Acceptance Criteria
- Fresh DMG first run cannot spawn two owned gateway processes from two Electron
instances.
- A stale yoyo migration lock whose pid is dead is cleared automatically and the
gateway starts.
- A yoyo migration lock whose pid is alive is never cleared automatically.
- A second gateway using the same desktop state fails before migration work.
- Graceful gateway shutdown removes `gateway.pid` and releases
`gateway.pid.lock`.
- Failure messages distinguish active startup, already-running gateway, and
unrecoverable migration lock states.
- CI covers stale-lock recovery and live-lock non-recovery.
## Rollout
- Ship behind normal startup behavior, with no user-facing setting.
- Keep structured logs in the desktop gateway log for post-incident diagnosis.
- Add a short troubleshooting entry once the behavior is implemented.
## Open Questions
- Whether yoyo lock inspection should use yoyo backend APIs only or direct
SQLite for local file databases.
- Whether desktop startup should extend the first-run health timeout after it
detects schema migration is active.
- Whether the boot splash should show a distinct "Preparing database" phase.
+129
View File
@@ -0,0 +1,129 @@
# Memory
OpenSquilla memory helps the agent recall durable context without replaying
every old conversation. Use it for stable preferences, reusable project facts,
previous decisions, and notes that should survive across sessions.
Memory is separate from skills. Skills teach the agent how to do a task; memory
stores useful facts and context the agent may need later.
## What to Store
Good memory entries are stable and reusable:
- user preferences;
- project conventions;
- recurring output formats;
- names of important repositories, directories, or services;
- decisions the user wants reused;
- brief notes from completed tasks.
Avoid memory for:
- API keys or secrets;
- raw private data that does not need long-term recall;
- one-off instructions for the current turn;
- noisy dumps that would pollute future retrieval;
- exact transcripts that should instead be exported as session records.
## Common Commands
Inspect memory health:
```sh
opensquilla memory status
opensquilla memory status --deep
```
Index and list memory sources:
```sh
opensquilla memory index
opensquilla memory list
```
Search and inspect memory:
```sh
opensquilla memory search "release note format"
opensquilla memory show <path>
```
Search previous sessions as well as memory:
```sh
opensquilla memory search "deployment decision" --source all
```
## Natural Chat Usage
Ask naturally when something should be remembered:
```text
Remember that I prefer concise release notes with a risk section.
```
Later, refer to the preference:
```text
Use my usual release-note format for this changelog.
```
When memory seems stale, ask the agent to search explicitly:
```text
Search memory for my release-note preferences before drafting this.
```
## Session-Derived Memory
For long or important sessions, flush session state into memory before
archiving, compacting, or switching tasks:
```sh
opensquilla memory flush-session <session-key>
```
Use session export when exact old wording matters:
```sh
opensquilla sessions export <session-key>
```
Memory is for useful recall. Session export is for exact records.
## Maintenance and Repair
Refresh the index after editing memory files or changing memory configuration:
```sh
opensquilla memory index --force
```
Inspect fallback and repair surfaces:
```sh
opensquilla memory raw-fallbacks list
opensquilla memory repair list
```
Show or repair a degraded compaction memory record when instructed by
diagnostics:
```sh
opensquilla memory repair show --summary-id <id>
opensquilla memory repair run --summary-id <id>
```
## Best Practices
- Keep entries short and sourceable.
- Prefer "Remember X for project Y" over vague "remember this."
- Search memory before assuming the agent forgot.
- Remove or revise stale preferences instead of adding contradictory ones.
- Keep secrets out of memory.
- Use artifacts or files for large reference material.
---
[Docs index](../README.md) · [Product guide](../../README.product.md) · [Improve this page](../contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+439
View File
@@ -0,0 +1,439 @@
# OpenSquilla MetaSkill User Guide
MetaSkill lets OpenSquilla move from figuring out complex work from scratch on
every turn to reusable, explicitly launchable, auditable, and improvable task
protocols.
A normal conversation solves one request. A MetaSkill preserves a way of doing
high-value work.
## Important Notice
Some MetaSkills in OpenSquilla, and some of the skills they call, are authored,
revised, or composed with AI assistance based on intended functionality,
available capabilities, and usage scenarios.
This means:
- MetaSkills are not merely a collection of fully hand-written scripts. They are
part of a system where AI can help formalize and evolve reusable task
protocols.
- AI-authored or AI-assisted MetaSkills should be reviewed through structural
validation, trigger-surface checks, runtime testing, human review, and
safety-boundary assessment before they are treated as ready for use.
- MetaSkill outputs are decision-support materials and work-product drafts. They
are not final professional advice in legal, medical, financial, hiring,
academic, security, or other high-stakes contexts.
- Actions such as publishing, applying, installing, paying, signing, messaging,
or modifying production systems require explicit user authorization and remain
the user's responsibility.
- When a MetaSkill relies on search, document parsing, LLM judgment, or
third-party tools, the result may be affected by source quality, model
limitations, tool availability, context completeness, and time-sensitive
changes.
- Users should review facts, citations, assumptions, risks, and unverifiable
claims, especially in high-stakes situations.
In short: MetaSkill turns high-value work into reusable, auditable, and
improvable AI collaboration protocols. It does not remove the need for review,
judgment, or accountability.
## What It Is
OpenSquilla is an open-source AI agent runtime. MetaSkill is its task-protocol
layer.
A MetaSkill does not introduce new execution atoms. It defines a way to organize
existing atoms, such as skills, tools, LLM calls, and sub-agents, into a
reusable task protocol.
The analogy is a Makefile and shell commands. A Makefile does not replace
commands; it defines how commands are composed. A MetaSkill does not replace
skills or tools; it tells OpenSquilla how a class of high-value work should be
understood, structured, checked, and delivered.
MetaSkill provides four main advantages:
- protocolized capability captured in a `SKILL.md` file with `kind: meta` and
`composition.steps`;
- explicit launch through `/meta`, with optional automatic triggering only when
`meta_skill.auto_trigger = true`;
- auditable and replayable step inputs, outputs, status, and results;
- improvable over time as repeated collaboration patterns become proposals.
## Default Launch Model
MetaSkills are manual-only by default. On supported chat surfaces, use `/meta`
to list available workflows and `/meta <name>` to run one. This keeps workflow
launches deliberate, reviewable, and easier to explain.
Web chat and the CLI gateway TUI support both list and run:
```text
/meta
/meta meta-kid-project-planner
```
Channel surfaces support `/meta` listing only. Standalone CLI chat requires
gateway mode for `/meta`.
To restore the older automatic behavior, set:
```toml
[meta_skill]
auto_trigger = true
```
With `auto_trigger = true`, OpenSquilla may consider MetaSkills during ordinary
natural-language turns. Leave it off when you want workflows to run only after
an explicit `/meta <name>` command.
## User Mental Model
Using a MetaSkill is not just asking a question. It is delegating OpenSquilla to
produce a reviewable result.
A strong MetaSkill request contains four things:
1. Outcome: what you want to receive.
2. Context: materials, entities, time range, and constraints that matter.
3. Standard: what "good" means for this task.
4. Boundaries: what must not happen, what must not be invented, and what requires
confirmation.
Example:
```text
/meta meta-kid-project-planner
I need a safe weekend project plan, not a generic list of ideas.
Use only materials that are easy to buy locally.
Separate adult-only steps from child-safe steps.
Do not include flames, blades, solvents, or risky chemicals.
```
The user defines the target and standard; OpenSquilla organizes the execution.
## Current Built-In MetaSkills
The retained built-in MetaSkills cover a focused set of high-value task classes.
| MetaSkill | Positioning |
| --- | --- |
| `meta-kid-project-planner` | Produces safe, age-appropriate plans for school projects, show-and-tell, or science activities. |
| `meta-paper-write` | Supports academic drafts, manuscript structure, citation planning, experiment placeholders, and LaTeX/PDF paths. |
| `meta-short-drama` | Produces short-drama scripts, visual prompts, video assembly plans, subtitles, and rendered local video artifacts. |
| `meta-skill-creator` | Turns repeated multi-skill collaboration patterns into new MetaSkill proposals. |
These are designed around quality over quantity. Immature, duplicate, or
single-skill wrapper MetaSkills should not remain in the bundled catalog.
## Requirements Before Running MetaSkills
The Skill page is the source of truth for current readiness. Open the skill
detail dialog and check the **Requirements** section before running workflows
that export files, compile PDFs, or render video.
Common setup surfaces:
- Paper/PDF workflows such as `meta-paper-write` require `xelatex` and
`bibtex` on `PATH`. Install a TeX distribution such as TeX Live, MiKTeX, or
BasicTeX before requesting compiled PDFs.
- Video workflows such as `meta-short-drama` require `ffmpeg` and `ffprobe` on
`PATH` for clip animation, merging, and subtitle burn-in.
- Office-document workflows roll up requirements from child skills such as
`docx`, `xlsx`, `pdf-toolkit`, and `pptx`; these usually surface Python
package requirements in the Skill page.
- Search, weather, image, and video-provider steps may require configured API
keys or provider credentials. The workflow should treat missing credentials as
setup blockers rather than silently degrading output.
## Two Ways to Use MetaSkill
### Default: Explicit Command
Start the workflow with `/meta <name>` and then describe the outcome:
```text
/meta meta-kid-project-planner
Plan a safe 20-minute balcony plant science project for a 7-year-old. Include
materials, steps, safety notes, and a simple presentation outline.
```
This is the normal 0.4 release-line path. It is best for important, expensive,
or easily confused tasks because the workflow launch is explicit.
### Compatibility: Automatic Triggering
If `meta_skill.auto_trigger = true` is set, OpenSquilla can consider MetaSkills
from natural-language intent:
```text
Use meta-skill `meta-kid-project-planner`.
Plan a safe 20-minute balcony plant science project for a 7-year-old. Include
materials, steps, safety notes, and a simple presentation outline.
```
This mode is for users who intentionally want the older auto-trigger behavior.
It is not the default.
## Low-Cost, High-Quality Request Template
Recommended template:
```text
/meta <name>
Outcome:
Context:
Decision standard:
Expected output:
Constraints:
Do not:
```
Example:
```text
/meta meta-kid-project-planner
Outcome: plan a child-safe weekend science project.
Context: 7-year-old, balcony plants, 20 minutes of activity, ordinary household
materials only.
Decision standard: safe, age-appropriate, low mess, and easy to present at
school.
Expected output: materials list, adult setup, child steps, safety notes, and a
presentation outline.
Constraints: avoid flames, blades, solvents, and risky chemicals.
Do not: ask the child to do adult-only setup alone.
```
Useful constraints:
- Do not invent missing facts.
- Separate facts, assumptions, and recommendations.
- Use only pasted material unless sources are available.
- Do not submit, publish, install, pay, send, or sign automatically.
- Ask me if a decision depends on missing information.
## Built-In MetaSkill Usage Patterns
### `meta-kid-project-planner`
Use for child school projects, show-and-tell, science demos, and safe creative
activities.
Good fit:
- science fair;
- show-and-tell;
- classroom demonstration;
- child-safe craft or experiment;
- low-burden parent preparation.
High-quality request:
```text
/meta meta-kid-project-planner
Help my child prepare a second-grade science fair project about plant growth. We
have beans, paper cups, cotton, water, and a sunny windowsill.
Keep it safe and simple.
Give me:
- materials list
- 3-day plan
- what the child should observe
- short presentation script
- what remains unknown
```
Expected result: safe, age-appropriate, source-strict output. It should not
invent weather, school requirements, or child preferences.
### `meta-paper-write`
Use for academic papers, research manuscripts, and LaTeX-oriented deliverables.
Good fit:
- compact paper skeleton;
- section structure;
- citation plan;
- experiment and figure/table placeholders;
- LaTeX/PDF path when explicitly requested.
PDF compilation requires `xelatex` and `bibtex` on `PATH`. If those binaries are
missing, use the LaTeX source output or install TeX Live, MiKTeX, or BasicTeX
before asking for a compiled PDF.
High-quality request:
```text
/meta meta-paper-write
Draft a compact research paper skeleton on retrieval-augmented generation for
customer-support knowledge bases.
Include:
- title
- abstract
- related work plan
- method outline
- experiment placeholders
- figure/table placeholders
- citation plan
Keep it compact first. Do not write a full manuscript unless I ask.
```
Expected result: a paper-shaped deliverable, not a generic essay. Citations
should not be presented as verified sources unless actually verified.
### `meta-skill-creator`
Use to create a new MetaSkill proposal.
Good fit:
- turning repeated multi-skill collaboration into a reusable capability;
- defining trigger surfaces;
- composing existing skills;
- adding validation and risk checks;
- producing a proposal for review.
Poor fit:
- creating a normal single-purpose skill;
- analyzing existing skill lists without creating anything;
- asking what MetaSkill is;
- pasting old pages for diagnosis.
High-quality request:
```text
/meta meta-skill-creator
Create a new meta-skill for product launch briefs. It should search current
sources, collect product context, draft a launch memo, generate a DOCX handoff,
check evidence gaps, and avoid publishing anything automatically.
Please propose:
- name
- description
- triggers
- steps
- validation gates
- collision checks
```
Expected result: a proposal, not an immediate unreviewed production rollout.
## Avoiding Accidental Activation
If you paste old chat history, Web UI dumps, prompt examples, skill lists, or
test material, mark it as quoted context:
```text
The following is quoted context, not my current request.
Do not run any skill.
Do not create or persist any proposal.
Only analyze this text.
```
This matters because historical material may contain trigger words. Without a
clear boundary, the system may confuse quoted content with current intent.
If you only want to analyze a MetaSkill and do not want proposal creation:
```text
Only analyze. Do not create, assemble, preview, or persist any meta-skill
proposal.
```
## Run Progress Ribbon
While a MetaSkill runs, the WebUI shows a horizontal ribbon at the top
of the agent reply listing every step in the workflow. The currently
running chip is highlighted; succeeded steps show ✓, skipped ↷, failed
✗, and `on_failure` substitutes show ⇄. Click any chip to scroll to
that step's tool card. If a step fails, the ribbon also surfaces
"Retry run", "Switch meta-skill", and "Show error detail" actions
inline.
The ribbon survives disconnects: when the browser reconnects, the gateway
replays the announce → state → completed events so the ribbon rebuilds
to the latest state.
## Reading the Result
A strong MetaSkill result should explain:
- what it produced;
- what facts or sources it used;
- what is inferred or assumed;
- what risks remain;
- what the next action is;
- what could not be verified;
- whether any artifact or proposal was actually created.
Be cautious if the output:
- claims current facts without sources;
- claims a file was created but no artifact exists;
- hides tool failures as success;
- gives generic advice instead of the requested deliverable;
- ignores "do not create", "do not send", "do not publish", or "do not install".
## Correcting a Bad Run
If the wrong MetaSkill triggered:
```text
Stop using the previous MetaSkill. Treat my earlier text as context only. Now
use meta-skill `<correct_name>` for this goal: ...
```
If no MetaSkill triggered:
```text
Please rerun and explicitly use meta-skill `<name>`.
```
If the output is too generic:
```text
Redo this as a decision-ready deliverable with evidence, assumptions, risks, and
next actions.
```
If creator starts creating but you do not want creation:
```text
Do not create, assemble, preview, or persist any meta-skill proposal. Only
analyze.
```
## Building Your Own MetaSkill
A task is a good MetaSkill candidate when:
- you repeatedly perform the same high-value task;
- each run has multiple steps;
- inputs are similar but details vary;
- the output format is relatively stable;
- review, audit, replay, or confirmation matters;
- ordinary prompts require you to restate too many rules every time.
Poor candidates include one-line fact queries, single tool calls, casual
conversation, brainstorming without stable output criteria, and high-risk
automated action without human confirmation.
For the authoring protocol, read [`../authoring/meta-skills.md`](../authoring/meta-skills.md).
---
[Docs index](../README.md) · [Product guide](../../README.product.md) · [Improve this page](../contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+177
View File
@@ -0,0 +1,177 @@
# Meta-Skills
Meta-skills package repeatable multi-step work as reusable, inspectable
workflows. Use them when a request needs more than one normal skill, tool,
checkpoint, or final synthesis pass.
For the full user-facing guide, read
[`meta-skill-user-guide.md`](meta-skill-user-guide.md). For authoring rules,
read [`../authoring/meta-skills.md`](../authoring/meta-skills.md).
## Skills vs Meta-Skills
| Capability | Use it for |
| --- | --- |
| Skill | One focused task pattern, instruction set, script, or tool helper. |
| Meta-skill | A reusable workflow made of multiple steps, skills, checks, or outputs. |
For example, "summarize this document" is skill-shaped. "Plan a safe child
science project with materials, adult setup, child steps, presentation notes, and
final safety review" is meta-skill-shaped.
## Stable Built-In MetaSkills
The retained stable catalog is intentionally small:
| MetaSkill | Positioning |
| --- | --- |
| `meta-kid-project-planner` | Produces safe, age-appropriate plans for school projects, show-and-tell, or science activities. |
| `meta-paper-write` | Supports academic drafts, manuscript structure, citation planning, experiment placeholders, and LaTeX/PDF paths. |
| `meta-short-drama` | Produces short-drama scripts, visual prompts, subtitles, and local video artifacts. |
| `meta-skill-creator` | Turns repeated multi-skill collaboration patterns into new MetaSkill proposals. |
Experimental meta-skills may exist under development trees, but this page lists
only bundled built-ins that should be presented as retained product
capabilities.
## Requirements
Use the Skill page detail dialog before running a MetaSkill. Its
**Requirements** section shows the MetaSkill's own requirements plus one-hop
requirements from child skills.
- `meta-paper-write` needs `xelatex` and `bibtex` for PDF compilation.
- `meta-short-drama` needs `ffmpeg` and `ffprobe` for local video rendering,
merge, and subtitle steps.
- MetaSkills inherit readiness from their child skills; for example,
`meta-paper-write` surfaces LaTeX/PDF requirements and
`meta-short-drama` surfaces local video-tool requirements.
## Run MetaSkills
MetaSkills are manual-only by default. They do not auto-trigger from message
keywords or appear in the runtime prompt unless you explicitly opt into the old
automatic behavior.
In Web chat and the CLI gateway TUI:
```text
/meta
/meta meta-kid-project-planner
```
`/meta` lists available MetaSkills. `/meta <name>` starts the selected
workflow. Channel surfaces can list MetaSkills with `/meta`, but they do not run
MetaSkills from chat text. Standalone CLI chat requires gateway mode for
`/meta`.
To restore automatic model-triggered behavior, set:
```toml
[meta_skill]
auto_trigger = true
```
Use this compatibility mode only when you want MetaSkills to be considered by
the model during ordinary chat turns.
## How to Prepare the Request
Ask for the outcome and the standard:
```text
Plan a safe 20-minute balcony plant science project for a 7-year-old. Include
materials, adult setup, child steps, safety notes, and a presentation outline.
```
When you start a workflow, include the task after the command:
```text
/meta meta-kid-project-planner
Plan a safe 20-minute balcony plant science project for a 7-year-old. Include
materials, adult setup, child steps, safety notes, and a presentation outline.
```
A strong request usually includes:
- outcome;
- context;
- decision standard;
- expected output;
- constraints;
- actions the agent must not take.
## Discover Meta-Skills
Use chat slash commands for the runtime list:
```text
/meta
```
Use the CLI for inventory and inspection:
```sh
opensquilla skills list
opensquilla skills search meta
```
Inspect a meta-skill composition:
```sh
opensquilla skills inspect <meta-skill-name>
```
The inspect command shows the compiled step shape before you rely on a workflow.
## Inspect Run History
List recent runs:
```sh
opensquilla skills meta runs list
```
Inspect one run:
```sh
opensquilla skills meta runs show <run-id>
opensquilla skills meta runs steps <run-id>
opensquilla skills meta runs failures --since 24h
```
Preview replay shape without executing live work:
```sh
opensquilla skills meta runs replay <run-id> --dry-run
```
## Proposals
Meta-skill creation workflows may write proposals before they become managed
skills. Inspect proposals:
```sh
opensquilla skills meta proposals list
opensquilla skills meta proposals show <proposal-id>
```
Accept a proposal only after review:
```sh
opensquilla skills meta proposals accept <proposal-id>
```
## Safety Model
MetaSkill outputs are reviewable work products and decision-support drafts. They
are not final professional advice in legal, medical, financial, hiring,
academic, security, or other high-stakes contexts.
Actions such as publishing, applying, installing, paying, signing, messaging, or
modifying production systems require explicit user authorization.
---
[Docs index](../README.md) · [Product guide](../../README.product.md) · [Improve this page](../contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+159
View File
@@ -0,0 +1,159 @@
# Skills
Skills are task-specific instruction packages and scripts. They let OpenSquilla
load relevant guidance only when a task needs it, instead of putting every
possible instruction into every prompt.
Skills are separate from memory. Memory stores facts; skills describe repeatable
ways to work.
## What Skills Are For
Use skills for repeatable work patterns such as:
- deep research;
- summarization;
- GitHub and PR workflows;
- document generation;
- spreadsheet, slide, PDF, and DOCX work;
- web search;
- weather lookup;
- terminal or tmux monitoring;
- subagent delegation;
- skill creation and review.
If the workflow combines multiple skills or a reusable multi-step plan, use a
meta-skill instead.
## Discover Installed Skills
List skills available in the current install:
```sh
opensquilla skills list
```
View one skill:
```sh
opensquilla skills view <skill-name>
```
Search community sources:
```sh
opensquilla skills search pdf
```
Some skills may be ineligible when optional dependencies are missing or when the
skill is intentionally demo-only. `skills list` is the source of truth for your
current install.
## Install, Update, and Remove Skills
Install a managed skill:
```sh
opensquilla skills install <skill-name>
```
Update one skill or all managed skills:
```sh
opensquilla skills update <skill-name>
opensquilla skills update --all
```
Remove a managed skill:
```sh
opensquilla skills uninstall <skill-name>
```
## Manage Skill Sources
Custom source repositories are called taps:
```sh
opensquilla skills tap list
opensquilla skills tap add <owner/repo>
opensquilla skills tap remove <owner/repo>
```
Use taps when your team maintains its own skill catalog.
## Publish and Inspect
Publish a skill directory:
```sh
opensquilla skills publish <path-to-skill>
```
Inspect the compiled composition for a meta-skill:
```sh
opensquilla skills inspect <meta-skill-name>
```
For ordinary skill content, use:
```sh
opensquilla skills view <skill-name>
```
## How to Ask for a Skill
Ask for the outcome:
```text
Create a PowerPoint deck summarizing this report.
```
Better than:
```text
Load the pptx skill and run its script.
```
OpenSquilla can choose eligible skills from the current catalog when the task
matches their description and triggers.
## Bundled Skill Families
| Family | Examples |
| --- | --- |
| Research | deep research, multi-source search, summarization |
| Documents | DOCX, PPTX, XLSX, PDF, HTML-to-PDF |
| Operations | cron, GitHub, terminal monitoring, subagents |
| Memory | memory-oriented helpers and history exploration |
| Creation | skill creator, skill review, proposal helpers |
## Troubleshooting
If a skill is not selected:
1. Confirm it appears in the installed catalog:
```sh
opensquilla skills list
```
2. Inspect its description and eligibility:
```sh
opensquilla skills view <skill-name>
```
3. Ask for the outcome in normal language. Skill names can help, but user
intent should still be clear.
4. If optional dependencies are missing, install or update the skill and retry.
For composed workflows, read [`meta-skills.md`](meta-skills.md). For the full
MetaSkill user guide, read [`meta-skill-user-guide.md`](meta-skill-user-guide.md).
For authoring rules, read [`../authoring/meta-skills.md`](../authoring/meta-skills.md).
---
[Docs index](../README.md) · [Product guide](../../README.product.md) · [Improve this page](../contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+172
View File
@@ -0,0 +1,172 @@
# SquillaRouter
SquillaRouter is OpenSquilla's local model-routing layer. It helps the agent
choose an appropriate model tier for each turn so routine work does not always
run on the most expensive model.
Use this page when you want to enable routing, understand what it changes, or
decide whether a fixed provider/model is better for a specific run.
## Why Use It
SquillaRouter is useful when you want:
- lower cost for simple chat, edits, summaries, and routine tool work;
- stronger models reserved for hard reasoning, recovery, and long tasks;
- one OpenSquilla workflow that can route across provider profiles;
- local routing decisions without sending prompts to a separate external
classifier just to choose the model.
It is not required. OpenSquilla can also run in direct single-model mode.
## Enable Routing
Recommended first-run setup:
```sh
opensquilla onboard --router recommended
```
Reconfigure an existing install:
```sh
opensquilla configure router --router recommended
```
Use the OpenRouter mixed defaults:
```sh
opensquilla configure router --router openrouter-mix
```
Disable routing and use the configured provider/model directly:
```sh
opensquilla configure router --router disabled
```
## Inspect Provider Support
Check the provider catalog available in your install:
```sh
opensquilla providers list
```
If the gateway is running, inspect runtime provider health:
```sh
opensquilla providers status
```
Router-supported profiles depend on the installed OpenSquilla version,
optional dependencies, and configured provider credentials. Common profiles
include OpenRouter, OpenAI, DeepSeek, Gemini, DashScope, Moonshot, Volcengine,
Zhipu, and compatible provider tiers exposed by the local catalog.
## What the Router Can Affect
Depending on configuration, SquillaRouter may influence:
- selected model tier;
- direct model fallback;
- reasoning level;
- response policy;
- image-capable model selection;
- cache-continuity safeguards for recent higher-tier turns.
The exact decision is available through runtime metadata and diagnostics
surfaces. Turn on diagnostics when you need to understand why a turn was routed
to a particular model:
```sh
opensquilla diagnostics on
```
## Terminal Router HUD
Interactive terminal chat can surface routing decisions through a TUI Router HUD
when router metadata is present and the selected backend supports the structured
UI/plugin surface. In the current implementation, the OpenTUI preview footer is
the primary terminal display for this HUD. The HUD is display-only: it consumes
the same turn metadata and does not change model selection.
The HUD can show the selected tier, selected model, baseline model, route
source, confidence, estimated savings, fallback state, thinking mode, prompt
policy, whether routing was applied, and rollout phase.
Full routing is shown as an active route. Observe-only routing is shown as an
observe decision, which means OpenSquilla recorded what the router would have
chosen while keeping the configured baseline behavior. Fallback decisions use a
warning style so provider or policy recovery is visible during the turn.
## Recommended Operating Modes
| Goal | Suggested mode |
| --- | --- |
| General personal-agent use | `recommended` |
| Multi-provider cost optimization through OpenRouter | `openrouter-mix` |
| Provider evaluation, billing audit, or reproducible benchmark run | `disabled` |
| Debugging one provider-specific behavior | `disabled` |
For routine use, start with `recommended`. Disable routing only when the model
choice itself is the thing you are testing.
## Example Requests
Good router-friendly requests describe the outcome, not the tier:
```text
Summarize this long issue thread and list the decision points.
```
```text
Review my current diff and point out the highest-risk changes.
```
Avoid asking the router to behave like a manual model picker unless you are
debugging:
```text
Use exactly this one model for every turn.
```
For exact-model work, configure direct routing instead.
## Troubleshooting
If routing does not appear to work:
1. Confirm the router is enabled:
```sh
opensquilla config get router.enabled
opensquilla config get llm.provider
```
2. Check provider readiness:
```sh
opensquilla providers status
opensquilla doctor
```
3. If SquillaRouter optional dependencies are missing, OpenSquilla can still run
with direct single-model routing. On Windows, ONNX Runtime may require the
Visual C++ Redistributable. On macOS terminal installs, LightGBM may require
`libomp` from Homebrew:
```sh
brew install libomp
opensquilla gateway restart
```
4. If you need deterministic model behavior for a run, disable routing:
```sh
opensquilla configure router --router disabled
```
---
[Docs index](../README.md) · [Product guide](../../README.product.md) · [Improve this page](../contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+118
View File
@@ -0,0 +1,118 @@
# Tool Compression
OpenSquilla agents use tools. Tool calls can produce large outputs: command
logs, JSON, web pages, search results, diffs, file contents, tables, and
artifacts. Tool compression keeps those outputs useful without letting them
consume the whole model context.
This is a user-facing context-management feature. It does not change what the
tool returned; it changes how much of that result is shown to the model for the
next step.
## Why It Matters
Tool compression helps when:
- a command prints a large log;
- a web page or search result is too long for a useful prompt;
- a file read returns more text than the next step needs;
- a long session is close to the context budget;
- you want raw results preserved while the model sees a compact preview.
Without compression, one large tool result can crowd out the user's goal,
recent conversation, and next action.
## What Users May See
In long or tool-heavy turns, the model-visible result may include:
- a compact preview;
- a note that a result was shortened;
- a `tool_result_handle` for an out-of-band stored result;
- estimated token-saving diagnostics when diagnostics are enabled.
This is expected. It means OpenSquilla is protecting the active context window.
## Product-Level Model
OpenSquilla separates two views:
| View | Purpose |
| --- | --- |
| Runtime view | The durable result OpenSquilla can preserve, inspect, or export. |
| Provider view | The bounded text sent back to the model for the next reasoning step. |
The agent can continue from the important facts while large raw material stays
available through files, session export, diagnostics, or tool-result handles
when configured.
## Compression Modes
OpenSquilla supports several compression styles depending on configuration and
tool output shape.
| Mode | Best for | Tradeoff |
| --- | --- | --- |
| `truncate` | Fast deterministic previews. | May omit useful middle sections. |
| `summarize` | Slower/background workflows that benefit from semantic summaries. | Adds another model call and should be opt-in. |
| Structured projection | Logs, diffs, JSON, tables, and known tool shapes. | Depends on reducer coverage for that output type. |
Most users should keep the default behavior and use diagnostics only when a
workflow is still too large.
## How to Work With Large Outputs
Ask for focused follow-up reads:
```text
Look at the failing test names and the last 80 lines of the log.
```
Prefer handles, paths, and summaries:
```text
Use the compacted result to identify likely causes, then read the exact file
sections you need.
```
Avoid asking the agent to paste every line of a huge result unless exact text is
the deliverable:
```text
Paste the entire 50,000-line log into chat.
```
## Inspect and Debug
Turn on diagnostics when you need to understand context growth:
```sh
opensquilla diagnostics on
```
Export the session when you need to inspect durable history outside the chat
surface:
```sh
opensquilla sessions export <session-key>
```
Review cost and usage after a large tool-heavy run:
```sh
opensquilla cost
```
## Best Practices
- Keep tool requests specific.
- Ask for the smallest file ranges, log tail, or JSON fields that answer the
question.
- Use artifacts for large deliverables instead of forcing everything into chat.
- Use session export for audit and debugging.
- Treat tool compression as a continuity feature, not as a substitute for
storing important files.
---
[Docs index](../README.md) · [Product guide](../../README.product.md) · [Improve this page](../contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+105
View File
@@ -0,0 +1,105 @@
# TUI Frontend
OpenSquilla terminal chat has one stable default backend and one opt-in preview
backend:
| Backend or target | Status | How to use | Requirements |
| --- | --- | --- | --- |
| `native` | Stable default | `opensquilla chat` | Python package only |
| `opentui` | Preview opt-in | `OPENSQUILLA_TUI_BACKEND=opentui uv run opensquilla chat` | Source checkout, Bun, and local OpenTUI package dependencies |
| `live-opentui` | Manual harness target | Real-terminal harness only | tmux, OpenTUI deps, and live provider config |
`live-opentui` is not an `OPENSQUILLA_TUI_BACKEND` value. It is a guarded test
target that launches the OpenTUI preview path through the real CLI.
The TUI contracts are renderer-independent and built around two separate planes:
- **Streaming plane:** batches token deltas before writing to the terminal, so
long answers do not redraw the whole interface for every token.
- **Structured UI plane:** sends normalized TUI domain events to plugins. Plugin
snapshots can be rendered by capable TUI backends and by future renderers.
The stable default terminal chat is Python-native and does not require Bun,
npm, or OpenTUI node modules. OpenTUI is a source-checkout preview backend
selected explicitly with `OPENSQUILLA_TUI_BACKEND=opentui`.
## Plugin Slots
Plugins consume renderer-independent events and publish small snapshots through
named slots. Current slots include:
| Slot | Purpose |
| --- | --- |
| `router_hud` | Active-turn model-routing decision. |
| `status` | Compact status or queue notices. |
| `tool_activity` | Tool cards and tool summary history. |
| `usage` | Token, cache, and cost summary. |
| `inspector` | Optional detail panel state for selected items. |
The first plugin is `RouterHudPlugin`. It listens for
`router_decision` events and updates the bottom toolbar without changing router
selection behavior.
## Router HUD
When routing metadata is available, capable TUI backends can render a Router
HUD. In the current implementation, the OpenTUI footer is the primary preview
display for this HUD. The HUD is display-only: it consumes turn metadata and
does not change model selection.
The HUD can show:
- selected tier and model;
- baseline model;
- route source;
- confidence;
- estimated savings;
- fallback state;
- thinking mode;
- prompt policy;
- whether routing was applied;
- rollout phase.
`routing_applied=true` with a full rollout is shown as an active route.
`routing_applied=false` or an observe rollout is shown as observe-only. Fallback
routes use warning styling.
## Backend Selection
The default backend is stable Python-native terminal chat.
The internal backend selector reads `OPENSQUILLA_TUI_BACKEND`. Unset or empty
values select stable terminal chat. Set the variable to `opentui` only in a
source checkout when evaluating the preview backend. Legacy values fail before
chat launch with a clear unsupported-backend error.
```sh
bun install --frozen-lockfile --cwd=src/opensquilla/cli/tui/opentui/package
OPENSQUILLA_TUI_BACKEND=opentui uv run opensquilla chat
```
The preview backend is loaded from the OpenTUI package next to the running
source tree; it is not required for normal terminal chat.
Do not add parallel terminal/frontend implementations without fresh product
direction and replay plus real-terminal evidence.
## Replay Benchmarks
The replay harness measures the OpenTUI rendering path without a live provider:
```sh
uv run python scripts/bench_tui_replay.py --renderer opentui --fixture long-stream --summary-json .artifacts/tui/opentui-long-stream.json
uv run python scripts/bench_tui_replay.py --renderer opentui --fixture dense-history --summary-json .artifacts/tui/opentui-dense-history.json
```
Summary fields include `renderer`, `fixture`, `available`, `skip_reason`,
`event_count`, `text_chars`, `tool_count`, `router_decision_count`, `wall_ms`,
`flush_count`, `max_buffer_chars`, `coalescing_ratio`, `transcript_items`,
`visible_items`, `expanded_tools`, `projection_wall_ms`,
`rendered_text_matches`, `plugin_error_count`, and `errors`.
Use the OpenTUI results as preview backend evidence.
For terminal-level launch and rendering evidence, use the
[real-terminal TUI harness](../tui-real-terminal-harness.md).
+156
View File
@@ -0,0 +1,156 @@
# Gateway
The OpenSquilla gateway is the local server behind the Web UI, channels, RPC
clients, sessions, approvals, diagnostics, and usage views. Most day-to-day
OpenSquilla surfaces work best when the gateway is running.
Use this page when you want to start, stop, inspect, expose, or troubleshoot
the gateway.
## Foreground Gateway
Run the gateway in the current terminal:
```sh
opensquilla gateway run
```
Open the control console:
```text
http://127.0.0.1:18791/control/
```
Stop a foreground gateway with `Ctrl+C`.
## Managed Background Gateway
Start a managed background process and wait for readiness:
```sh
opensquilla gateway start --json
```
Inspect it:
```sh
opensquilla gateway status
opensquilla gateway status --json
```
Restart or stop it:
```sh
opensquilla gateway restart
opensquilla gateway stop
```
Stop and restart shut down gracefully: in-flight agent turns and background
completions are drained before the process exits, and the force-kill deadline
exceeds that drain budget so work is not cut off mid-write. Tune the per-phase
drain budget with `OPENSQUILLA_GATEWAY_GRACEFUL_TIMEOUT` (seconds; default 30,
bounded). The same drain runs on `Ctrl+C` / `SIGTERM` for a foreground gateway.
On Windows — which has no real `SIGTERM` — the desktop app and `gateway stop`
trigger the drain through an owner-only, loopback `POST /api/system/shutdown`.
Use the managed gateway for the Web UI, channels, scheduled jobs, and local
automation that should survive the current terminal tab.
## Host and Port
Use a different port:
```sh
opensquilla gateway run --port 18792
opensquilla gateway status --port 18792
```
Bind to a specific host:
```sh
opensquilla gateway run --listen 127.0.0.1 --port 18791
```
`--listen` is an alias for the bind host and wins over `--bind` when both are
provided.
## Safety Defaults
The gateway defaults to loopback scope, usually `127.0.0.1`, because the local
gateway controls chat, tools, sessions, channels, approvals, and configuration.
Public binding is opt-in:
```sh
opensquilla gateway run --listen 0.0.0.0 --port 18791
```
Do not expose a gateway to an untrusted network without token auth and a network
boundary you understand.
## Configuration Path
Use a specific config file:
```sh
opensquilla gateway run --config /path/to/opensquilla.toml
opensquilla gateway status --config /path/to/opensquilla.toml
```
OpenSquilla also reads standard configuration locations described in
[`configuration.md`](configuration.md).
## Remote Status Check
Inspect a gateway URL directly:
```sh
opensquilla gateway status --gateway ws://localhost:18791/ws
```
This is useful when a client or MCP bridge is configured with an explicit
gateway URL.
## When to Restart
Restart the gateway after changing:
- provider or router configuration;
- channel configuration;
- durable agent entries;
- global sandbox posture;
- search or image-generation setup;
- environment variables used by configured providers.
```sh
opensquilla gateway restart
```
## Troubleshooting
Check status and readiness:
```sh
opensquilla gateway status
opensquilla doctor
```
If the port is busy:
```sh
opensquilla gateway run --port 18792
```
If the Web UI cannot connect, confirm that the URL matches the gateway bind
host and port.
Read next:
- [`web-ui.md`](web-ui.md)
- [`configuration.md`](configuration.md)
- [`channels.md`](channels.md)
- [`troubleshooting.md`](troubleshooting.md)
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+134
View File
@@ -0,0 +1,134 @@
# Glossary
This glossary defines common OpenSquilla terms in user-facing language. It is
not a runtime design document.
## Agent
A named OpenSquilla identity with defaults such as model, workspace, name, and
description. The built-in `main` agent is always available.
Read: [`agents.md`](agents.md)
## Artifact
A file or media output produced by a run, such as an HTML page, report, image,
spreadsheet, PDF, or slide deck.
Read: [`artifacts-and-media.md`](artifacts-and-media.md)
## Approval
A human decision required before a sensitive tool action can continue. Approval
behavior depends on the surface, permission profile, and tool policy.
Read: [`approvals-and-permissions.md`](approvals-and-permissions.md)
## Channel
A messaging integration such as Telegram, Slack, Feishu/Lark, Discord, DingTalk,
WeCom, Matrix, terminal, or websocket-style clients.
Read: [`channels.md`](channels.md)
## Compaction
The process of reducing old context in a long session so the agent can continue
within the model's context budget.
Read: [`features/compaction-and-cache.md`](features/compaction-and-cache.md)
## Diagnostics
Runtime logging controls used to understand routing, provider behavior,
compaction, tool compression, cache behavior, and delivery failures.
Read: [`diagnostics-and-replay.md`](diagnostics-and-replay.md)
## Gateway
The local server behind the Web UI, channels, sessions, approvals, diagnostics,
usage, and RPC clients.
Read: [`gateway.md`](gateway.md)
## Memory
Durable user or project context that can be searched and recalled later without
stuffing every old transcript into the active prompt.
Read: [`features/memory.md`](features/memory.md)
## MetaSkill
A reusable, auditable workflow protocol that composes multiple skills, tools,
LLM calls, checks, or output steps into one repeatable capability.
Read: [`features/meta-skills.md`](features/meta-skills.md) and
[`features/meta-skill-user-guide.md`](features/meta-skill-user-guide.md)
## Permission Profile
The chosen tool-access posture for a run, such as `restricted`, `on`, `bypass`,
or `full`.
Read: [`approvals-and-permissions.md`](approvals-and-permissions.md)
## Provider
An LLM backend configured for OpenSquilla, such as TokenRhythm, OpenRouter,
OpenAI, Anthropic, Gemini, DeepSeek, DashScope, or Ollama.
Read: [`providers-and-models.md`](providers-and-models.md)
## Replay
A read-only view of a recorded turn from the decision log. Replay does not
re-run tools.
Read: [`diagnostics-and-replay.md`](diagnostics-and-replay.md)
## Scheduler
The `opensquilla cron` feature for recurring and one-time OpenSquilla runs.
Read: [`scheduling.md`](scheduling.md)
## Session
A durable conversation or task history. Sessions can be listed, resumed,
exported, aborted, or deleted.
Read: [`sessions.md`](sessions.md)
## Skill
A reusable package of task-specific guidance, scripts, or workflow instructions
that OpenSquilla can load when needed.
Read: [`features/skills.md`](features/skills.md)
## SquillaRouter
OpenSquilla's local routing layer for choosing an appropriate model tier per
turn.
Read: [`features/squilla-router.md`](features/squilla-router.md)
## Tool Compression
A context-saving feature that keeps large tool results useful while sending a
smaller preview to the model.
Read: [`features/tool-compression.md`](features/tool-compression.md)
## Workspace
The local directory a task is allowed or expected to work in. Workspace flags
help contain file and shell work.
Read: [`tools-and-sandbox.md`](tools-and-sandbox.md)
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+79
View File
@@ -0,0 +1,79 @@
# MCP Server Bridge
OpenSquilla can run as a stdio MCP server bridge for MCP-capable clients. Use
this when another local AI client should call into OpenSquilla session
workflows through the Model Context Protocol.
The MCP bridge is an integration surface. It is separate from OpenSquilla's Web
UI, CLI, channels, and gateway control console.
## Requirements
Install OpenSquilla with the MCP extra when you need this bridge:
```sh
uv tool install --python 3.12 "opensquilla[recommended,mcp] @ https://github.com/opensquilla/opensquilla/releases/download/v0.5.0rc3/opensquilla-0.5.0rc3-py3-none-any.whl"
```
Start the OpenSquilla gateway:
```sh
opensquilla gateway run
```
Or use the managed gateway:
```sh
opensquilla gateway start --json
opensquilla gateway status
```
## Run the Bridge
```sh
opensquilla mcp-server run
```
By default, the bridge connects to:
```text
ws://localhost:18791/ws
```
Use a different gateway:
```sh
opensquilla mcp-server run --gateway ws://localhost:18792/ws
```
The command runs a stdio MCP server. Configure your MCP-capable client to launch
that command as the server process.
## Safety Notes
- Keep the gateway bound to `127.0.0.1` unless you intentionally expose it.
- Do not put provider keys or channel secrets in MCP client config examples.
- Treat the MCP client as another tool-calling surface. The same OpenSquilla
permissions, tools, sessions, and gateway state still matter.
## Troubleshooting
If the bridge cannot start:
```sh
opensquilla gateway status
opensquilla doctor
```
If the command reports that MCP dependencies are missing, reinstall with the
`mcp` extra.
Read next:
- [`configuration.md`](configuration.md)
- [`tools-and-sandbox.md`](tools-and-sandbox.md)
- [`operations.md`](operations.md)
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+237
View File
@@ -0,0 +1,237 @@
# Operations
This guide covers day-two commands: sessions, cron, cost, diagnostics, replay,
migration, durable agents, MCP, and install inventory. Use it after the first
successful chat or gateway run.
## Sessions
Sessions are durable chat/task histories. Use them to resume, inspect, export,
or clean up prior work.
```sh
opensquilla sessions list
opensquilla sessions show <session-key>
opensquilla sessions resume <session-key>
opensquilla sessions export <session-key>
opensquilla sessions abort <session-key>
opensquilla sessions delete <session-key>
```
Use session export when exact old context matters or when you want to debug a
long-running task outside the chat UI.
For resume, abort, export, and cleanup workflows, see
[`sessions.md`](sessions.md).
## Durable Agents
OpenSquilla supports durable agent entries, including the built-in `main`
agent.
```sh
opensquilla agents list
opensquilla agents add research --name Research --workspace /path/to/research
opensquilla agents delete research
```
Use durable agents when you want separate workspaces, instructions, or tool
profiles for recurring roles. Restart the gateway after agent config changes.
Keep each durable agent's instructions focused on that role instead of turning
every agent into a copy of `main`.
For agent examples and concepts, see [`agents.md`](agents.md).
## Cron and Scheduled Runs
Cron jobs run OpenSquilla tasks on a schedule.
Inspect jobs:
```sh
opensquilla cron list
opensquilla cron status <job-id>
opensquilla cron runs <job-id>
```
Add a simple recurring reminder:
```sh
opensquilla cron add \
--every 1h \
--text "Check for urgent project updates and summarize them" \
--name hourly-project-check
```
Add a daily cron-style task:
```sh
opensquilla cron add \
--cron "0 9 * * 1-5" \
--tz "America/Los_Angeles" \
--text "Prepare my weekday morning briefing" \
--name weekday-briefing
```
Manage jobs:
```sh
opensquilla cron update <job-id> --enabled
opensquilla cron remove <job-id>
opensquilla cron run <job-id>
```
Good uses:
- morning briefings;
- recurring research digests;
- PR or CI checks;
- channel-delivered reminders;
- scheduled memory consolidation or reporting tasks.
Pair cron with channels when the output should be delivered somewhere other
than the local Web UI.
For scheduling examples, delivery options, and troubleshooting, see
[`scheduling.md`](scheduling.md).
## Cost and Usage
Inspect usage and estimated cost:
```sh
opensquilla cost
opensquilla cost --by-model
opensquilla cost --json
```
Use cost inspection after tool-heavy, routed, or long-context tasks to
understand actual runtime behavior.
For cost investigation workflow, see [`usage-and-cost.md`](usage-and-cost.md).
## Diagnostics
Diagnostics help explain runtime behavior without changing the core task.
```sh
opensquilla diagnostics status
opensquilla diagnostics on
opensquilla diagnostics off
```
Use diagnostics when investigating:
- provider retry behavior;
- router decisions;
- cache breaks;
- compaction events;
- tool-result compression;
- channel delivery failures.
Turn diagnostics off after collecting the needed evidence.
For diagnostics guidance and safe sharing notes, see
[`diagnostics-and-replay.md`](diagnostics-and-replay.md).
## Replay
Replay a recorded turn from the decision log:
```sh
opensquilla replay --session <session-key> --turn <turn-id>
```
Replay is useful for reproducing an agent turn, reviewing decision metadata, or
debugging behavior after the original chat has moved on.
## Migration
Preview first:
```sh
opensquilla migrate openclaw --json
opensquilla migrate hermes --json
```
Apply after reviewing the report:
```sh
opensquilla migrate openclaw --apply
opensquilla migrate hermes --apply
```
See [`../MIGRATION.md`](../MIGRATION.md) for custom paths and conflict
handling.
## MCP Server
OpenSquilla can run an MCP server bridge when installed with the `mcp` extra:
```sh
opensquilla mcp-server run
```
Install with:
```sh
uv tool install --python 3.12 "opensquilla[recommended,mcp] @ https://github.com/opensquilla/opensquilla/releases/download/v0.5.0rc3/opensquilla-0.5.0rc3-py3-none-any.whl"
```
Use this when another MCP-capable client should access OpenSquilla-managed tools
or runtime surfaces.
For setup details, see [`mcp-server.md`](mcp-server.md).
## Install Inventory
Emit a reproducible workspace-state inventory:
```sh
opensquilla dist
```
Use this for support, release QA, or environment comparison.
## Models
Inspect available models:
```sh
opensquilla models list
```
In this build, model inspection can be runtime-backed. If it cannot connect,
start the gateway first:
```sh
opensquilla gateway run
```
For provider catalog inspection that does not require a live gateway, use:
```sh
opensquilla providers list
```
Read: [`providers-and-models.md`](providers-and-models.md)
## Health Checklist
For a confusing install or runtime:
```sh
opensquilla doctor
opensquilla gateway status
opensquilla providers list
opensquilla search list
opensquilla channels types
opensquilla sandbox status
```
Then turn on diagnostics only if the basic health surfaces are not enough.
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+394
View File
@@ -0,0 +1,394 @@
# Providers and Models
OpenSquilla supports multiple LLM providers through one configuration surface.
You can run direct single-model mode or enable SquillaRouter for tiered routing.
Use this page when you need to configure a provider, inspect model support, or
choose between direct model mode and router mode.
## Inspect Providers
List provider metadata from the local install:
```sh
opensquilla providers list
opensquilla providers list --json
```
Show runtime provider diagnostics from the running gateway:
```sh
opensquilla providers status
opensquilla providers status openrouter --json
opensquilla providers status --probe-models
```
`providers list` does not require a running gateway. `providers status` does.
## Configure a Provider
Interactive:
```sh
opensquilla providers configure openrouter
```
Non-interactive onboarding-style configuration:
```sh
export OPENROUTER_API_KEY="sk-..."
opensquilla configure provider --provider openrouter --api-key-env OPENROUTER_API_KEY
```
Direct provider examples:
```sh
opensquilla configure provider --provider openai --model gpt-5.4-mini --api-key-env OPENAI_API_KEY
opensquilla configure provider --provider anthropic --model claude-sonnet-4-5 --api-key-env ANTHROPIC_API_KEY
opensquilla configure provider --provider gemini --model gemini-2.5-flash --api-key-env GEMINI_API_KEY
opensquilla configure provider --provider ollama --model llama3.1
```
Prefer environment-variable references for API keys so secrets are not written
directly into configuration files.
### Endpoint (base URL) resolution
`llm.base_url` resolves **explicit config → derived env var → provider
default**:
- A custom endpoint you saved (Web UI advanced options, `config.set`, or a
hand-written `base_url` in the TOML) always wins.
- If the config never chose an endpoint — no `base_url`, or the field still
holds the provider's own default URL — the derived environment variable
(`OPENAI_BASE_URL`, `OPENROUTER_BASE_URL`, `<PROVIDER>_BASE_URL`) applies.
This is the lever for pointing a whole fleet at a corporate proxy without
touching each config file.
- `OPENSQUILLA_LLM_BASE_URL` enters at config-model construction (the
`OPENSQUILLA_LLM_*` settings layer): it fills `base_url` whenever the TOML
does not set one, and the resolver then treats it as an explicit value —
so it beats the provider-derived vars above, while a `base_url` written in
the TOML still beats it.
API keys follow the same explicit-config-first rule via `api_key` /
`api_key_env`.
## Onboarding-Verified Providers
This build exposes onboarding support for:
- TokenRhythm
- OpenRouter
- OpenAI
- Anthropic
- Ollama
- DeepSeek
- Gemini
- DashScope / Qwen
- Moonshot AI
- Zhipu / Z.AI
- Baidu Qianfan
- Volcengine Ark
The provider registry may contain additional compatible providers for advanced
or self-hosted setups. Use `opensquilla providers list` on your install for the
current catalog.
### OpenAI: `openai` vs `openai_responses`
OpenAI is exposed as two provider ids that share the same `OPENAI_API_KEY` and
base URL (`https://api.openai.com/v1`):
- `openai` — the chat/completions request shape. Use this for standard
chat-style turns and broad tool compatibility.
- `openai_responses` — the native Responses-API shape (capabilities `chat` and
`responses`). Use this when you want Responses-API behavior rather than the
chat/completions surface.
Both read the same key and base URL, so switching between them needs only a
`provider` change.
### Volcengine Ark: regular vs coding-plan endpoints
Use `volcengine` for regular Ark chat/completions models. Its default base URL
is the OpenAI-compatible endpoint `https://ark.cn-beijing.volces.com/api/v3`.
Use `volcengine_coding_plan` for Volcengine's OpenAI Responses-compatible coding-plan
subscription surface. Its default base URL is
`https://ark.cn-beijing.volces.com/api/coding/v3`; OpenSquilla appends
`/responses` when it sends the request.
```sh
export VOLCENGINE_API_KEY="..."
opensquilla configure provider --provider volcengine_coding_plan --model <model> --api-key-env VOLCENGINE_API_KEY
```
Use `volcengine_coding_plan_anthropic` for tools or deployments that expect the
Anthropic Messages protocol. Its default base URL is
`https://ark.cn-beijing.volces.com/api/coding`; OpenSquilla appends
`/v1/messages`.
```sh
export VOLCENGINE_API_KEY="..."
opensquilla configure provider --provider volcengine_coding_plan_anthropic --model <model> --api-key-env VOLCENGINE_API_KEY
```
Do not point either coding-plan provider at the regular `/api/v3` URL. That
regular Ark URL does not consume Coding Plan quota.
### Tencent TokenHub: CN, Anthropic-protocol, and international endpoints
Tencent's Hunyuan `hy3` / `hy3-preview` models are served on the TokenHub
platform (the legacy `api.hunyuan.cloud.tencent.com` platform is being
retired and never received `hy3`). Three experimental provider ids map the
documented endpoints:
- `tencent_tokenhub` — OpenAI-compatible chat/completions at
`https://tokenhub.tencentmaas.com/v1` (mainland; keys from the CN TokenHub
console, `TENCENT_TOKENHUB_API_KEY`). `hy3` thinking uses
`reasoning_effort` `low`/`high`, and assistant `reasoning_content` is
replayed across turns as the hy3 interleaved-thinking contract requires.
- `tencent_tokenhub_anthropic` — the same deployment's Anthropic Messages
protocol (`https://tokenhub.tencentmaas.com` + `/v1/messages`,
`x-api-key` auth, same key).
- `tencent_tokenhub_intl` — the international deployment at
`https://tokenhub-intl.tencentcloudmaas.com/v1`
(`TENCENT_TOKENHUB_INTL_API_KEY`). It is a separate Tencent Cloud account
and key system, and its model list currently carries third-party models
(DeepSeek, GLM, Kimi, MiniMax) but not `hy3`.
```sh
export TENCENT_TOKENHUB_API_KEY="..."
opensquilla configure provider --provider tencent_tokenhub --model hy3 --api-key-env TENCENT_TOKENHUB_API_KEY
```
TokenHub also hosts third-party models behind the same endpoints; OpenSquilla
does not inject thinking payloads for those ids because TokenHub does not
document their dialects on this gateway.
Tencent's Token Plan subscription (the Hy Token Plan carries `hy3` /
`hy3-preview`; the General plan adds `tc-code-latest`, DeepSeek V4, GLM-5.x,
Kimi and MiniMax ids on the same key) is exposed as two more provider ids on
the plan host:
- `tencent_token_plan` — Chat Completions at
`https://api.lkeap.cloud.tencent.com/plan/v3` (the plan endpoints do not
offer the Responses API).
- `tencent_token_plan_anthropic` — Anthropic Messages at
`https://api.lkeap.cloud.tencent.com/plan/anthropic` (+ `/v1/messages`),
bearer auth.
Both read `TENCENT_TOKEN_PLAN_API_KEY`. Plan keys are dedicated `sk-tp-…`
credentials created on the TokenHub Token Plan console page — they are not
interchangeable with pay-as-you-go TokenHub keys. Note Tencent's plan terms
restrict these keys to interactive AI-tool use and prohibit non-interactive
batch/automation calling; unattended pipelines should use the pay-as-you-go
`tencent_tokenhub` provider instead. The plans are mainland-only products —
the international site offers pay-as-you-go TokenHub only.
## Model Inspection
List models:
```sh
opensquilla models list
```
If runtime-backed model inspection cannot connect, start the gateway:
```sh
opensquilla gateway run
```
For provider metadata that does not require the gateway, use:
```sh
opensquilla providers list
```
### Context-Window Resolution Order
Context budgeting, compaction thresholds, usage pressure reporting, and the
router's capability facts all resolve a model's context window through the
same layers, first match wins:
1. **Per-model override**`[models.<provider_id>."<model_id>"]`
`context_window` in your config. Set this for models the catalog does not
know (direct DashScope/TokenHub ids, self-hosted vLLM declaring its real
window) or to correct a wrong catalog value. Reported as source
`override` (`config` in `config.effective`, `model_override` in usage
context status).
2. **Global override**`llm.context_window_tokens` (0 = auto). A blunt
instrument that applies to whatever model is active; the per-model
override always beats it.
3. **Model catalog** — live OpenRouter data, the vendored models.dev
snapshot, then packaged corrections.
4. **Default** — a conservative 8,192 for local runtimes (match your actual
`num_ctx`/server window with an override), 200,000 otherwise.
The Web UI exposes the per-model override under Settings → Chat Model →
Advanced, with an auto-detected / override / effective readout.
## Direct Model vs Router
Direct model mode:
```sh
opensquilla configure router --router disabled
opensquilla configure provider --provider openai --model gpt-5.4-mini --api-key-env OPENAI_API_KEY
```
Router mode:
```sh
opensquilla configure router --router recommended
```
| Mode | Use when |
| --- | --- |
| Direct model | You are testing one exact model, reproducing provider behavior, or auditing provider billing. |
| Router mode | You want normal personal-agent use where cost and task complexity vary by turn. |
For routing details, see
[`features/squilla-router.md`](features/squilla-router.md).
## Pricing and Cost Estimation
OpenSquilla reports real provider-billed cost when a provider returns it, and
estimates cost locally from token usage everywhere else. Every usage row and
by-model breakdown item is labeled so you can tell which kind of number you
are looking at.
### How a Cost Is Estimated
Each priced call is split into four token buckets — fresh input, cache read,
cache write, output — and each bucket is priced at its own rate. The result
carries a `basis` label:
| Basis | Meaning |
| --- | --- |
| `cache_aware` | All buckets present in the call have a known rate; the four-bucket math ran. |
| `cache_blind` | The call used cache tokens but a needed cache rate is unknown, so OpenSquilla fell back to pricing every input token (cache or fresh) at the plain input rate. This is a conservative upper bound, not the real charge — expect it to overstate cost on cache-heavy sessions. |
| `free` | The model or runtime is zero-priced (see local runtimes below). |
### Price Resolution Order
For a given `(model, provider)` pair, OpenSquilla resolves a price through
these layers, first match wins:
1. **Local runtime**`ollama`, `lm_studio`, `ovms`, `vllm`, and `local` are
always free, regardless of model id.
2. **User override**`[models.<provider_id>."<model_id>"]` in your config
(see [`configuration.md`](configuration.md) and `opensquilla.toml.example`).
3. **Model catalog** — the vendored models.dev snapshot, including per-model
cache-read/cache-write rates where upstream publishes them.
4. **Live OpenRouter endpoint price** — looked up only when the provider is
`openrouter` or unset (first-party provider ids never query the OpenRouter
marketplace); falls back to the static table if OpenRouter is unreachable.
5. **Static table** — a built-in pricing table bundled with OpenSquilla.
6. **Default**`$3` / `$15` per million input/output tokens when nothing
else matched.
If OpenSquilla is estimating a model at the wrong price, add an override
instead of waiting for a catalog refresh:
```toml
[models.openrouter."z-ai/glm-5.2"]
input_cost_per_mtok = 0.5 # USD per million input tokens
output_cost_per_mtok = 2.0 # USD per million output tokens
cache_read_cost_per_mtok = 0.05 # USD per million cached-prompt-read tokens
cache_write_cost_per_mtok = 0.6 # USD per million cached-prompt-write tokens
```
Quote model ids that contain dots or slashes. All four fields are optional —
set only the ones you need to correct. `config.set`/`patch`/`apply` and
`opensquilla gateway reload` hot-apply these overrides; see
`opensquilla.toml.example` for more examples including self-hosted `vllm` and
`custom` endpoints.
### Cost Provenance (`costSource`)
Every usage row and by-model breakdown item carries a `costSource` (also
exposed dual-cased as `cost_source`):
| `costSource` | Meaning |
| --- | --- |
| `provider_billed` | The full cost came from a real provider-reported bill. |
| `opensquilla_estimate` | No billed cost was available; the figure is a local estimate. |
| `mixed` | The same model had both billed and unbilled calls in the aggregated row — the total is billed cost plus an estimate for the rest, not a pure bill. |
| `unavailable` | No pricing table entry and no billed cost, so no dollar figure could be produced. |
Rows also carry two additive fields: `estimateBasis` (the `cache_aware` /
`cache_blind` / `free` label above, present only when part of the row was
estimated) and `priceSource` (which resolver layer priced it — `user_override`,
`catalog`, `live_openrouter`, `static_table`, `default`, or `local_free`). The
Web UI's by-model usage cards show a small source chip for `costSource` and,
when the underlying basis is `cache_blind`, a hint that the figure is an
upper bound rather than the real cache-discounted cost.
### Which Providers Yield Billed vs. Estimated Cost
| Capability | Providers |
| --- | --- |
| Provider-billed cost | `openrouter` only |
| Cache-aware estimate possible | `anthropic`, `deepseek`, `minimax` (Anthropic-shaped), ensemble members |
| Cache-read-aware estimate only (no cache-write rate) | `openai`, `openai_responses`, `azure`, `gemini`, `openai_codex` |
| Cache-blind estimate (falls back to plain input-rate pricing when cache tokens appear) | other OpenAI-compatible provider kinds |
| Free | local runtimes (`ollama`, `lm_studio`, `ovms`, `vllm`, `local`) |
| Subscription (no invoice to compare against) | coding-plan/subscription provider kinds — treat any reported figure as an estimate, not a bill |
Use `opensquilla providers status --probe-models` and `opensquilla cost
--by-model` to see which class your configured provider/model falls into for
a given session.
### Turn and Router Budget Gates
Two per-turn agent budgets exist and behave differently:
- `max_turn_billed_cost_usd` gates only on real provider-billed cost. It is
inert (never trips) on providers or paths that never report billed cost —
do not rely on it alone outside `openrouter`.
- `max_turn_cost_usd` gates on the same accumulator used everywhere else in
this section: billed cost when the provider reports it, otherwise the
cache-aware/cache-blind estimate. It works on every provider. When it trips,
the error (`turn_cost_budget_exceeded`) states whether the total was billed,
estimated, or mixed.
SquillaRouter's session budget gate (`[squilla_router.budget]`, see
[`features/squilla-router.md`](features/squilla-router.md)) logs a
`spend_source` alongside each `router_budget.warn`/`router_budget.cap` event
and in the routing trail:
| `spend_source` | Meaning |
| --- | --- |
| `billed` | Accumulated spend is real provider-billed cost. |
| `estimate` | Accumulated spend is a local estimate for the whole session. |
| `estimate_mixed` | The session mixes billed and estimated cost. |
| `none` | No spend has been recorded yet. |
| `unknown` | Spend could not be determined; the gate suspends rather than acting on a guess. |
Read next: [`usage-and-cost.md`](usage-and-cost.md) for the `opensquilla cost`
CLI and how to read a session's usage rows.
## Provider Troubleshooting
Start with:
```sh
opensquilla doctor
opensquilla providers status
opensquilla diagnostics on
```
Check:
- the API key environment variable is set in the gateway process environment;
- the model id matches the provider;
- the base URL is correct for compatible APIs;
- proxy settings match your network;
- router is disabled when debugging one exact provider/model;
- the gateway was restarted after config changes.
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+229
View File
@@ -0,0 +1,229 @@
# Quickstart
This guide gets OpenSquilla installed, configured, and running locally. It
assumes you want the standard product experience: terminal commands, local Web
UI, SquillaRouter, memory/search support, and safe local defaults.
## Requirements
- Python 3.12 or newer for terminal installs.
- `uv` for the recommended terminal install.
- Git and Git LFS only when installing from source.
- A provider API key unless you use a local provider such as Ollama.
## Recommended Install
Install the current release wheel with the recommended extras:
```sh
uv tool install --python 3.12 "opensquilla[recommended] @ https://github.com/opensquilla/opensquilla/releases/download/v0.5.0rc3/opensquilla-0.5.0rc3-py3-none-any.whl"
```
The `recommended` extra includes SquillaRouter dependencies and memory/search
support used by the default product experience.
If `opensquilla` is not found after install, open a new shell or run:
```sh
uv tool update-shell
```
## First-Run Setup
Interactive setup:
```sh
opensquilla onboard
```
Script-friendly setup:
```sh
export OPENROUTER_API_KEY="sk-..."
opensquilla onboard --provider openrouter --api-key-env OPENROUTER_API_KEY
```
Useful variants:
```sh
opensquilla onboard --if-needed
opensquilla onboard --minimal
opensquilla onboard --provider openai --api-key-env OPENAI_API_KEY
opensquilla onboard --provider ollama --model llama3.1
```
`--if-needed` is safe for install scripts because it avoids rewriting an
already-ready setup. `--minimal` configures the provider path and skips optional
channels/search/image-generation sections.
Check onboarding state:
```sh
opensquilla onboard status
```
## Run the Gateway
Foreground gateway:
```sh
opensquilla gateway run
```
Background gateway with readiness wait:
```sh
opensquilla gateway start --json
opensquilla gateway status
```
Default address:
```text
http://127.0.0.1:18791/control/
```
The gateway defaults to loopback for safety. To bind elsewhere, opt in:
```sh
opensquilla gateway run --listen 0.0.0.0 --port 18791
```
Only expose a non-loopback gateway behind appropriate auth and network controls.
## First Useful Run
Open the Web UI:
```text
http://127.0.0.1:18791/control/
```
Start terminal chat:
```sh
opensquilla chat
```
Run one automation turn:
```sh
opensquilla agent -m "Inspect this workspace and suggest a test plan"
```
Run a one-shot task in a specific workspace:
```sh
opensquilla agent \
--workspace /path/to/project \
--workspace-strict \
-m "Review the current diff and list the highest-risk changes"
```
Use the Web UI for browser-based chat, approvals, setup, channels, usage, and
logs. Use `opensquilla chat` when you want a terminal conversation. Use
`opensquilla agent` for one-shot automation.
## Resume Work
Resume a terminal chat session:
```sh
opensquilla chat --session <session-key>
```
Inspect sessions:
```sh
opensquilla sessions list
opensquilla sessions show <session-key>
opensquilla sessions export <session-key>
```
Export a session when exact history matters for debugging or handoff.
## Check Readiness
Run these after setup:
```sh
opensquilla doctor
opensquilla providers list
opensquilla search list
opensquilla channels types --json
```
If the gateway is running, inspect runtime status:
```sh
opensquilla gateway status
opensquilla providers status
opensquilla channels status
opensquilla memory status
```
For provider/model selection details, see
[`providers-and-models.md`](providers-and-models.md). For search setup, see
[`search.md`](search.md).
For gateway lifecycle, host/port, and exposure guidance, see
[`gateway.md`](gateway.md).
## Stop or Restart
Foreground gateway:
```text
Ctrl+C
```
Managed background gateway:
```sh
opensquilla gateway stop
opensquilla gateway restart
```
## Next Steps
After the first run:
1. Configure search if you want web research:
[`search.md`](search.md).
2. Enable channels if you want Slack, Telegram, Feishu/Lark, or another
messaging surface: [`channels.md`](channels.md).
3. Review memory behavior if you want durable recall:
[`features/memory.md`](features/memory.md).
4. Review tool permissions before unattended automation:
[`tools-and-sandbox.md`](tools-and-sandbox.md).
5. Learn SquillaRouter if you want cost-aware model routing:
[`features/squilla-router.md`](features/squilla-router.md).
6. Use the glossary if product terms are unfamiliar:
[`glossary.md`](glossary.md).
## Install From Source
Use source install when you want a checkout-backed install:
```sh
git lfs install
git clone https://github.com/opensquilla/opensquilla.git
cd opensquilla
git lfs pull --include="src/opensquilla/squilla_router/models/**"
bash scripts/install_source.sh
```
For development, use the repository virtual environment:
```sh
uv sync --extra recommended --extra dev
uv run opensquilla --help
uv run opensquilla gateway run
```
When developing from source, prefix commands with `uv run` so they use the
checkout you are editing.
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+138
View File
@@ -0,0 +1,138 @@
# OpenSquilla 0.3.0
## Overview
Every agent workspace eventually grows little rituals: search this, inspect
that, ask for the missing detail, write the report, keep the useful trace.
0.3.0 is the release where OpenSquilla starts saving those rituals instead of
making you re-teach them every time.
OpenSquilla 0.3.0 brings MetaSkills into the product as reusable agent
workflows. It also adds a practical Health Doctor, stronger structured
tool-output compression, a real task-oriented documentation set, and a broad
round of runtime/WebUI fixes for long-running agent work.
## ✨ What's New
### MetaSkills: repeated work becomes a protocol
MetaSkills package repeatable multi-step work into reusable, inspectable
workflows. This release adds the runtime pieces needed to make them practical:
composition parsing, step scheduling, pause/resume user-input flows, run
history, proposal gates, bundled stable MetaSkills, and authoring docs.
Use this when a task is more than a single prompt: research-to-report,
document-to-decision, daily operating briefs, account watching, job-search
preparation, kid project planning, academic paper drafting, and creating new
workflow proposals. If a task has a shape you recognize, OpenSquilla can now
start treating that shape as reusable product behavior.
### Health Doctor: fewer mystery failures
`opensquilla doctor` and the WebUI Health view now turn runtime state into
actionable findings. Provider, gateway, memory, logs, search, image generation,
router, channels, sandbox, and embedding problems can now surface as concrete
readiness diagnostics with recovery commands instead of scattered manual
debugging. The goal is simple: when something is degraded, the product should
say what needs attention.
### Structured Tool Compression: noisy tools, cleaner context
Tool-heavy sessions are less likely to drown the model in raw output. The new
Tokenjuice-backed projection path compacts large logs, diffs, JSON, test output,
package-manager output, and other known tool shapes before they reach provider
context, while OpenSquilla keeps runtime-side evidence and projection telemetry
available for inspection.
### Product Documentation: finally, a map
The repository now includes a real task-oriented docs set: quickstart,
configuration, CLI, WebUI, providers, sessions, tools and sandboxing, usage and
cost, memory, compaction, MetaSkills, tool compression, scheduling, channels,
MCP, troubleshooting, and contribution guidance.
## 🛠 Fixed
### Long Sessions and Compaction
Long-session memory and compaction flows now preserve raw archive evidence,
checkpoint receipts, repair queues, and WebUI-safe status. Context safety,
semantic memory quality, and repair work are reported as separate signals.
### WebUI Chat and Artifacts
WebChat fixes cover router replay, session restore gaps, duplicate compaction
status, attachment and pasted-text rendering, artifact downloads, composer
layout, model-router animation timing, and visible recovery during long turns.
### Runtime and Provider Handling
Provider/runtime hardening reduces malformed tool-call fallout, preserves
configured model-switch intent, handles provider tool-choice requirements, and
keeps oversized current-turn tool payloads from surfacing as bare internal
failures.
### Cross-Platform Reliability
CLI help rendering, sqlite fallback behavior, UTF-8 subprocess handling,
Windows-only test fixtures, onboarding commands, and release-surface checks are
more portable across supported platforms.
## Downloads
- Python wheel: `opensquilla-0.3.0-py3-none-any.whl`
- Windows portable: `OpenSquilla-0.3.0-windows-x64-py312-recommended-portable.zip`
- Stable Windows portable alias: `OpenSquilla-windows-x64-portable.zip`
- Checksums: `SHA256SUMS`
Linux and macOS users should install the Python wheel with `uv tool install`.
Windows users can use either the wheel or the portable zip.
The stable Windows portable alias contains the same build as the versioned
portable zip, but keeps a fixed filename for scripts and docs.
## Upgrading from 0.2.1
If OpenSquilla was installed with `uv tool install`, reinstall 0.3.0 over the
existing tool environment:
```sh
uv tool install --python 3.12 --force --reinstall-package opensquilla \
"opensquilla[recommended] @ https://github.com/opensquilla/opensquilla/releases/download/v0.3.0/opensquilla-0.3.0-py3-none-any.whl"
```
The release installers use the same forced reinstall path. Close any running
OpenSquilla gateway before upgrading, then restart it after the install. Existing
`~/.opensquilla/config.toml` and session data are reused; legacy
`agent_token_saving.tool_result_compression_*` settings are ignored or migrated
because Tokenjuice projection is now the built-in tool-result path.
Windows portable users should extract the 0.3.0 zip to a fresh folder, or replace
the whole extracted 0.2.1 folder while the gateway is stopped. Do not copy only
individual files from the new zip into an old portable tree.
## Acknowledgements
Thanks @ab2ence for #56, #61, #81, #88, and #109, which helped bring
Tokenjuice-backed tool compression, canonical tool-result projection, memory
dream consolidation, chat streaming restore work, and cross-platform release
gate hardening into OpenSquilla.
Thanks @lose4578 for submitting #80, and thanks cwan0785
(@Anonymous-4427 on GitHub) for authoring the TUI
backend/runtime extraction commits behind that pull request.
Thanks @nice-code-la for #82, #93, #96, #110, #114 (replayed through #115),
and #119, which helped preserve router model-switch intent, harden
router/MetaSkill execution, and mature the retained high-value MetaSkill
workflows.
Thanks @openvictory for #116, which fixed UTF-8 migration loading for yoyo
migrations and helped keep the release gates aligned on Windows.
OpenSquilla's Tokenjuice-backed projection includes a Python adaptation of
rule-driven reduction ideas and bundled rules derived from
[vincentkoc/tokenjuice](https://github.com/vincentkoc/tokenjuice),
redistributed under the MIT license. See `THIRD_PARTY_NOTICES.md` and
`src/opensquilla/plugins/tokenjuice/PROVENANCE.md` for provenance details.
+92
View File
@@ -0,0 +1,92 @@
# OpenSquilla 0.3.1
## Overview
OpenSquilla 0.3.1 is a maintenance release for the 0.3 line. It updates the
stable install path while bringing the most user-visible fixes from the
integration branch onto the release line.
The release focuses on making day-to-day use less fragile: chat messages render
as authored, Slack channel setup and replies keep the context they need, media
and voice workflow handoffs are easier to continue, and invalid provider or
release states are caught earlier.
## 🛠 Fixed
### Chat and channel replies keep their context
WebChat now preserves multiline user messages and gives authored messages more
readable spacing. Slack setup and reply paths also keep more of the context they
need, including Socket Mode and app-mention setup, signing-secret checks,
existing-secret preservation, and thread/channel metadata for replies.
### Workflow handoffs recover more cleanly
Voice/audio, media helper, and MetaSkill clarification handoffs are now on the
stable release line. The bundled short-drama and video helper workflows remain
available, with Windows-safe script handling and review pauses so generated
workflow output is easier to inspect before continuing.
### Provider and release checks fail earlier
Malformed tool-call history is kept away from providers before it becomes an
invalid request. PR CI also classifies changed files by impact surface, so docs,
runtime, dependency, release, and test changes can trigger the checks they need
without forcing unnecessary work for every pull request.
## Changed
- Release installer defaults now point to `v0.3.1`.
- README, quickstart, MCP, and operations docs now use the 0.3.1 wheel URL.
- `pyproject.toml`, `uv.lock`, release consistency tests, and install-script
tests now agree on version `0.3.1`.
- `docs/releases/0.3.1.md` records the GitHub Release body used for this release.
## Downloads
- Python wheel: `opensquilla-0.3.1-py3-none-any.whl`
- Windows portable: `OpenSquilla-0.3.1-windows-x64-py312-recommended-portable.zip`
- Stable Windows portable alias: `OpenSquilla-windows-x64-portable.zip`
- Checksums: `SHA256SUMS`
Linux and macOS users should install the Python wheel with `uv tool install`.
Windows users can use either the wheel or the portable zip.
The stable Windows portable alias contains the same build as the versioned
portable zip, but keeps a fixed filename for scripts and docs.
## Upgrading from 0.3.0
If OpenSquilla was installed with `uv tool install`, reinstall 0.3.1 over the
existing tool environment:
```sh
uv tool install --python 3.12 --force --reinstall-package opensquilla \
"opensquilla[recommended] @ https://github.com/opensquilla/opensquilla/releases/download/v0.3.1/opensquilla-0.3.1-py3-none-any.whl"
```
The release installers use the same forced reinstall path. Close any running
OpenSquilla gateway before upgrading, then restart it after the install.
Existing `~/.opensquilla/config.toml` and session data are reused.
Windows portable users should extract the 0.3.1 zip to a fresh folder, or
replace the whole extracted 0.3.0 folder while the gateway is stopped. Do not
copy only individual files from the new zip into an old portable tree.
## Acknowledgements
Thanks @openvictory for #123, #133, and #137, which helped bring visible
running-state feedback plus short-drama and media helper workflows into the
0.3.1 release line.
Thanks @freeaccount-create for #142, which helped bring Slack Socket Mode and
self-targeting replies into the channel workflow.
Thanks @ruhook for #124, and thanks @qq712696307 for the authored commit in
that pull request, which preserved user message newlines in WebChat.
Thanks @Cola-Alex for #143, which increased tokenjuice summarize and
failure-context windows for fallback tool-result projection.
Thanks @nice-code-la for #165 and #166, which helped make voice workflows usable
end to end and clarification pauses resume cleanly.
+150
View File
@@ -0,0 +1,150 @@
# OpenSquilla 0.4.0
## Overview
OpenSquilla 0.4.0 is the first release with desktop installers for the Vue
control console. It keeps the Python wheel and legacy Windows portable paths
available, while making the desktop app the clearest install path for macOS and
Windows users who want the packaged control UI.
The release also updates the daily control surfaces, workflow launch model,
coding workflow, search providers, terminal preview path, and runtime
hardening. Existing gateway and data locations stay the same, so users can
upgrade without migrating their `~/.opensquilla` state.
## ✨ What's New
### Desktop installers for the Control UI
The release now includes a macOS Apple Silicon installer and a Windows x64 NSIS
installer for the Electron desktop shell. Both packages embed the built Vue
control UI and the packaged gateway runtime.
### Coding mode and guarded code-task workflow
Coding mode gives source-editing work a clearer product lane. The
`opensquilla code-task` workflow routes generated or edited code through
isolated run directories, trusted-host confirmation, separated build output,
and verification before source persistence. This keeps coding tasks easier to
inspect and safer to continue from the Control UI.
### Manual MetaSkills and workflow launch control
MetaSkills are manual-only by default. Use `/meta` to list workflows and
`/meta <name>` to run one; set `meta_skill.auto_trigger = true` only when the
older automatic behavior is intentional. MetaSkill progress, clarification,
run-history reads, and rescue-action surfaces are clearer in the Control UI.
### Control UI, sessions, and daily workflow polish
The refreshed browser console centers everyday work around conversation state,
session inspection, Settings, artifact previews, share export, deliverables,
turn trace, mobile tabs, and clearer Skills, Usage, Cron, Logs, and Approvals
surfaces.
### Search, providers, and runtime hardening
DuckDuckGo, Bocha, Brave, Tavily, and Exa are now documented as runtime search
providers, with `web_search` for source-backed answers and `web_discover` for
lightweight discovery. The release also adds the `openai_responses` provider
shape and hardens provider stream parsing, Gemini thought-signature replay,
SSRF fake-IP DNS guidance, session recovery, artifact handling, and approval
event delivery.
## Downloads
Recommended desktop downloads:
- macOS desktop installer: `OpenSquilla-0.4.0-mac-arm64.dmg`
- Windows desktop installer: `OpenSquilla-0.4.0-win-x64.exe`
Code signing policy: [`docs/code-signing-policy.md`](https://github.com/opensquilla/opensquilla/blob/7353f2795aa2e77aa408c3e8a9150dd7efbd80d0/docs/code-signing-policy.md).
Terminal and automation downloads:
- Python wheel: `opensquilla-0.4.0-py3-none-any.whl`
- Checksums: `SHA256SUMS`
Legacy compatibility downloads:
- Legacy Windows portable, versioned: `OpenSquilla-0.4.0-windows-x64-py312-recommended-portable.zip`
- Legacy Windows portable, stable alias: `OpenSquilla-windows-x64-portable.zip`
The legacy Windows portable assets remain available as legacy compatibility
downloads for existing scripts and portable-folder workflows. New Windows
desktop users should prefer `OpenSquilla-0.4.0-win-x64.exe`.
Privacy and third-party attribution are documented in
[`PRIVACY.md`](https://github.com/opensquilla/opensquilla/blob/7353f2795aa2e77aa408c3e8a9150dd7efbd80d0/PRIVACY.md) and
[`THIRD_PARTY_NOTICES.md`](https://github.com/opensquilla/opensquilla/blob/v0.4.0/THIRD_PARTY_NOTICES.md).
Updater metadata:
- `latest-mac.yml`
- `latest.yml`
- `*.blockmap`
## Upgrading from 0.3.1
If OpenSquilla was installed with `uv tool install`, reinstall 0.4.0 over the
existing tool environment:
```sh
uv tool install --python 3.12 --force --reinstall-package opensquilla \
"opensquilla[recommended] @ https://github.com/opensquilla/opensquilla/releases/download/v0.4.0/opensquilla-0.4.0-py3-none-any.whl"
```
The release installers use the same forced reinstall path. Close any running
OpenSquilla gateway before upgrading, then restart it after the install.
Existing `~/.opensquilla/config.toml` and session data are reused.
Desktop users should quit the running desktop app before replacing it. macOS
users install the `.dmg` by dragging OpenSquilla into Applications. Windows
users run the `.exe` installer.
Legacy Windows portable users should extract the 0.4.0 portable zip to a fresh
folder, or replace the whole extracted 0.3.x folder while the gateway is
stopped. Do not copy only individual files from the new zip into an old
portable tree.
## Acknowledgements
Thanks to the contributors whose pull-request work is present in the current
0.4.0 release surface:
- [@ab2ence](https://github.com/ab2ence) for Control UI migration and
stabilization, share-image export, Web Chat slash-input handling, bundled
AwesomeWebpage MetaSkill work, the Coding mode toggle, and desktop gateway
startup plus install telemetry hardening.
- [@myz-ah](https://github.com/myz-ah) for the guarded `code-task` workflow and
Web UI LaTeX formula rendering.
- [@nice-code-la](https://github.com/nice-code-la) for Skills readiness,
MetaSkill progress and clarification UX, manual `/meta` behavior, scoped
MetaSkill run-history reads, router fallback/default refresh work, image
follow-up routing gates, from-scratch `code-task` build support, and
MetaSkill clarify resume feedback.
- [@openvictory](https://github.com/openvictory) for MetaSkill run-history and
rescue-action Control UI work carried through the session-contract Control UI
integration, plus Skill API-key fallback behavior.
- [@Liu-RK](https://github.com/Liu-RK) for sandbox run-mode and managed
access-control work across Windows and Linux.
- [@weiconghe](https://github.com/weiconghe) for Gemini thought-signature
replay across provider tool-call turns.
- [@changquanyou](https://github.com/changquanyou) for no-space SSE `data:`
handling and managed-layer MetaSkill inspection.
- [@nkgotcode](https://github.com/nkgotcode) for DOCX `skill_exec` export
behavior.
- [@C1-BA-B1-F3](https://github.com/C1-BA-B1-F3) for actionable SSRF fake-IP
DNS failure guidance.
- [@BlueOcean223](https://github.com/BlueOcean223) for TUI EOF-state recovery
on cached reentry.
- [@szdtzpj](https://github.com/szdtzpj) for environment test precedence and
the TUI abort hook.
- [@lose4578](https://github.com/lose4578) for OpenTUI scrollback-native
frontend work carried into the 0.4.0 preview backend.
- cwan0785 ([@Anonymous-4427](https://github.com/Anonymous-4427)) for OpenTUI
preview backend implementation commits carried into the 0.4.0 preview
backend.
See [`CONTRIBUTORS.md`](https://github.com/opensquilla/opensquilla/blob/v0.4.0/CONTRIBUTORS.md)
for the full 0.4.0 attribution ledger and PR evidence.
+128
View File
@@ -0,0 +1,128 @@
# OpenSquilla 0.4.1
## Overview
OpenSquilla 0.4.1 is a maintenance release for the 0.4 desktop and Control UI
line. It focuses on packaged desktop reliability, Web UI recovery, Coding mode
and SquillaRouter packaging, installer telemetry accuracy, and the project move
to `main` as the active development branch.
Existing gateway configuration and session data stay in place. Users upgrading
from 0.4.0 should close any running desktop app or gateway process, install the
0.4.1 package, and restart OpenSquilla.
## ✨ What's Improved
### 🖥️ Desktop and Coding mode reliability
The desktop package now fails fast when SquillaRouter model assets are missing
or still Git LFS pointer files, and packaged gateway smoke checks cover
`code-task`, Coding mode support, and router startup before release assets are
published. Windows desktop cleanup wording and active-window reload behavior are
also tightened.
### 🌐 Multilingual Control UI and client
The Control UI and desktop client now support English, Simplified Chinese,
Japanese, French, German, and Spanish across first-paint desktop boot text,
settings surfaces, connection state, and persisted language selection.
### 🧰 Telemetry, icons, and user-facing polish
Install telemetry now skips GitHub Actions, pytest, and explicit test
environments before creating telemetry state or uploading events. The Windows
Electron app, installer, and uninstaller use the OpenSquilla logo. Web UI fixes
improve streaming recovery, stale task isolation, settings restore behavior,
session deletion, topbar layout, status line breaks, and HTML artifact opening
from the desktop app.
Non-user-initiated network observability can be disabled before startup with
`OPENSQUILLA_PRIVACY_DISABLE_NETWORK_OBSERVABILITY=true` or:
```toml
[privacy]
disable_network_observability = true
```
That unified switch covers automatic install telemetry, passive update checks,
and desktop startup auto-update checks. The legacy compatibility environment
variables `OPENSQUILLA_TELEMETRY_DISABLED=true` and
`OPENSQUILLA_UPDATE_CHECK_DISABLED=true` remain honored; manual
user-initiated release, download, or update checks may still contact GitHub
after user intent.
### 🧭 Providers, router labels, and mainline governance
Provider profile fixes cover Volcengine and BytePlus, macOS router runtime
diagnostics are clearer, and model request logs expose router target labels.
OpenSquilla now treats `main` as the ordinary development and integration
branch; maintainer collaboration branches remain available for release,
hotfix, staging, integration, and sandbox work.
## Downloads
🖥️ Recommended desktop downloads:
- macOS desktop installer: `OpenSquilla-0.4.1-mac-arm64.dmg`
- macOS desktop zip: `OpenSquilla-0.4.1-mac-arm64.zip`
- Windows desktop installer: `OpenSquilla-0.4.1-win-x64.exe`
Code signing policy: [`docs/code-signing-policy.md`](https://github.com/opensquilla/opensquilla/blob/7353f2795aa2e77aa408c3e8a9150dd7efbd80d0/docs/code-signing-policy.md).
⚙️ Terminal and automation downloads:
- Python wheel: `opensquilla-0.4.1-py3-none-any.whl`
- Checksums: `SHA256SUMS`
🧳 Legacy compatibility downloads:
- Legacy Windows portable, versioned: `OpenSquilla-0.4.1-windows-x64-py312-recommended-portable.zip`
- Legacy Windows portable, stable alias: `OpenSquilla-windows-x64-portable.zip`
The legacy Windows portable assets remain available as legacy compatibility
downloads for existing scripts and portable-folder workflows. New Windows
desktop users should prefer `OpenSquilla-0.4.1-win-x64.exe`.
Privacy and third-party attribution are documented in
[`PRIVACY.md`](https://github.com/opensquilla/opensquilla/blob/7353f2795aa2e77aa408c3e8a9150dd7efbd80d0/PRIVACY.md) and
[`THIRD_PARTY_NOTICES.md`](https://github.com/opensquilla/opensquilla/blob/v0.4.1/THIRD_PARTY_NOTICES.md).
🔄 Updater metadata:
- `latest-mac.yml`
- `latest.yml`
- `*.blockmap`
## Upgrading from 0.4.0
If OpenSquilla was installed with `uv tool install`, reinstall 0.4.1 over the
existing tool environment:
```sh
uv tool install --python 3.12 --force --reinstall-package opensquilla \
"opensquilla[recommended] @ https://github.com/opensquilla/opensquilla/releases/download/v0.4.1/opensquilla-0.4.1-py3-none-any.whl"
```
The release installers use the same forced reinstall path. Close any running
OpenSquilla gateway or desktop app before upgrading, then restart it after the
install. Existing `~/.opensquilla/config.toml` and session data are reused.
Desktop users should quit the running desktop app before replacing it. macOS
users install the `.dmg` by dragging OpenSquilla into Applications. Windows
users run the `.exe` installer.
Legacy Windows portable users should extract the 0.4.1 portable zip to a fresh
folder, or replace the whole extracted 0.4.0 folder while the gateway is
stopped. Do not copy only individual files from the new zip into an old
portable tree.
## Acknowledgements
Thanks to the contributors whose pull-request work is newly present in the
0.4.1 release surface:
- [@ab2ence](https://github.com/ab2ence) for install telemetry CI/test
environment skipping and desktop HTML artifact native-open support.
See [`CONTRIBUTORS.md`](https://github.com/opensquilla/opensquilla/blob/v0.4.1/CONTRIBUTORS.md)
for the full attribution ledger and PR evidence.
+132
View File
@@ -0,0 +1,132 @@
# OpenSquilla 0.5.0 Preview 1
## Overview
OpenSquilla 0.5.0 Preview 1 is a preview release for the next routing and
managed-execution line. The headline feature is dynamic Model Ensemble routing:
OpenSquilla can route across multiple candidate models, progressively reveal
results, and still fall back to direct single-model defaults when that is the
better fit. The second major theme is sandbox and managed-execution alignment,
followed by Control UI polish, OpenTUI preview reliability, and Windows/runtime
cleanup.
Existing gateway configuration and session data stay in place. Users upgrading
from 0.4.1 should close any running desktop app or gateway process, install the
0.5.0 Preview 1 package, and restart OpenSquilla.
## What's Improved
### Model Ensemble and smarter provider routing
Dynamic Model Ensemble routing is a first-class preview feature: OpenSquilla
can route across multiple candidate models, progressively reveal results, and
fall back to direct single-model defaults when that is the better fit.
OpenAI-compatible and Codex-oriented provider paths are easier to select,
inspect, and combine with router timeout tuning and clearer target labels for
model requests.
### Managed execution and sandbox alignment
Sandbox run modes, approval boundaries, and managed host execution now share
clearer authorization behavior and diagnostics. This preview also tightens
gateway lifecycle conflict reporting and cross-platform subprocess handling.
### Desktop and Control UI polish
The desktop app and Control UI improve router/provider settings, drag-and-drop
attachments, history materialization, image preview navigation, settings
restore, refreshed-session recovery, and package runtime checks.
### OpenTUI preview and terminal reliability
OpenTUI preview work continues with stronger terminal behavior, while Windows
process cleanup, GBK/UTF-8 subprocess handling, pidlock behavior, and gateway
runtime diagnostics are more predictable.
Non-user-initiated network observability can be disabled before startup with
`OPENSQUILLA_PRIVACY_DISABLE_NETWORK_OBSERVABILITY=true` or:
```toml
[privacy]
disable_network_observability = true
```
That unified switch covers automatic install telemetry, passive update checks,
and desktop startup auto-update checks. The legacy compatibility environment
variables `OPENSQUILLA_TELEMETRY_DISABLED=true` and
`OPENSQUILLA_UPDATE_CHECK_DISABLED=true` remain honored; manual user-initiated
release, download, or update checks may still contact GitHub after user intent.
## Downloads
Recommended desktop downloads:
- macOS desktop installer: `OpenSquilla-0.5.0-rc1-mac-arm64.dmg`
- macOS desktop zip: `OpenSquilla-0.5.0-rc1-mac-arm64.zip`
- Windows desktop installer: `OpenSquilla-0.5.0-rc1-win-x64.exe`
Code signing policy: [`docs/code-signing-policy.md`](https://github.com/opensquilla/opensquilla/blob/v0.5.0rc1/docs/code-signing-policy.md).
Terminal and automation downloads:
- Python wheel: `opensquilla-0.5.0rc1-py3-none-any.whl`
- Checksums: `SHA256SUMS`
No Windows portable assets are published for 0.5.0 preview releases. Existing
0.4.x portable downloads remain available on their original release pages for
legacy scripts and portable-folder workflows. New Windows users should use the
Electron installer or the terminal wheel install path.
Privacy and third-party attribution are documented in
[`PRIVACY.md`](https://github.com/opensquilla/opensquilla/blob/v0.5.0rc1/PRIVACY.md) and
[`THIRD_PARTY_NOTICES.md`](https://github.com/opensquilla/opensquilla/blob/v0.5.0rc1/THIRD_PARTY_NOTICES.md).
Updater metadata:
- `latest-mac.yml`
- `latest.yml`
- `*.blockmap`
## Upgrading from 0.4.1
If OpenSquilla was installed with `uv tool install`, reinstall 0.5.0 Preview 1
over the existing tool environment:
```sh
uv tool install --python 3.12 --force --reinstall-package opensquilla \
"opensquilla[recommended] @ https://github.com/opensquilla/opensquilla/releases/download/v0.5.0rc1/opensquilla-0.5.0rc1-py3-none-any.whl"
```
The release installers use the same forced reinstall path. Close any running
OpenSquilla gateway or desktop app before upgrading, then restart it after the
install. Existing `~/.opensquilla/config.toml` and session data are reused.
Desktop users should quit the running desktop app before replacing it. macOS
users install the `.dmg` by dragging OpenSquilla into Applications, ejecting
the mounted DMG, and opening the Applications copy. If the Dock icon keeps
bouncing or startup reports a busy/translocated app, force quit any old
OpenSquilla process, eject the DMG, and reopen OpenSquilla. Windows users run
the `.exe` installer.
Legacy Windows portable users should switch to the Windows Electron installer
or terminal wheel install path for 0.5.0 previews. Do not expect a new
0.5.0rc1 portable zip or `/releases/latest/download/` portable alias.
## Acknowledgements
Thanks to the contributors whose work is newly present in the 0.5.0 Preview 1
release surface:
- [@ab2ence](https://github.com/ab2ence) for drag-and-drop attachment work,
dynamic Model Ensemble routing, and ensemble timeout tuning.
- [@Liu-RK](https://github.com/Liu-RK) for sandbox authorization alignment and
managed execution host routing.
- [@TUOXI293](https://github.com/TUOXI293), a first-time OpenSquilla release
contributor, for image preview navigation.
- [@tqangxl](https://github.com/tqangxl), a first-time OpenSquilla release contributor,
for gateway lifecycle conflict diagnostics and SQLAlchemy core dependency work.
- [@HuaXiawithMoon](https://github.com/HuaXiawithMoon), a first-time OpenSquilla
release contributor, for WeCom AI Bot websocket mode work.
See [`CONTRIBUTORS.md`](https://github.com/opensquilla/opensquilla/blob/v0.5.0rc1/CONTRIBUTORS.md)
for the full attribution ledger and PR/commit evidence.
+128
View File
@@ -0,0 +1,128 @@
# OpenSquilla 0.5.0 Preview 2
## Overview
OpenSquilla 0.5.0 Preview 2 is a preview maintenance release for the 0.5
routing and desktop/runtime line. It keeps the default path on the
single-model `squilla_router`, while the front-end ensemble toggle still
defaults enabled ensemble sessions to the packaged `static_openrouter_b5`
profile. This preview focuses on provider/router recovery, Web UI upload
refresh, desktop and session stability, and CI contract repair before the next
0.5 release candidate.
Existing gateway configuration and session data stay in place. Users upgrading
from 0.4.1 or 0.5.0 Preview 1 should close any running desktop app or gateway
process, install the 0.5.0 Preview 2 package, and restart OpenSquilla.
## What's Improved
### Model Ensemble and provider routing
Provider and router settings are easier to recover and inspect across the Web
UI, desktop onboarding, config provenance RPCs, and the provider catalog. Fresh
installs continue to use the direct single-model router path by default. Users
who explicitly enable ensemble mode get the static OpenRouter B5 profile as the
default ensemble selection, with doctor and timeout checks scoped to that
opt-in path.
### Managed execution and sandbox alignment
Cancelled turns, sandbox denial resume recovery, approval grant behavior, and
bounded code-task verification have tighter rollback and recovery behavior.
The `code-task` build scaffold now stays non-interactive by using the scaffold
package's supported skip flag.
### Desktop and Control UI polish
The desktop app and Control UI improve local HTML artifact opening, desktop
reopen behavior, session deletion, attachment isolation, composer draft
persistence, refreshed-session recovery, empty states, voice readiness, and
ensemble progress trace display.
### Web UI uploads and runtime contracts
Expired or near-expired staged uploads refresh their file UUIDs before send
when the original local file is still available. The Preview 2 branch also
repairs main CI contract drift around onboarding status fields, router mode
classification, migration/provider persistence, and static-B5 doctor coverage.
Non-user-initiated network observability can be disabled before startup with
`OPENSQUILLA_PRIVACY_DISABLE_NETWORK_OBSERVABILITY=true` or:
```toml
[privacy]
disable_network_observability = true
```
That unified switch covers automatic install telemetry, passive update checks,
and desktop startup auto-update checks. The legacy compatibility environment
variables `OPENSQUILLA_TELEMETRY_DISABLED=true` and
`OPENSQUILLA_UPDATE_CHECK_DISABLED=true` remain honored; manual user-initiated
release, download, or update checks may still contact GitHub after user intent.
## Downloads
Recommended desktop downloads:
- macOS desktop installer: `OpenSquilla-0.5.0-rc2-mac-arm64.dmg`
- macOS desktop zip: `OpenSquilla-0.5.0-rc2-mac-arm64.zip`
- Windows desktop installer: `OpenSquilla-0.5.0-rc2-win-x64.exe`
Code signing policy: [`docs/code-signing-policy.md`](https://github.com/opensquilla/opensquilla/blob/v0.5.0rc2/docs/code-signing-policy.md).
Terminal and automation downloads:
- Python wheel: `opensquilla-0.5.0rc2-py3-none-any.whl`
- Checksums: `SHA256SUMS`
No Windows portable assets are published for 0.5.0 preview releases. Existing
0.4.x portable downloads remain available on their original release pages for
legacy scripts and portable-folder workflows. New Windows users should use the
Electron installer or the terminal wheel install path. Do not expect a new
0.5.0rc2 portable zip or `/releases/latest/download/` portable alias.
Privacy and third-party attribution are documented in
[`PRIVACY.md`](https://github.com/opensquilla/opensquilla/blob/v0.5.0rc2/PRIVACY.md) and
[`THIRD_PARTY_NOTICES.md`](https://github.com/opensquilla/opensquilla/blob/v0.5.0rc2/THIRD_PARTY_NOTICES.md).
Updater metadata:
- `latest-mac.yml`
- `latest.yml`
- `*.blockmap`
## Upgrading from 0.4.1
If OpenSquilla was installed with `uv tool install`, reinstall 0.5.0 Preview 2
over the existing tool environment:
```sh
uv tool install --python 3.12 --force --reinstall-package opensquilla \
"opensquilla[recommended] @ https://github.com/opensquilla/opensquilla/releases/download/v0.5.0rc2/opensquilla-0.5.0rc2-py3-none-any.whl"
```
The release installers use the same forced reinstall path. Close any running
OpenSquilla gateway or desktop app before upgrading, then restart it after the
install. Existing `~/.opensquilla/config.toml` and session data are reused.
Desktop users should quit the running desktop app before replacing it. macOS
users install the `.dmg` by dragging OpenSquilla into Applications, ejecting
the mounted DMG, and opening the Applications copy. If the Dock icon keeps
bouncing or startup reports a busy/translocated app, force quit any old
OpenSquilla process, eject the DMG, and reopen OpenSquilla. Windows users run
the `.exe` installer.
Legacy Windows portable users should switch to the Windows Electron installer
or terminal wheel install path for 0.5.0 previews. Do not expect a new
0.5.0rc2 portable zip or `/releases/latest/download/` portable alias.
## Acknowledgements
Thanks to the contributor whose work is newly present in the 0.5.0 Preview 2
release surface:
- [@HuaXiawithMoon](https://github.com/HuaXiawithMoon) for keeping `code-task`
build scaffolding non-interactive.
See [`CONTRIBUTORS.md`](https://github.com/opensquilla/opensquilla/blob/v0.5.0rc2/CONTRIBUTORS.md)
for the full attribution ledger and PR/commit evidence.
+227
View File
@@ -0,0 +1,227 @@
# OpenSquilla 0.5.0 Preview 3
## Overview
OpenSquilla 0.5.0 Preview 3 is a broad preview release for the 0.5 runtime,
desktop, routing, and deployment line. It adds a transactional migration path
for older OpenSquilla homes, expands provider and router choices, strengthens
the shared agent runtime, refreshes the terminal and Control UI experiences,
and introduces prebuilt multi-architecture container images.
Existing CLI and desktop configuration remains in place when it already lives
in the active OpenSquilla home. Retired Windows portable homes and other legacy
or relocated homes can now be discovered, previewed, and imported explicitly.
Preview 2, Preview 1, and 0.4.1 clients should not wait for an in-app RC3
notification. Those released clients either predate the macOS prerelease feed
resolver or consult GitHub's stable-only latest-release endpoint, so a correctly
marked RC3 pre-release is not reliably visible to them. Install Preview 3
manually using one of the pinned downloads below. Preview 3 includes the macOS
resolver needed for future same-line preview and stable updates.
## ✨ What's Improved
### Legacy home migration and upgrade safety
`opensquilla migrate` now detects legacy OpenSquilla homes alongside the
existing migration sources. The dedicated `opensquilla migrate opensquilla`
path supports CLI homes, retired Windows portable data directories, desktop
homes, restored backups, Docker volumes, and other explicit source paths.
Migration is dry-run by default. Apply mode stages the complete import,
normalizes stale paths and configuration, moves inline provider secrets to
`.env`, pauses imported scheduled jobs, and publishes the target
transactionally. Recovery metadata makes interrupted imports repeatable instead
of leaving a partial home or forcing users to discard their source data.
Desktop onboarding, Settings, gateway boot diagnostics, doctor, and the Web UI
surface legacy data and provide the matching recovery command. Configuration
formats from every released OpenSquilla version remain supported, so older
homes can be imported without hand-editing their files.
### Providers, models, and routing
TokenRhythm support now includes a verified provider integration, a curated
router ladder, a static ensemble profile, live model-limit corrections, and
GLM 5.2 coverage. The ensemble configuration has been redesigned around clear
presets and custom lineups.
New provider coverage includes Tencent TokenHub and Token Plan for the Hunyuan
hy3 family, plus Alibaba Cloud IQS for runtime web search. Live catalogs and
model discovery expose fuller model lists and current limits. Provider probes
report latency, per-model context-window overrides participate in budgeting,
API-key shape diagnostics catch common setup mistakes, and an explicitly saved
`llm.base_url` now wins over provider environment defaults.
Provider request and stream handling has tighter compatibility across strict
OpenAI-compatible gateways, DashScope thinking and prompt-cache behavior,
reasoning-only responses, length limits, and one-shot thinking fallbacks.
Code-task subagents inherit the configured provider and fail early when the
selected credentials cannot be used.
The opt-in router self-learning loop can collect privacy-preserving routing
features, learn from explicit feedback, evaluate candidate heads offline, and
roll back a regressed promotion. It remains disabled unless the operator turns
it on.
### Desktop, terminal, and Control UI
The terminal UI gains a substantial interaction and rendering overhaul,
including inline approvals and clearer live activity. The Control UI adds a
theme engine, improved monitoring and diagnostics, safer Settings navigation,
copyable desktop-shell commands, better image navigation, compact long tool
traces, and an opt-in background-music player for user-supplied media.
Desktop fixes cover gateway boot recovery, language selection, Windows native
theme behavior, the macOS prerelease feed resolver, gateway lifecycle guidance,
and packaged CLI invocation. Chat keeps scroll position and token-linked state
more reliably, while code blocks and skill details are easier to inspect and
copy.
Attachments can now accept opaque file types without parsing their contents,
with bounded upload memory and workspace disk usage. Large valid UTF-8 text
files and larger channel downloads have clearer, safer staging behavior.
### Runtime, safety, and data reliability
Persistence migrations, scheduling, session cleanup, MCP lifecycle, channel
reply routing, provider retry behavior, context compaction, tool dispatch, and
workspace writes have all received contract hardening. The per-turn objective
reminder is now off by default to preserve provider prompt-cache reuse and avoid
unnecessary repeated reasoning.
The gateway now disables CORS by default and rejects cross-origin browser
requests to state-changing routes unless the origin is explicitly allowed.
Diagnostics redact more secret shapes, provider credential reveal windows are
shorter, and sandbox/search/file-access boundaries are more consistent across
platforms.
### Container deployment
Release tags now build and publish a prebuilt gateway image for both
`linux/amd64` and `linux/arm64`:
- `ghcr.io/opensquilla/opensquilla:v0.5.0rc3`
- `ghcr.io/opensquilla/opensquilla:latest`
Docker `latest` follows the most recently pushed release tag, including previews
and backports. Use the versioned tag for reproducible deployments and rollback.
State remains in the configured volume when the container is replaced.
## Downloads
Recommended desktop downloads:
- macOS desktop installer: `OpenSquilla-0.5.0-rc3-mac-arm64.dmg`
- macOS desktop zip: `OpenSquilla-0.5.0-rc3-mac-arm64.zip`
- Windows desktop installer: `OpenSquilla-0.5.0-rc3-win-x64.exe`
The Windows desktop installer is currently unsigned. See the
[code signing policy](https://github.com/opensquilla/opensquilla/blob/v0.5.0rc3/docs/code-signing-policy.md)
before installation.
Terminal and automation downloads:
- Python wheel: `opensquilla-0.5.0rc3-py3-none-any.whl`
- Checksums: `SHA256SUMS`
Updater metadata:
- `latest-mac.yml`
- `latest.yml`
- `*.blockmap`
No Windows portable assets are published for 0.5.0 preview releases. Existing
0.4.x portable downloads remain on their original release pages so users can
recover the old data directory, but new installations should use Electron, the
versioned Python wheel, or the container image. Do not expect a new
0.5.0rc3 portable zip or a portable `/releases/latest/download/` alias.
Privacy and third-party attribution are documented in
[`PRIVACY.md`](https://github.com/opensquilla/opensquilla/blob/v0.5.0rc3/PRIVACY.md)
and
[`THIRD_PARTY_NOTICES.md`](https://github.com/opensquilla/opensquilla/blob/v0.5.0rc3/THIRD_PARTY_NOTICES.md).
## Upgrading from Preview 2, Preview 1, or 0.4.1
Quit the running desktop app and gateway before replacing them. macOS users
should drag the new app into Applications, eject the DMG, and open the
Applications copy. Windows users should run the new installer. Existing active
home configuration and session data are reused.
When moving from Preview 3 to RC4 or a later Windows Desktop build, install the
new package directly over the existing installation. Do not uninstall Preview 3
first: its uninstaller may remove `%APPDATA%\OpenSquilla`. Back up that directory
before upgrading. RC4 and later installers preserve profile data during a normal
uninstall.
Back up the active home before upgrading if you may need to roll back. Preview 3
relocates data left in older desktop layouts; after that relocation, downgrading
to Preview 2 or Preview 1 can make workspaces, skills, secrets, or sessions look
missing because those builds still expect the old paths. Prefer restoring a
backup over running an older client against a migrated home.
CLI users can reinstall the published wheel over the current tool environment:
```sh
uv tool install --python 3.12 --force --reinstall-package opensquilla \
"opensquilla[recommended] @ https://github.com/opensquilla/opensquilla/releases/download/v0.5.0rc3/opensquilla-0.5.0rc3-py3-none-any.whl"
```
To inspect legacy OpenSquilla data before importing it:
```sh
opensquilla migrate
```
The command is a dry-run unless `--apply` is present. For a retired Windows
portable home, the explicit path is also available:
```sh
opensquilla migrate opensquilla --kind windows-portable
opensquilla migrate opensquilla --kind windows-portable --apply
```
If multiple portable homes are found, use the displayed chooser or pass
`--home <path>`. The source is left untouched after a successful import.
Container users should pin this release for reproducible deployments:
```sh
docker pull ghcr.io/opensquilla/opensquilla:v0.5.0rc3
docker compose up -d
```
Non-user-initiated network observability can be disabled before startup with
`OPENSQUILLA_PRIVACY_DISABLE_NETWORK_OBSERVABILITY=true` or:
```toml
[privacy]
disable_network_observability = true
```
The legacy compatibility environment variables
`OPENSQUILLA_TELEMETRY_DISABLED=true` and
`OPENSQUILLA_UPDATE_CHECK_DISABLED=true` remain honored.
## Acknowledgements
Thanks to the human contributors whose work is newly present in Preview 3:
- [@ab2ence](https://github.com/ab2ence) for desktop gateway boot recovery.
- [@JarvisPei](https://github.com/JarvisPei) for desktop language resolution and
the opt-in background-music player.
- [@labulalala](https://github.com/labulalala) for more reliable Windows
source-installer PATH setup and clearer shell guidance.
- [@Liu-RK](https://github.com/Liu-RK) for token deep links, zero-output chat
recovery, and sandbox file-access alignment.
- [@lyteen](https://github.com/lyteen) for the router self-learning foundation
adopted into the hardened opt-in loop.
- [@nice-code-la](https://github.com/nice-code-la) for verified coding-provider
router presets.
- [@TUOXI293](https://github.com/TUOXI293) for chat, code-copy, skill-details,
tool-trace, title-bar, and native-theme improvements.
See
[`CONTRIBUTORS.md`](https://github.com/opensquilla/opensquilla/blob/v0.5.0rc3/CONTRIBUTORS.md)
for the full attribution ledger and PR/commit evidence.
Binary file not shown.
+168
View File
@@ -0,0 +1,168 @@
# Scheduling
OpenSquilla scheduling lets you run recurring or one-time agent work from the
gateway. Use it for reminders, periodic summaries, status checks, channel
updates, and webhook-delivered automation.
Scheduling is managed with the `opensquilla cron` command group.
## Requirements
Scheduled jobs run through the gateway:
```sh
opensquilla gateway run
```
For long-lived local use, start the managed gateway:
```sh
opensquilla gateway start --json
opensquilla gateway status
```
## List Jobs
```sh
opensquilla cron list
opensquilla cron list --agent main
opensquilla cron list --json
```
## Add an Interval Job
Run a prompt every hour:
```sh
opensquilla cron add \
--every 1h \
--text "Summarize important project updates" \
--name hourly-project-check
```
Intervals accept values such as `30s`, `5m`, and `1h`.
## Add a Cron Expression
Run on weekdays at 09:00 in a named timezone:
```sh
opensquilla cron add \
--cron "0 9 * * 1-5" \
--tz "America/Los_Angeles" \
--text "Prepare a short morning brief" \
--name weekday-morning-brief
```
Use `--exact` when you do not want the default stagger.
## Add a One-Time Job
```sh
opensquilla cron add \
--at "2026-06-01T09:00:00+00:00" \
--text "Remind me to review the launch checklist" \
--name launch-checklist-reminder
```
## Choose the Session Target
The default target is an isolated session. For most scheduled work, that is the
least surprising option.
Useful targets:
| Target | Use when |
| --- | --- |
| `isolated` | Each scheduled run should stand alone. |
| `session` | You want to deliver into a specific session configured by the runtime surface. |
| `main` | You want a system event for the main session. |
Example:
```sh
opensquilla cron add \
--every 30m \
--session-target isolated \
--text "Check for urgent channel updates" \
--name urgent-update-check
```
## Delivery
Disable delivery:
```sh
opensquilla cron add \
--every 1h \
--text "Create a private summary" \
--no-deliver \
--name private-hourly-summary
```
Deliver through a webhook:
```sh
opensquilla cron add \
--every 1h \
--text "Post a compact status summary" \
--webhook-url https://example.com/hooks/opensquilla \
--webhook-token-env OPENSQUILLA_WEBHOOK_TOKEN \
--name webhook-status-summary
```
Prefer `--webhook-token-env` or `--webhook-token-file` over inline tokens so
secrets do not land in shell history.
## Inspect and Run Jobs
```sh
opensquilla cron status <job-id>
opensquilla cron runs <job-id>
opensquilla cron runs <job-id> --limit 50
```
Run a job immediately:
```sh
opensquilla cron run <job-id> --yes
```
## Update or Remove Jobs
```sh
opensquilla cron update <job-id> --enabled
opensquilla cron update <job-id> --disabled
opensquilla cron update <job-id> --every 2h
opensquilla cron remove <job-id> --yes
```
Primary delivery destinations are not patched in place from the CLI. Remove and
re-add a job when the primary channel or webhook destination needs to change.
## Troubleshooting
Check the gateway and job state:
```sh
opensquilla gateway status
opensquilla cron list
opensquilla cron status <job-id>
opensquilla cron runs <job-id>
```
If a job posts to a channel, also check:
```sh
opensquilla channels status
```
Read next:
- [`channels.md`](channels.md)
- [`operations.md`](operations.md)
- [`troubleshooting.md`](troubleshooting.md)
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+188
View File
@@ -0,0 +1,188 @@
# Web Search
OpenSquilla can search the web through configured search providers and can fetch
pages through guarded web tools. Search is useful for current information,
source-backed reports, market research, release notes, and troubleshooting.
## Inspect Search Providers
```sh
opensquilla search list
opensquilla search list --json
opensquilla search status
```
Runtime-supported providers in this build include:
- Alibaba Cloud IQS
- Bocha
- Brave Search
- DuckDuckGo
- Tavily
- Exa
The catalog may include metadata for providers that are not runtime-supported
in the current build. Check JSON output when integrating.
## Configure Search
No-key path:
```sh
opensquilla configure search --search-provider duckduckgo
```
Equivalent search subcommand:
```sh
opensquilla search configure duckduckgo
```
Bocha:
```sh
export BOCHA_SEARCH_API_KEY="..."
opensquilla configure search --search-provider bocha --api-key-env BOCHA_SEARCH_API_KEY
```
Brave Search:
```sh
export BRAVE_SEARCH_API_KEY="..."
opensquilla configure search --search-provider brave --api-key-env BRAVE_SEARCH_API_KEY
```
Tavily:
```sh
export TAVILY_API_KEY="..."
opensquilla configure search --search-provider tavily --api-key-env TAVILY_API_KEY
```
Exa:
```sh
export EXA_API_KEY="..."
opensquilla configure search --search-provider exa --api-key-env EXA_API_KEY
```
Alibaba Cloud IQS (strong Chinese-web coverage; keys come from the IQS console):
```sh
export IQS_SEARCH_API_KEY="..."
opensquilla configure search --search-provider iqs --api-key-env IQS_SEARCH_API_KEY
```
In configuration files, `search_provider` can be `"duckduckgo", "bocha", "brave", "iqs", "tavily", or "exa"`.
It identifies the provider tied to `search_api_key` and
`search_api_key_env`; automatic searches without `--provider` still rank all
available providers by mode, recency needs, and provider capabilities. Use
`search_api_key_env` for an environment-variable reference, or paste a one-time
key through onboarding. `search_fallback_policy = "network"` retries through
DuckDuckGo only after network/timeout errors, while `search_diagnostics = true`
includes provider-attempt details in tool results.
Configuration matrix:
- **no-key**: choose DuckDuckGo, or leave search unconfigured and the runtime
uses DuckDuckGo for general web search.
- **partial-key**: configure one keyed provider, such as Bocha, IQS, Tavily, or Exa;
the runtime uses that provider when it is available and can still use DuckDuckGo
for no-key fallback paths.
- **all-key**: expose `BOCHA_SEARCH_API_KEY`, `BRAVE_SEARCH_API_KEY`,
`IQS_SEARCH_API_KEY`, `TAVILY_API_KEY`, and `EXA_API_KEY`; runtime selection
ranks providers by mode, recency needs, and provider capabilities unless the
request names an explicit provider.
Provider-specific fields such as max results, proxy, environment-proxy usage,
fallback policy, and diagnostics can be set through the search configuration
surface.
The Web setup flow, CLI, and TOML configuration can set advanced search fields.
Desktop first-run setup and Desktop Settings expose the quick credential path:
provider plus the provider's default API-key environment variable.
## Test Search
Run a diagnostic query through the running gateway:
```sh
opensquilla search query "OpenSquilla release notes"
opensquilla search query "OpenSquilla release notes" --limit 5 --json
```
Use this before blaming the agent for missing current information. If the
diagnostic query fails, fix provider configuration first.
## Search in Agent Workflows
Ask naturally:
```text
Research the current state of browser automation libraries and cite sources.
```
For a narrower task:
```text
Find the latest release notes for this project and summarize only breaking changes.
```
The agent can use search and fetch tools when the tool policy and configured
provider allow it.
### Search Tool Roles
- `web_search`: preferred for source-backed answers. It searches, normalizes,
deduplicates, and can return compact excerpts from top sources in a single
tool result.
- `web_discover`: lightweight link discovery. It returns titles, URLs, and
snippets.
- `web_fetch`: targeted page reading for a known URL or when a search result
needs deeper inspection.
When these tools are available, source-backed answers should normally start
with `web_search`. Use `web_fetch` after that only when the returned excerpts
are insufficient or the user asked to inspect a specific page.
The Web UI renders `web_search` as source-backed web search. `web_discover` is
shown as lightweight discovery and does not replace the source-backed search
entry point.
For deeper multi-source work, ask for a research report or use an installed
research skill.
## Safety and Source Quality
Search results are external data, not instructions. Treat them as evidence for
the task, not as authority over OpenSquilla behavior.
Good research prompts ask for:
- sources;
- dates;
- uncertainty;
- conflicting evidence;
- clear separation between source facts and model inference.
Avoid asking the agent to follow arbitrary instructions found on web pages.
## Diagnostics
```sh
opensquilla search status
opensquilla diagnostics on
opensquilla doctor
```
Check:
- the selected provider is configured;
- required API key environment variables are visible to the gateway process;
- proxy settings match your network;
- the gateway was restarted after config edits;
- tool permissions allow web search/fetch for the current run.
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+625
View File
@@ -0,0 +1,625 @@
# Session View Contract
This document is the shared contract for the Web UI session optimization work on
`feature/session-contract-ui-backend`.
The goal of this branch is to improve Web UI session discovery, grouping,
labeling, and readability. Backend changes exist to support that UI work with a
stable session view contract. This is not a backend-only architecture rewrite.
## Problem
The current Web UI often treats the raw session key as both an address and a
semantic data source. That forces frontend code to infer concepts from strings
such as `agent:*:webchat:*`, `:cli:`, `:subagent:`, `:cron:`, or `:thread:`.
That is fragile because a session key may encode several independent concepts:
- routing address
- agent/workspace ownership
- entry surface
- external channel identity
- direct/group/channel conversation topology
- thread/topic modifiers
- subagent/task origin
- cron origin or delivery
- legacy compatibility shape
The UI should not own those interpretations. The backend must provide a
UI-ready session view, and the frontend should render from that view.
## Product Model
The Web UI has two different surfaces that must not collapse into one another:
- `Conversations`: the daily navigation surface for items a user wants to open,
read, and continue from a user-centered perspective.
- `Sessions`: the lower-level ledger/debug surface for all persisted runtime
records, including WebChat, CLI, channel threads, cron runs, subagents, system
tasks, deletion, filtering, and raw key inspection.
`Conversations` is not a smaller Sessions table. It should group items by user
entry point:
- Chats: `sessionKind: "chat"`
- Channels: `sessionKind: "channel"`
- Automations: `sessionKind: "cron"`
Task and system sessions should normally stay in the Sessions ledger unless a
dedicated background-work UI explicitly opts into them.
`New chat` is only a WebChat creation flow:
```text
New chat -> choose agent -> create/open WebChat
```
It must not create cron jobs, channel sessions, subagent tasks, or system/task
sessions. Cron and channel creation/configuration belong to their own
Automations/Channels surfaces.
## API
Preferred RPC:
```ts
rpc.call("sessions.list", { limit: 200, view: "session-list-v1" })
```
If a REST endpoint is used, `/api/sessions` should support equivalent `limit`
and `view` parameters before the chat session selector relies on it for a larger
list. The current default session list size may be too small for selector UI.
The response shape remains backward compatible:
```ts
interface SessionsListResponseV1 {
sessions: SessionListItemV1[];
count: number;
ts: number;
}
```
Existing callers that send only `{ limit }` must continue to work.
## Contract Fields
```ts
interface SessionListItemV1 {
key: string;
sessionId?: string;
// Legacy/stored agent id. Kept for compatibility with existing callers.
agentId?: string;
// Effective routing/workspace owner. New UI should prefer this.
effectiveAgentId: string;
sessionKind: "chat" | "channel" | "task" | "cron" | "system" | "unknown";
surface:
| "webchat"
| "cli"
| "tui"
| "mcp"
| "slack"
| "feishu"
| "wecom"
| "telegram"
| "discord"
| "dingtalk"
| "matrix"
| "qq"
| "cron"
| "subagent"
| "unknown";
conversationKind: "main" | "direct" | "group" | "channel" | "unknown";
thread?: {
id: string;
kind: "thread" | "topic";
} | null;
title: string;
subtitle?: string;
groupLabel: string;
updatedAt: number;
messageCount: number;
status: string;
runStatus:
| "idle"
| "queued"
| "running"
| "interrupted"
| "failed"
| "timeout"
| "cancelled";
// Whether the current Web UI should enable its standard chat composer.
interactive: boolean;
channelContext?: {
name?: string;
id?: string;
accountId?: string;
peerId?: string;
threadId?: string;
};
parent?: {
key: string;
taskId?: string;
spawnDepth?: number;
} | null;
cron?: {
jobId?: string;
sessionTarget?: "main" | "isolated" | "current" | "session";
originSessionKey?: string;
targetSessionKey?: string;
} | null;
}
```
## Field Semantics
`key`
Public session routing address. The UI may use it for opening, resuming,
copying, deleting, and debugging a session. The UI must not parse it for
semantic classification.
`sessionId`
Backend transcript/storage identity when available. It is not the primary UI
routing address.
`agentId`
Legacy or stored agent id. This remains available for compatibility with
existing CLI/TUI/MCP and older UI paths.
`effectiveAgentId`
The agent id that should be used for UI ownership, workspace/routing display,
and agent badges. This handles legacy rows where the stored `agentId` may be
`main` while routing should follow another agent.
`sessionKind`
The lifecycle bucket of the session:
- `chat`: human-facing interactive chat session, including WebChat, CLI, TUI,
MCP, and main-agent chat sessions.
- `channel`: external platform conversation session.
- `task`: runtime/background task session, especially subagent work.
- `cron`: cron-owned isolated run session.
- `system`: internal/system session when the backend exposes one.
- `unknown`: backend cannot classify the row.
This field is the primary grouping input for the `Conversations` surface. If a
design sketch calls this concept `conversationKind: "chat" | "channel" |
"cron" | "task"`, the contract name for that concept is `sessionKind`.
`surface`
The entry surface or platform that produced the session view. Examples:
`webchat`, `cli`, `tui`, `mcp`, `feishu`, `slack`, `telegram`, `cron`,
`subagent`.
Current terminal TUI sessions are CLI-compatible. They should normally report
`surface: "cli"` because the existing TUI gateway path creates CLI sessions and
uses the CLI gateway client contract. Use `surface: "tui"` only if a future TUI
path explicitly marks sessions as TUI-owned.
Known public channel surfaces align with the channel adapter contract:
`slack`, `discord`, `feishu`, `dingtalk`, `wecom`, `qq`, `matrix`, and
`telegram`. Unknown or not-yet-public adapters should degrade to
`surface: "unknown"` while preserving display metadata in `channelContext`.
`conversationKind`
The conversation topology:
- `main`: an agent's main/private session.
- `direct`: direct/private one-to-one conversation.
- `group`: group, room, or multi-person conversation.
- `channel`: platform channel/broadcast-style conversation.
- `unknown`: backend cannot classify the topology.
Thread and topic information must be expressed through `thread`, not by adding
`conversationKind: "thread"`.
`thread`
Optional modifier for platform thread/topic context. It does not replace
`conversationKind`.
`title`
Primary user-facing label. UI should prefer this over the raw `key`.
`subtitle`
Secondary context such as source, agent, channel, parent, or recent context.
`groupLabel`
UI grouping label. Session selector and Sessions page grouping should use this
field instead of deriving groups from the key.
`updatedAt`
Epoch milliseconds for recency sorting and relative time display.
`messageCount`
Transcript/message count for display.
`status`
Persisted session lifecycle status. Current backend values include `running`,
`done`, `failed`, `killed`, and `timeout`. Frontend should treat this as a
backend lifecycle string and use `runStatus` for idle/running turn badges.
`runStatus`
Runtime task status for current/last turn display. This is separate from the
persisted session lifecycle status.
`interactive`
Whether the current Web UI should enable its standard chat composer for this
row. This is not the same as visibility. A non-interactive row may still appear
in Conversations or Sessions as a readable item.
Default rules:
- WebChat rows should be interactive.
- CLI/TUI/MCP rows are compatible ledger rows; do not enable the Web UI composer
unless backend explicitly marks them interactive.
- Channel rows are readable from the Web UI, but the standard WebChat composer
should remain disabled unless a safe channel-reply flow exists.
- Cron, subagent, task, and system rows should normally be non-interactive.
If the UI later needs more nuance, add a structured field such as `openMode`
instead of inferring behavior from the key.
`channelContext`
Optional external channel identity and delivery metadata. This should be
display-only in the UI unless a feature explicitly needs routing details.
Do not confuse this with the legacy `channel` field already present in
`sessions.list`. The legacy field remains for CLI/TUI/older callers and may be
a string. New UI should use `surface` and `channelContext`.
`parent`
Optional subagent/task parent relationship.
`cron`
Optional cron metadata. Cron metadata does not automatically make an existing
webchat/channel session a cron session.
`error_id`
Optional short reference id on `session.event.error` payloads (and rendered
into user-facing error text as `(ref: <error_id>)`). Joins the error to its
durable `turn_errors` record for diagnostics. Additive; may be absent on
older gateways or when no record was written.
## Backend Rules
The backend owns session classification and display normalization.
Backend generation should prefer explicit structured data before legacy key
fallbacks:
1. Session row fields, including agent id, display name, channel fields,
delivery context, parent session key, and origin metadata.
2. Route/source metadata such as source kind, channel kind, channel id,
thread id, and interaction mode.
3. Task runtime rows for `runStatus`, subagent/task status, and parent
relationships.
4. Cron job/session metadata for cron-owned isolated runs and cron delivery
context.
5. Legacy key parsing only as a compatibility fallback inside backend
normalization.
The frontend must not duplicate backend key parsing.
Backend compatibility requirements:
- Keep `sessions.list { limit }` working.
- Keep `sessions.create -> { key, sessionId }` working.
- Keep `sessions.resolve({ key })` working.
- Keep `chat.history({ sessionKey })` working.
- Keep existing row fields such as `agent_id`, `agentId`, `updated_at`,
`updatedAt`, `message_count`, `entry_count`, `sourceKind`, and `channelKind`.
- Add new contract fields without deleting or changing the old shape.
- Treat existing fields as compatibility output, not as the canonical semantic
source for the new Web UI.
- Keep the existing CLI and current terminal TUI gateway contracts thin:
`sessions.create({ kind: "cli" })`, `sessions.list({ limit })`,
`sessions.resolve({ key })`, and `chat.history({ sessionKey })` must not gain
required new parameters.
## Frontend Rules
Frontend should render from contract fields:
- Use `sessionKind` for the primary Conversations sections:
Chats, Channels, and Automations.
- Use `groupLabel` for second-level grouping within a section.
- Use `title` as primary text.
- Use `subtitle` as secondary text.
- Use `effectiveAgentId` for agent badges and agent ownership display.
- Use `messageCount` for message count.
- Use `updatedAt` for relative time.
- Use `runStatus` for runtime badges.
- Use `sessionKind`, `surface`, and `conversationKind` for icons, colors, and
high-level visual treatment.
- Use `interactive` to decide whether to enable the standard Web UI composer.
- Treat `thread` or `topic` as a modifier, not as a separate conversation kind.
- Use `key` only for open/resume/copy/delete/RPC/debug actions.
If the UI needs a missing semantic field, backend should add it to this contract
instead of the frontend deriving it from the key.
`Sessions` page rules:
- Show all rows returned by `sessions.list`, including WebChat, CLI, channel,
channel thread/topic, cron, subagent, task, system, and unknown rows.
- Keep raw key visible or easily inspectable.
- Favor filtering, deletion, status inspection, debugging, and resume/open
actions over daily navigation grouping.
`New chat` rules:
- Create only WebChat sessions.
- Ask for or infer the target agent, then call the WebChat creation/open flow.
- Do not create cron, channel, subagent, task, or system rows.
## Forbidden Frontend Behavior
Frontend must not:
- parse `session.key` to determine session kind
- parse `session.key` to determine agent ownership
- group by key tokens such as `:webchat:`, `:cli:`, `:subagent:`, `:cron:`,
`:thread:`, or `:topic:`
- infer external channel type from key segments
- make the raw key the dominant user-facing label except in explicit debug/copy
contexts
- render a normal webchat/channel session as cron only because cron delivered
into it
- use `New chat` as a generic creation entry for cron, channel, subagent, task,
or system sessions
Temporary fallback logic should be isolated, clearly marked, and should not
become the primary UI path.
## Display Examples
### WebChat
```json
{
"key": "agent:main:webchat:default",
"sessionId": "0d2d6f3e-8a41-40de-a3d4-5f05a3c4557a",
"agentId": "main",
"effectiveAgentId": "main",
"sessionKind": "chat",
"surface": "webchat",
"conversationKind": "direct",
"thread": null,
"title": "Web chat",
"subtitle": "main",
"groupLabel": "Web chat",
"updatedAt": 1760000000000,
"messageCount": 42,
"status": "done",
"runStatus": "idle",
"interactive": true,
"parent": null,
"cron": null
}
```
### CLI
```json
{
"key": "agent:main:cli:a1b2c3d4",
"agentId": "main",
"effectiveAgentId": "main",
"sessionKind": "chat",
"surface": "cli",
"conversationKind": "main",
"title": "CLI session",
"subtitle": "main",
"groupLabel": "CLI",
"updatedAt": 1760000000000,
"messageCount": 12,
"status": "done",
"runStatus": "idle",
"interactive": false
}
```
### Subagent Task
```json
{
"key": "agent:main:subagent:760b927a",
"agentId": "main",
"effectiveAgentId": "main",
"sessionKind": "task",
"surface": "subagent",
"conversationKind": "unknown",
"title": "Subagent task",
"subtitle": "Spawned from Web chat",
"groupLabel": "Subagents",
"updatedAt": 1760000000000,
"messageCount": 8,
"status": "running",
"runStatus": "running",
"interactive": false,
"parent": {
"key": "agent:main:webchat:default",
"taskId": "task-123",
"spawnDepth": 1
},
"cron": null
}
```
### Cron-Owned Isolated Run
```json
{
"key": "cron:daily-summary:run:abc123",
"effectiveAgentId": "main",
"sessionKind": "cron",
"surface": "cron",
"conversationKind": "unknown",
"title": "Daily summary",
"subtitle": "Cron isolated run",
"groupLabel": "Cron",
"updatedAt": 1760000000000,
"messageCount": 4,
"status": "done",
"runStatus": "idle",
"interactive": false,
"cron": {
"jobId": "daily-summary",
"sessionTarget": "isolated"
}
}
```
### Cron Delivery Into Existing Channel Session
Cron delivery metadata may be present, but the existing channel session keeps
its original visual identity.
```json
{
"key": "agent:main:feishu:group:oc_123",
"agentId": "main",
"effectiveAgentId": "main",
"sessionKind": "channel",
"surface": "feishu",
"conversationKind": "group",
"title": "Launch room",
"subtitle": "Feishu group",
"groupLabel": "Feishu",
"updatedAt": 1760000000000,
"messageCount": 31,
"status": "done",
"runStatus": "idle",
"interactive": false,
"channelContext": {
"name": "feishu",
"id": "oc_123"
},
"cron": {
"jobId": "launch-check",
"sessionTarget": "session",
"targetSessionKey": "agent:main:feishu:group:oc_123"
}
}
```
### External Channel Thread
```json
{
"key": "agent:main:slack:group:C123:thread:1717000000.000100",
"agentId": "main",
"effectiveAgentId": "main",
"sessionKind": "channel",
"surface": "slack",
"conversationKind": "group",
"thread": {
"id": "1717000000.000100",
"kind": "thread"
},
"title": "C123 thread",
"subtitle": "Slack thread",
"groupLabel": "Slack",
"updatedAt": 1760000000000,
"messageCount": 16,
"status": "done",
"runStatus": "idle",
"interactive": false,
"channelContext": {
"name": "slack",
"id": "C123",
"threadId": "1717000000.000100"
}
}
```
### Legacy Agent Mismatch
If stored `agentId` is `main` but the effective routing/workspace owner is
another agent, the UI must show `effectiveAgentId`.
```json
{
"key": "agent:kid-project:webchat:test",
"agentId": "main",
"effectiveAgentId": "kid-project",
"sessionKind": "chat",
"surface": "webchat",
"conversationKind": "direct",
"title": "Kid project",
"subtitle": "Web chat",
"groupLabel": "Web chat",
"updatedAt": 1760000000000,
"messageCount": 5,
"status": "done",
"runStatus": "idle",
"interactive": true
}
```
## Backend Test Expectations
Backend contract tests should cover at least:
- WebChat session
- CLI session
- subagent task session
- cron-owned isolated session
- cron delivery into an existing session
- external channel session, such as Feishu, Slack, or Telegram
- thread/topic modifier
- legacy row where stored `agentId` differs from `effectiveAgentId`
- unknown/fallback row that still produces usable `title`, `groupLabel`, and
`runStatus`
- current terminal TUI rows remaining CLI-compatible unless a future TUI path
explicitly marks them as TUI-owned
- `interactive` defaults for WebChat, CLI/TUI, channel, cron, subagent, task,
and system rows
## Frontend Acceptance Criteria
- Conversations sidebar groups by `sessionKind`, then `groupLabel`.
- Chat session selector displays `title`, `subtitle`, `groupLabel`,
`effectiveAgentId`, and `interactive` behavior from the contract.
- Sessions page displays `title`, `subtitle`, `effectiveAgentId`,
`messageCount`, `updatedAt`, `runStatus`, and raw key/debug affordances.
- No new frontend logic parses `session.key` for semantic classification.
- Existing open/resume/copy/delete behavior still uses `key`.
- WebChat, CLI, subagent, cron, and external channel sessions render from
contract fields.
- `New chat` creates only WebChat sessions.
- Unknown or missing values degrade gracefully.
- Fallback logic does not reintroduce key parsing as the primary path.
+137
View File
@@ -0,0 +1,137 @@
# Sessions and History
Sessions are durable OpenSquilla conversations. They let you inspect past work,
resume a conversation, export a transcript, or stop a turn that is still
running.
Use sessions when you want to:
- continue a previous chat from the CLI or Web UI;
- find the session key for an artifact, cost report, or channel thread;
- export a transcript for debugging or sharing;
- abort a long-running turn without deleting the session;
- delete old sessions after you no longer need them.
## Requirements
Session commands use the gateway RPC surface. Start or connect to the gateway
before running most session commands:
```sh
opensquilla gateway run
```
Or use the managed background gateway:
```sh
opensquilla gateway start --json
opensquilla gateway status
```
## List Recent Sessions
```sh
opensquilla sessions list
opensquilla sessions list --limit 20
opensquilla sessions list --status idle
opensquilla sessions list --agent main
opensquilla sessions list --channel telegram
opensquilla sessions list --since 2026-05-01
```
Use `--json` for scripts:
```sh
opensquilla sessions list --json
```
## Inspect a Session
```sh
opensquilla sessions show <session-key>
opensquilla sessions show <session-key> --json
```
The output includes the resolved session key, agent id, status, model, update
time, title, and the latest preview when available.
## Resume a Session
```sh
opensquilla sessions resume <session-key>
```
This opens terminal chat on the existing session. Use it when you want to keep
the same conversation state instead of starting a fresh chat.
## Abort a Running Turn
```sh
opensquilla sessions abort <session-key>
opensquilla sessions abort <session-key> --json
```
Abort stops the running turn if one exists. It does not delete the session.
## Export a Transcript
Export Markdown:
```sh
opensquilla sessions export <session-key>
opensquilla sessions export <session-key> --output session.md
```
Export JSON:
```sh
opensquilla sessions export <session-key> --format json --output session.json
```
Exported transcripts are useful for bug reports, audits, or moving a task into a
document. Remove secrets, private local paths, provider tokens, and private
channel identifiers before sharing an export publicly.
## Delete a Session
```sh
opensquilla sessions delete <session-key>
opensquilla sessions delete <session-key> --yes
```
Deleting a session is for cleanup. Export first if you may need the transcript
later.
## Web UI Workflow
The Web UI uses the same session system. In the control console, use the chat
session selector to switch sessions, inspect status, and continue recent work.
Open:
```text
http://127.0.0.1:18791/control/
```
## Troubleshooting
If commands cannot reach the gateway:
```sh
opensquilla gateway status
opensquilla doctor
```
If old context appears summarized, the session may have compacted older
history. This is normal for long sessions under context pressure. Export the
session when exact text matters.
Read next:
- [`features/compaction-and-cache.md`](features/compaction-and-cache.md)
- [`web-ui.md`](web-ui.md)
- [`operations.md`](operations.md)
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+160
View File
@@ -0,0 +1,160 @@
# Tools, Approvals, and Sandbox
OpenSquilla tools give the agent useful capabilities. Policy layers, approval
surfaces, workspace constraints, and sandbox posture control how those tools are
allowed to act.
Use this page before running unattended automation, file edits, shell commands,
or channel-connected agents.
For a focused permissions guide, see
[`approvals-and-permissions.md`](approvals-and-permissions.md).
## Built-In Tool Areas
| Area | Examples |
| --- | --- |
| Filesystem | `read_file`, `write_file`, `edit_file`, `list_dir`, `glob_search`, `grep_search`, spreadsheet reads. |
| Shell and code | `exec_command`, `background_process`, `process`, `execute_code`. |
| Git | `git_status`, `git_diff`, `git_log`, `git_commit`, `apply_patch`. |
| Web | `web_search`, `web_discover`, `web_fetch`, `http_request`. |
| Memory | `memory_search`, `memory_save`, `memory_get`, `memory_delete`. |
| Sessions | `sessions_send`, `sessions_spawn`, `sessions_list`, `sessions_history`, `session_status`. |
| Artifacts | `publish_artifact`. |
| Media | image generation, PDF, TTS, and media helpers. |
| Skills | `skill_list`, `skill_view`, `skill_create`, `skill_edit`, `install_skill_deps`, `meta_invoke`. |
| Admin | cron and gateway administration. |
| Channels/platforms | messaging and Feishu/Lark docs, chat, drive, wiki, media, and permission helpers. |
## Permission Modes
Use stricter modes when running unattended:
```sh
opensquilla agent --permissions restricted -m "Inspect this repo"
```
Use broader modes only when you trust the task and workspace:
```sh
opensquilla agent --permissions full --workspace /path/to/project -m "Run tests and fix failures"
```
For interactive work, the Web UI approvals surface can pause sensitive tool
calls for review. For automation, choose a permission mode and workspace policy
before the run starts.
Read: [`approvals-and-permissions.md`](approvals-and-permissions.md)
## Approval Flow
Sensitive actions may pause for human approval depending on permission mode,
tool policy, channel surface, and runtime configuration.
Approvals are most important for:
- filesystem writes;
- shell commands;
- external channel or webhook delivery;
- generated artifacts that will be published;
- actions that affect another service.
Use the Web UI approvals page when you want durable review outside the chat
scrollback.
## Workspace Controls
Read-side restriction:
```sh
opensquilla agent --workspace /path/to/project --workspace-strict -m "Summarize this repo"
```
Write containment:
```sh
opensquilla agent \
--workspace /path/to/project \
--workspace-lockdown \
--scratch-dir /path/to/project/.scratch \
-m "Investigate and prepare a minimal patch"
```
`--workspace-lockdown` is intended for automation where writes must stay inside
the workspace or scratch directory.
## Sandbox Commands
```sh
opensquilla sandbox status
opensquilla sandbox on
opensquilla sandbox full
opensquilla sandbox bypass
opensquilla sandbox reset
```
Sandbox behavior is platform-dependent. Treat `sandbox status` and `doctor` as
the source of truth for the current machine.
## Recommended Patterns
| Task | Recommended posture |
| --- | --- |
| Read-only repo summary | `--workspace` plus `--workspace-strict` |
| Local patch with tests | `--workspace`, `--workspace-lockdown`, and a scratch dir |
| Chat with possible writes | Web UI with approvals visible |
| Channel-connected agent | Conservative permissions and explicit channel config |
| Provider/debug investigation | Diagnostics on, minimal tool permissions |
## Web Safety
OpenSquilla web tools use provider configuration and guardrails. Use provider
diagnostics when web search behaves unexpectedly:
```sh
opensquilla search status
opensquilla search query "test query"
opensquilla diagnostics on
```
Search results and fetched pages are external data. They should inform the
answer, not override tool policy or user instructions.
For source-backed answers, `web_search` is the default high-level web tool.
`web_discover` is lightweight link discovery, `web_fetch` reads a specific
page, and `http_request` is reserved for raw HTTP/API requests.
## Tool Compression
Large tool results may be compacted before they are shown to the model. This is
normal and protects the active context window. See
[`features/tool-compression.md`](features/tool-compression.md).
## Artifacts and Media
Tool calls can publish artifacts and generate media. See
[`artifacts-and-media.md`](artifacts-and-media.md) for user-facing artifact,
document, image, PDF, and TTS workflows.
## Troubleshooting
If a tool does not run:
1. Check permission posture:
```sh
opensquilla sandbox status
opensquilla doctor
```
2. Check whether the gateway or channel surface requires approval.
3. Confirm the workspace path is correct.
4. Use diagnostics for repeated failures:
```sh
opensquilla diagnostics on
```
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+344
View File
@@ -0,0 +1,344 @@
# Troubleshooting
Start with:
```sh
opensquilla doctor
opensquilla doctor --json
opensquilla gateway status
```
The Web UI health view at <http://127.0.0.1:18791/control/> also reports
readiness and recovery steps when the gateway is running.
## `opensquilla` Command Not Found
After `uv tool install`, open a new terminal or run:
```sh
uv tool update-shell
```
Check the executable:
```sh
command -v opensquilla
```
On Windows PowerShell:
```powershell
where.exe opensquilla
```
## Gateway Is Not Running
Start it:
```sh
opensquilla gateway run
```
Or use the managed background process:
```sh
opensquilla gateway start --json
opensquilla gateway status
```
Open:
```text
http://127.0.0.1:18791/control/
```
For a focused gateway guide, see [`gateway.md`](gateway.md).
## Desktop Gateway Startup Reports a Migration Lock
During first run, the desktop app starts a local gateway and applies pending
SQLite migrations before opening the Control UI. If startup is interrupted, the
gateway may report a yoyo migration lock for `sessions.db`.
Recent versions recover automatically when the lock row points only to dead or
invalid process ids. The gateway keeps the migration failure loud and does not
clear the lock when any recorded pid is still alive.
Check the desktop gateway log for these events:
```text
migrator.lock_timeout
migrator.stale_lock_cleared
migrator.lock_held_by_live_process
migrator.stale_lock_retry_failed
```
If the log says the lock is held by a live process, wait for that gateway to
finish starting or stop the process cleanly. Do not remove `yoyo_lock` rows or
run yoyo break-lock unless you have verified the recorded process is no longer
running.
## Collecting Diagnostics for a Bug Report
One action collects everything a maintainer needs:
- **CLI:** `opensquilla bundle` — works even when the gateway will not start.
- **Web UI:** Logs page → **Diagnostic bundle** button.
- **Desktop app:** application menu → **Download Diagnostics…** (if the app
cannot reach its gateway, this opens the logs folder instead).
The bundle is a single zip containing gateway logs, recent error records,
router decision and trace slices, an offline health report, and your
configuration with all secrets redacted. Local paths are normalized to `~` and
conversation content is **excluded** unless you explicitly opt in
(`--include-content` or the dialog checkbox). Attach the zip to your GitHub
issue.
When a turn fails, the error message ends with a reference code like
`(ref: a1b2c3d4)`. Quote that code in your report — it joins your description
directly to the recorded error inside the bundle.
### Where logs live
- CLI/gateway installs: `~/.opensquilla/logs/` (`debug.log` is the rotating
gateway log; `gateway.log` captures daemonized stdout).
- Desktop app (macOS): `~/Library/Application Support/OpenSquilla/logs/`
(packaged builds) or `~/Library/Application Support/@opensquilla/desktop-electron/logs/`
(development builds) — `desktop.log` is the app lifecycle log and
`gateway.log` the embedded gateway's output. The gateway's own state lives
under `opensquilla/state/` next to them.
## Port Already In Use
Use another port:
```sh
opensquilla gateway run --port 18792
```
Or stop the managed gateway:
```sh
opensquilla gateway stop
```
## Provider Not Configured
Run:
```sh
opensquilla onboard
opensquilla providers list
opensquilla providers configure openrouter
```
Use environment-variable secrets:
```sh
export OPENAI_API_KEY="sk-..."
opensquilla configure provider --provider openai --api-key-env OPENAI_API_KEY
```
## Router Dependency Problems
If SquillaRouter cannot load, OpenSquilla can still run with direct model
routing. To disable the router:
```sh
opensquilla configure router --router disabled
opensquilla gateway restart
```
On Windows, ONNX Runtime may need the Visual C++ Redistributable for Visual
Studio 2015-2022 x64. Install it, then restart the shell and gateway.
On macOS terminal installs, LightGBM may need the system OpenMP runtime. If
startup logs `Library not loaded: @rpath/libomp.dylib` from
`lightgbm/lib/lib_lightgbm.dylib`, install it and restart the gateway:
```sh
brew install libomp
opensquilla gateway restart
```
The desktop app bundles the native runtime it needs; this recovery step
is for terminal or source installs.
## Search Does Not Work
Inspect search providers:
```sh
opensquilla search list
opensquilla search status
```
Use DuckDuckGo for a no-key path:
```sh
opensquilla configure search --search-provider duckduckgo
```
Use Brave with a key:
```sh
export BRAVE_SEARCH_API_KEY="..."
opensquilla configure search --search-provider brave --api-key-env BRAVE_SEARCH_API_KEY
```
Use Bocha, IQS, Tavily, or Exa when your workflow needs freshness or richer
source content:
```sh
export BOCHA_SEARCH_API_KEY="..."
opensquilla configure search --search-provider bocha --api-key-env BOCHA_SEARCH_API_KEY
export IQS_SEARCH_API_KEY="..."
opensquilla configure search --search-provider iqs --api-key-env IQS_SEARCH_API_KEY
export TAVILY_API_KEY="..."
opensquilla configure search --search-provider tavily --api-key-env TAVILY_API_KEY
export EXA_API_KEY="..."
opensquilla configure search --search-provider exa --api-key-env EXA_API_KEY
```
For no-key, partial-key, or all-key setups, inspect the effective runtime state:
```sh
opensquilla search status --json
```
## Channel Config Saved but Channel Is Offline
Restart the gateway after editing channel config:
```sh
opensquilla gateway restart
opensquilla channels status <name> --json
```
For webhook channels, confirm the gateway is reachable from the provider and
that callback secrets match.
## A Tool Was Denied
Check sandbox and permission state:
```sh
opensquilla sandbox status
opensquilla doctor
```
For one-shot runs, choose an explicit permission posture:
```sh
opensquilla agent --permissions restricted -m "Read only"
opensquilla agent --permissions full -m "Trusted local automation"
```
## The Agent Seems to Forget Old Context
Long sessions may compact old history. This is expected under context pressure.
Inspect sessions:
```sh
opensquilla sessions show <session-key>
opensquilla sessions export <session-key>
```
If exact old text matters, keep it in a file, memory note, or exported session.
## A Turn Is Too Expensive or Too Slow
Try:
```sh
opensquilla configure router --router recommended
opensquilla diagnostics on
opensquilla cost
```
For automation:
```sh
opensquilla agent --max-iterations 20 --timeout 600 -m "Bounded task"
```
For large tool outputs, see
[`features/tool-compression.md`](features/tool-compression.md).
## Docker: Web UI Is Unreachable from Another Machine
The default compose port publish is loopback-only
(`127.0.0.1:18791:18791`), so other devices cannot reach the gateway.
Publish on all interfaces instead — and configure token auth first:
```yaml
ports:
- "18791:18791"
```
Keep `OPENSQUILLA_LISTEN` at `0.0.0.0`; exposure is controlled by the
`ports` mapping, not by the bind address. If the host runs a firewall,
allow inbound TCP 18791 from your LAN. Full flow:
[`docker.md`](docker.md).
## Docker: Web UI Connects but Configuration Changes Are Rejected
A containerized gateway binds a wildcard address, so every browser —
including one on the same host — is treated as a remote operator.
Remote operators without a token can chat but cannot administer
configuration or onboarding. Enable token auth:
```yaml
environment:
OPENSQUILLA_AUTH_MODE: token
OPENSQUILLA_AUTH_TOKEN: ${OPENSQUILLA_AUTH_TOKEN:?generate one with openssl rand -hex 32}
```
Put the token value in a git-ignored `.env` next to `compose.yaml`, then log
in with the token in the URL:
```text
http://<server-address>:18791/control/?token=<value>
```
Use `token` mode specifically — `password` and `trusted-proxy` modes do
not support the Web UI connection. If the variables have no effect, the
state volume's `config.toml` may already contain an `[auth]` table —
TOML values take precedence over `OPENSQUILLA_AUTH_*` at boot; edit the
token there (or in the Web UI) and restart.
## Docker: Gateway Fails at Boot on a Bind-Mounted State Directory
The container runs as non-root UID 10001. A bind mount owned by another
user is unwritable, and the gateway fails while creating its databases.
Give the directory to the container user and restart:
```sh
sudo chown -R 10001:10001 /srv/opensquilla
docker compose up -d
```
The named-volume default (`opensquilla-state`) does not have this
problem — the image pre-creates the state root with the right owner.
## Docker: Build Fails with "model assets are unavailable"
`docker build` validates the bundled router models and refuses to bake
Git LFS pointer files into the image. Hydrate them before building
(`git-lfs` is a separate package from `git` on Debian):
```sh
sudo apt install -y git git-lfs
git lfs pull --include="src/opensquilla/squilla_router/models/**"
docker build -t opensquilla:local .
```
Prebuilt images avoid this entirely — see [`docker.md`](docker.md).
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+107
View File
@@ -0,0 +1,107 @@
# Real Terminal TUI Harness
The real-terminal harness launches the OpenTUI chat surface in a child process,
drives it through tmux when available, falls back to PTY when needed, and stores
evidence under `.artifacts/tui-real-terminal/runs`.
## Platform requirements
The harness runs on Unix-like terminal environments. Linux and macOS can run it
directly. Windows users need WSL2 because the harness depends on Unix terminal
primitives. It prefers tmux when available and falls back to a Unix
pseudo-terminal (Python's `pty` module) when tmux is missing.
- Linux and macOS can run the deterministic suite with either tmux or the PTY
fallback.
- Native Windows shells such as PowerShell and `cmd.exe` are not supported:
Python's `pty` module is Unix-only, and tmux has no native Windows build.
- WSL2 is mentioned only as the Windows compatibility path; inside WSL2 this is
just the Linux path.
Install tmux when you want the tmux driver:
```bash
# Debian/Ubuntu Linux, including WSL2:
sudo apt-get update && sudo apt-get install -y tmux
# macOS:
brew install tmux
```
Windows-only setup:
```bash
# In an elevated PowerShell, once:
wsl --install # installs WSL2 + a default Ubuntu distro
# Then inside the WSL2 shell:
sudo apt-get update && sudo apt-get install -y tmux
uv run pytest tests/integration/cli/tui_real_terminal -q
```
When neither tmux nor PTY is available (e.g. native-Windows CI),
`probe_terminal_capabilities()` reports `preferred_driver="none"` and every
scenario test is skipped with a `pytest.skip` reason that names the missing
capability — the run does not fail. The pure-logic driver, capability-probe, and
scenario-model unit tests run on every platform.
## Commands
Fast smoke:
```bash
uv run pytest tests/integration/cli/tui_real_terminal/test_launch_input_loop.py -q
```
Full deterministic suite:
```bash
uv run pytest tests/integration/cli/tui_real_terminal -q
```
Manual lab:
```bash
uv run python scripts/tui_real_terminal_lab.py --scenario long_streaming --backend opentui
```
OpenTUI backend path:
```bash
uv run pytest tests/integration/cli/tui_real_terminal -q --tui-backend opentui
```
The `opentui` backend runs deterministic fake-provider apps through the real
terminal harness. A guarded `live-opentui` backend exists for manual real CLI
smoke checks:
```bash
OPENSQUILLA_TUI_LIVE_REAL=1 uv run pytest \
tests/integration/cli/tui_real_terminal/test_live_opentui_real_cli.py -q \
--tui-backend live-opentui --tui-driver tmux
OPENSQUILLA_TUI_LIVE_REAL=1 uv run python scripts/tui_real_terminal_lab.py \
--scenario live_opentui_architecture_prompt --backend live-opentui
```
The live smoke launches `opensquilla chat --standalone` with
`OPENSQUILLA_TUI_BACKEND=opentui`, drives it through tmux, sends a real prompt,
and captures text evidence. Use it deliberately because it may hit the
configured live provider.
## Evidence
Each run writes:
- `scenario.json`
- `terminal.log`
- `app.log`
- `transcript.txt`
- `frames/*.txt`
- `screenshots/`
- `result.json`
- `visual-verdict.json`
Capability misses are explicit skips. Deterministic assertion failures block.
Visual verdicts with `inspect` preserve evidence without blocking unrelated
backend changes.
+157
View File
@@ -0,0 +1,157 @@
# Terminal Chat (TUI)
Terminal chat, also called the TUI, is the command-line chat surface for
OpenSquilla. Use it when you want an interactive conversation in a shell,
especially while working in a local project directory.
## Start Chat
Start the default terminal chat:
```sh
opensquilla chat
```
This uses the stable Python-native terminal backend. It does not require Bun,
npm, tmux, or OpenTUI dependencies.
If gateway-backed chat cannot connect, start the gateway first:
```sh
opensquilla gateway start --json
opensquilla chat
```
Use a specific model for the session:
```sh
opensquilla chat --model gpt-5.4-mini
```
Resume an existing session:
```sh
opensquilla chat --session <session-key>
```
Terminal chat is interactive and requires a real TTY. For scripts, pipes, CI,
or one-shot automation, use:
```sh
opensquilla agent -m "Inspect this workspace"
```
## Gateway and Standalone Modes
By default, `opensquilla chat` uses the gateway-backed chat path, so it shares
sessions, configuration, approvals, usage, and model/provider state with the Web
UI and other gateway clients.
Use standalone mode when you want direct terminal chat without the gateway
daemon:
```sh
opensquilla chat --standalone
```
Standalone mode accepts workspace flags for local file and tool work:
```sh
opensquilla chat --standalone --workspace /path/to/project --workspace-strict
```
In gateway mode, `--workspace` is ignored by terminal chat. Use a gateway-visible
path with `/path`, or use `/file` to upload a local file from the CLI machine.
## Common Commands
Type `/help` in terminal chat to see the commands supported by the current mode.
Commands available in both gateway and standalone chat include:
| Command | Purpose |
| --- | --- |
| `/help` | Show command help. |
| `/status` or `/session` | Show the active session and model. |
| `/new [title]` | Start a new session. |
| `/model [model]` | Show or change the active model. |
| `/cost` | Show usage for the current chat state. |
| `/clear` or `/reset` | Clear the current session context. |
| `/compact` or `/cmp` | Compact long context when possible. |
| `/save [path]` | Save the transcript. |
| `/image <path> [prompt]` | Send an image file with an optional prompt. |
| `/path <path> [prompt]` | Attach a file by path. |
| `/theme ...` | Change terminal theme settings when the active backend supports it. |
| `/quit` or `/exit` | Leave chat. |
Gateway-backed chat also supports session and operations commands:
| Command | Purpose |
| --- | --- |
| `/sessions [limit]` | List recent sessions. |
| `/resume <id>` | Resume a session. |
| `/delete <id>` | Delete a session. |
| `/models` | List available models. |
| `/usage` | Show aggregate usage. |
| `/meta` | List MetaSkills. |
| `/meta <name>` | Run a MetaSkill in the current session. |
| `/file <path> [prompt]` | Upload a local file and send it with a prompt. |
| `/permissions ...` | Inspect or change interactive permission mode. |
| `/approvals ...` | Inspect or reset approval state. |
| `/forget` | Clear remembered approvals. |
Standalone chat supports the core commands above, but `/models`, `/meta`, and
gateway-wide usage or approval commands require gateway mode.
## Files and Images
Use `/image` for image files:
```text
/image ./screenshot.png Describe the UI issue
```
Use `/path` when the file path is visible to the running chat process:
```text
/path ./docs/quickstart.md Summarize the setup steps
```
In gateway mode with a remote gateway, prefer `/file` so the CLI uploads the
local file before sending the turn:
```text
/file ./report.pdf Extract the action items
```
## OpenTUI Preview
The default terminal chat is the supported path for normal use. OpenTUI is an
opt-in preview backend for evaluating a richer terminal UI from a source
checkout. It is not required for day-to-day terminal chat.
From a source checkout:
```sh
bun install --frozen-lockfile --cwd=src/opensquilla/cli/tui/opentui/package
OPENSQUILLA_TUI_BACKEND=opentui uv run opensquilla chat
```
Leave `OPENSQUILLA_TUI_BACKEND` unset to use the stable terminal chat.
Read [`features/tui-frontend.md`](features/tui-frontend.md) for OpenTUI backend
status, Router HUD details, and replay benchmarks. Read
[`tui-real-terminal-harness.md`](tui-real-terminal-harness.md) only when you are
running maintainer integration tests for terminal rendering.
## Related Pages
- [`cli.md`](cli.md) for the full CLI reference.
- [`sessions.md`](sessions.md) for listing, resuming, exporting, and deleting
sessions.
- [`approvals-and-permissions.md`](approvals-and-permissions.md) for permission
profiles and approval workflows.
- [`features/meta-skill-user-guide.md`](features/meta-skill-user-guide.md) for
`/meta` workflows.
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+101
View File
@@ -0,0 +1,101 @@
# Usage and Cost
OpenSquilla records token usage and estimated cost from the running gateway.
Use the cost view after routed, tool-heavy, channel, or long-context work to
understand where model spend is going.
## Requirements
Cost inspection uses the gateway:
```sh
opensquilla gateway status
```
If the gateway is not running:
```sh
opensquilla gateway run
```
## Show Cost
```sh
opensquilla cost
```
The default view lists session/model rows with input tokens, output tokens, and
estimated cost.
## Group by Model
```sh
opensquilla cost --by-model
```
Use this when SquillaRouter is enabled and you want to see which models carried
the recent workload.
## Use JSON Output
```sh
opensquilla cost --json
opensquilla cost --by-model --json
```
JSON output is useful for local dashboards, regression checks, and automated
reports.
## What to Check First
| Signal | What it can mean |
| --- | --- |
| Many rows for premium models | Router policy or task shape may be escalating more often than expected. |
| High input tokens | Long history, large tool results, or large prompt/tool schema surfaces may dominate cost. |
| High output tokens | The task may need tighter instructions or a smaller response format. |
| Cost concentrated in one session | Inspect that session before changing global configuration. |
## Lower Cost Safely
Start with router and diagnostics:
```sh
opensquilla configure router --router recommended
opensquilla diagnostics on
opensquilla cost --by-model
```
For large tool results, read:
- [`features/tool-compression.md`](features/tool-compression.md)
- [`features/compaction-and-cache.md`](features/compaction-and-cache.md)
For simple one-shot automation, bound the run:
```sh
opensquilla agent --max-iterations 20 --timeout 600 -m "Bounded task"
```
## Notes and Limits
- Cost is an estimate based on recorded runtime usage and configured pricing,
unless the provider itself reports a billed amount. Each row's `costSource`
(`provider_billed` / `opensquilla_estimate` / `mixed` / `unavailable`) says
which kind of number you are looking at; see
[`providers-and-models.md`](providers-and-models.md#pricing-and-cost-estimation)
for the full pricing and provenance model.
- Provider bills remain the source of truth for actual charges.
- Tool compression and routing can reduce model context cost, but they should
be checked against task success, not only token totals.
- Diagnostics can explain why a turn routed, compacted, retried, or produced
unusually large outputs.
Read next:
- [`features/squilla-router.md`](features/squilla-router.md)
- [`features/tool-compression.md`](features/tool-compression.md)
- [`diagnostics-and-replay.md`](diagnostics-and-replay.md)
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+222
View File
@@ -0,0 +1,222 @@
# Use Cases and Recipes
Use this page when you know what you want OpenSquilla to do, but you are not
sure which feature guide to read first.
## First Successful Run
Goal: install OpenSquilla, configure one provider, and send a real message.
```sh
opensquilla onboard
opensquilla gateway run
```
Then open:
```text
http://127.0.0.1:18791/control/
```
If you prefer the terminal:
```sh
opensquilla chat
```
Read next:
- [`quickstart.md`](quickstart.md)
- [`web-ui.md`](web-ui.md)
- [`providers-and-models.md`](providers-and-models.md)
## Reduce Model Cost
Goal: keep simple work on cheaper models and reserve stronger models for hard
turns.
```sh
opensquilla configure router --router recommended
opensquilla cost --by-model
```
Use diagnostics when you want to inspect routing and runtime behavior:
```sh
opensquilla diagnostics on
```
Read next:
- [`features/squilla-router.md`](features/squilla-router.md)
- [`features/tool-compression.md`](features/tool-compression.md)
- [`features/compaction-and-cache.md`](features/compaction-and-cache.md)
## Work With Large Tool Results
Goal: let the agent inspect logs, pages, tables, search results, or diffs
without flooding the model context.
Start with a bounded workspace run:
```sh
opensquilla agent \
--workspace /path/to/project \
--workspace-strict \
-m "Inspect the latest logs and summarize the actionable failures"
```
If the turn seems too slow or expensive:
```sh
opensquilla cost
opensquilla diagnostics on
```
Read next:
- [`features/tool-compression.md`](features/tool-compression.md)
- [`tools-and-sandbox.md`](tools-and-sandbox.md)
- [`troubleshooting.md`](troubleshooting.md)
## Build a Repeatable Workflow
Goal: turn recurring work into reusable skills or meta-skills.
Find an existing skill:
```sh
opensquilla skills search report
opensquilla skills view <skill-name>
```
Inspect a meta-skill before running it:
```sh
opensquilla skills inspect <meta-skill-name>
```
Review historical meta-skill runs:
```sh
opensquilla skills meta runs list
opensquilla skills meta runs show <run-id>
```
Read next:
- [`features/skills.md`](features/skills.md)
- [`features/meta-skills.md`](features/meta-skills.md)
- [`artifacts-and-media.md`](artifacts-and-media.md)
## Remember Useful Context
Goal: preserve preferences, project notes, or reusable task context so future
turns can find them.
```sh
opensquilla memory status
opensquilla memory search "project preference"
opensquilla memory list
```
Inspect a stored memory file:
```sh
opensquilla memory show <path>
```
Read next:
- [`features/memory.md`](features/memory.md)
- [`features/compaction-and-cache.md`](features/compaction-and-cache.md)
## Connect a Messaging Channel
Goal: use OpenSquilla from a supported messaging surface while keeping the
gateway as the local control point.
```sh
opensquilla channels types
opensquilla channels describe telegram
opensquilla channels add telegram --name personal
opensquilla gateway restart
opensquilla channels status personal --json
```
Read next:
- [`channels.md`](channels.md)
- [`configuration.md`](configuration.md)
- [`tools-and-sandbox.md`](tools-and-sandbox.md)
## Schedule Recurring Work
Goal: ask OpenSquilla to run a recurring task without manually opening a chat.
```sh
opensquilla cron add \
--every 1h \
--text "Summarize important project updates" \
--name hourly-project-check
```
Inspect jobs and runs:
```sh
opensquilla cron list
opensquilla cron status <job-id>
opensquilla cron runs <job-id>
```
Read next:
- [`operations.md`](operations.md)
- [`channels.md`](channels.md)
- [`scheduling.md`](scheduling.md)
## Publish a User-Visible Artifact
Goal: ask the agent to produce a file, report, slide deck, HTML page, image, or
media asset that you can inspect and share.
```sh
opensquilla agent -m "Create a short HTML report from the current notes"
opensquilla sessions export <session-key>
```
Read next:
- [`artifacts-and-media.md`](artifacts-and-media.md)
- [`features/skills.md`](features/skills.md)
- [`features/meta-skills.md`](features/meta-skills.md)
## Recover From a Bad Run
Goal: understand what happened, reduce risk, and continue safely.
```sh
opensquilla doctor
opensquilla gateway status
opensquilla sessions show <session-key>
opensquilla cost
```
If a tool was denied or the agent had too much access:
```sh
opensquilla sandbox status
opensquilla agent --permissions restricted -m "Read only"
```
Read next:
- [`troubleshooting.md`](troubleshooting.md)
- [`tools-and-sandbox.md`](tools-and-sandbox.md)
- [`approvals-and-permissions.md`](approvals-and-permissions.md)
- [`diagnostics-and-replay.md`](diagnostics-and-replay.md)
- [`operations.md`](operations.md)
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)
+153
View File
@@ -0,0 +1,153 @@
# Web UI
The OpenSquilla Web UI is the local control console for setup, chat sessions,
approvals, channels, logs, agents, usage, and operational status. It is the
best surface when you want browser-based chat, visible tool activity, durable
approvals, and a quick view of runtime health.
The default Control UI in the 0.4 release line is the Vue product UI served by the gateway.
The legacy frontend is kept only as a maintainer rollback fallback, not as the
normal user path.
## Start the Web UI
Run the gateway in the foreground:
```sh
opensquilla gateway run
```
Open:
```text
http://127.0.0.1:18791/control/
```
Or start a managed background gateway:
```sh
opensquilla gateway start --json
opensquilla gateway status
```
The default gateway binds to `127.0.0.1` for safety.
For gateway lifecycle, host/port, and exposure details, see
[`gateway.md`](gateway.md).
## Main Areas
| Area | Use it for |
| --- | --- |
| Chat | Run and resume chat sessions, inspect tool activity, launch `/meta` workflows, publish artifacts, and use manual compact controls. |
| Conversations | Switch active sessions from the sidebar and keep long-running work visible. |
| Overview / Health | See readiness, provider state, memory state, sandbox posture, and recovery hints. |
| Settings | Configure providers, router, search, channels, permissions, and other setup sections from a modal flow. |
| Channels | Inspect configured channel adapter status and jump to guided setup for configuration changes. |
| Skills | Browse skill readiness and MetaSkill availability. |
| Sessions | Inspect the durable sessions ledger and operational state. |
| Agents | Manage durable agent entries. |
| Usage | Inspect token and estimated-cost rollups. |
| Cron | View and manage scheduled runs. |
| Logs | Inspect runtime logs and diagnostics. |
| Approvals | Respond to sensitive tool-call approval requests. |
## Chat Sessions
The chat UI supports:
- streaming assistant output;
- tool-call cards;
- turn activity and RunTrace views for provider, router, tool, and usage events;
- inline approval requests for sensitive actions;
- artifact cards with thumbnails when previews are available;
- a deliverables drawer for generated outputs;
- share and export actions for handoff;
- a conversation sidebar for switching sessions;
- `/meta` listing and run launch on gateway-backed chat sessions;
- pending message queue behavior while compaction or runtime work is in flight;
- manual `/compact`;
- per-turn usage and savings metadata when available;
- copyable session keys;
- mobile tabs that keep chat, sessions, and operational views reachable on
narrow screens.
Use the session selector to switch between existing sessions. Copy the session
key when reporting a bug or asking another OpenSquilla surface to inspect the
same session.
Coding mode can be enabled from chat when you want code modifications routed
through `opensquilla code-task`. With Coding mode on, code changes use the
guarded host workflow described in [`cli.md`](cli.md#coding-mode-and-code-task)
instead of ordinary in-session editing.
## Manual Compaction
Long sessions can be compacted from chat. If no compaction is needed, the UI
reports:
```text
Already within context budget; no compact was applied
```
If compaction is running, wait for its terminal state before assuming the next
message has the compacted context. See
[`features/compaction-and-cache.md`](features/compaction-and-cache.md).
## Artifacts
When the agent publishes a file, the Web UI shows an artifact card. Use artifact
cards for:
- generated HTML prototypes;
- reports and briefings;
- exported data files;
- PDFs, slide decks, images, and other generated outputs.
Artifact cards may include thumbnails or preview metadata, and the deliverables
drawer keeps published outputs discoverable after the originating turn has
scrolled away.
For channel delivery limits and artifact recovery, see
[`artifacts-and-media.md`](artifacts-and-media.md).
## Approvals
Some tools require confirmation. The approvals area gives operators a durable
place to approve or deny sensitive actions instead of burying the decision in
chat text.
Use the approvals area when:
- the agent wants to write files;
- a command requires elevated permissions;
- a channel or external action needs human confirmation;
- unattended automation should pause before a risky operation.
## Logs and Diagnostics
For local diagnosis:
```sh
opensquilla diagnostics on
opensquilla gateway status
opensquilla doctor
```
Use the Web UI logs and health views to correlate provider readiness, channel
state, session state, and user-visible errors.
## Safety
The Web UI is local by default. If you bind the gateway to a public interface,
configure token auth and network controls first:
```sh
opensquilla gateway run --listen 0.0.0.0 --port 18791
```
Do not expose an unauthenticated gateway to the public internet.
---
[Docs index](README.md) · [Product guide](../README.product.md) · [Improve this page](contributing-docs.md) · [Report a docs issue](https://github.com/opensquilla/opensquilla/issues/new?template=docs_report.yml)