chore: import upstream snapshot with attribution
This commit is contained in:
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
@@ -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)
|
||||
@@ -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.
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
@@ -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)
|
||||
@@ -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).
|
||||
@@ -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)
|
||||
@@ -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.0–1.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` (0–1), `cost_latency`
|
||||
(0–1, 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.
|
||||
@@ -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.
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
@@ -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.
@@ -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
@@ -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)
|
||||
@@ -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.
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
@@ -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)
|
||||
Reference in New Issue
Block a user