Changeset 0.27.0 (#166)
This commit is contained in:
@@ -298,137 +298,43 @@ tools. The editor extension defines `read_file`, `write_file`,
|
||||
|
||||
---
|
||||
|
||||
## 6. Surfaces (Modes)
|
||||
## 6. Extension Surfaces
|
||||
|
||||
*Implemented in v0.21.3.*
|
||||
*Shipped in v0.27.0.*
|
||||
|
||||
A "mode" is an extension that registers a **surface** — a UI region that
|
||||
replaces or augments the default chat area. The surface system preserves
|
||||
DOM state across mode switches (critical for CM6 editor instances).
|
||||
Extension surfaces are full-page custom UIs installed as `.surface`
|
||||
archives and served at `/s/:slug`. They run inside the platform shell
|
||||
with access to the authenticated API, theme system, and UI components.
|
||||
|
||||
### 6.1 Surface Regions
|
||||
See **[EXTENSION-SURFACES.md](EXTENSION-SURFACES.md)** for the complete
|
||||
authoring guide including manifest format, platform API reference, CSS
|
||||
custom properties, and a worked example.
|
||||
|
||||
The following `data-surface-region` attributes are present in `index.html`:
|
||||
### Summary
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ sidebar-top │ surface-header │
|
||||
│ │ (model-bar) │
|
||||
│ mode-selector │ │
|
||||
│ (auto-shown │ surface-main │
|
||||
│ when ≥2 │ (chatMessages) │
|
||||
│ surfaces) │ │
|
||||
│ │ │
|
||||
│ sidebar-content │ surface-footer │
|
||||
│ (search+chats) │ (input-area) │
|
||||
│ │ │
|
||||
│ sidebar-bottom │ │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
- **Archive format:** zip with `manifest.json` + `js/main.js` + optional `css/main.css`
|
||||
- **Install:** Admin panel → Surfaces → Upload (no restart required)
|
||||
- **Route:** `/s/{id}` — rendered via Go templates, DB lookup at request time
|
||||
- **Entry point:** `js/main.js` mounts into `#extension-mount`
|
||||
- **Platform access:** `API._get()`, `UI.toast()`, `Theme.resolved()`, `Events.on()`, `ChatPane.create()`
|
||||
- **Theming:** CSS custom properties from `variables.css` (`--bg`, `--bg-surface`, `--text`, `--text-2`, `--accent`, etc.)
|
||||
- **Admin API:** install, enable/disable, uninstall via `/api/v1/admin/surfaces/*`
|
||||
|
||||
### 6.2 Surface Registration
|
||||
### Relationship to Other Extension Types
|
||||
|
||||
**Manifest-based** (planned — extension loader integration):
|
||||
Extension surfaces are the **most capable** extension type. They create
|
||||
entirely new pages. Other extension types are lighter-weight:
|
||||
|
||||
```json
|
||||
{
|
||||
"surfaces": [
|
||||
{
|
||||
"id": "editor",
|
||||
"label": "Editor",
|
||||
"icon": "code",
|
||||
"regions": ["surface-main", "surface-footer", "sidebar-content"],
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
| Type | Creates a page? | Uses |
|
||||
|------|----------------|------|
|
||||
| **Surface** (`/s/:slug`) | Yes — full page | Custom dashboards, tools, visualizations |
|
||||
| **Block renderer** (Hook 3) | No — transforms message content | Mermaid diagrams, KaTeX math, CSV tables |
|
||||
| **Tool** (Hook 5) | No — LLM-invocable function | Calculator, web search, file operations |
|
||||
| **Post-render** (Hook 3) | No — enhances rendered messages | Syntax highlighting, link previews |
|
||||
|
||||
**Imperative** (implemented):
|
||||
|
||||
```js
|
||||
Extensions.register({
|
||||
id: 'editor-mode',
|
||||
init(ctx) {
|
||||
ctx.surfaces.register('editor', {
|
||||
label: 'Editor',
|
||||
icon: 'code',
|
||||
regions: ['surface-main', 'surface-footer', 'sidebar-content'],
|
||||
activate() {
|
||||
ctx.ui.replace('surface-main', this.renderEditor());
|
||||
ctx.ui.replace('surface-footer', this.renderEditorInput());
|
||||
ctx.ui.replace('sidebar-content', this.renderFileTree());
|
||||
},
|
||||
deactivate() {
|
||||
ctx.ui.restore('surface-main');
|
||||
ctx.ui.restore('surface-footer');
|
||||
ctx.ui.restore('sidebar-content');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Region management API** (on `ctx.ui`):
|
||||
|
||||
- `ctx.ui.replace(regionId, element)` — saves current children to a
|
||||
`DocumentFragment` (detached, not destroyed), inserts new element.
|
||||
- `ctx.ui.restore(regionId)` — re-attaches saved children.
|
||||
|
||||
This is critical for CM6 — editor instances survive mode switches because
|
||||
their DOM nodes are detached (preserving internal state) rather than removed.
|
||||
|
||||
**Surface management API** (on `ctx.surfaces`):
|
||||
|
||||
- `ctx.surfaces.register(id, opts)` — register a new surface
|
||||
- `ctx.surfaces.unregister(id)` — unregister (switches to chat if active)
|
||||
- `ctx.surfaces.activate(id)` — switch to a surface
|
||||
- `ctx.surfaces.getCurrent()` — returns active surface id
|
||||
|
||||
### 6.3 Mode Selector
|
||||
|
||||
When extensions register surfaces, a mode selector appears in the sidebar
|
||||
(`#modeSelectorWrap`) below the brand/new-chat area. Clicking a mode calls
|
||||
`activate()` on that surface and `deactivate()` on the current one.
|
||||
|
||||
Events fired:
|
||||
```js
|
||||
Events.on('surface.activated', ({ surface, previous }) => { ... });
|
||||
Events.on('surface.deactivated', ({ surface }) => { ... });
|
||||
Events.on('surface.registered', ({ surface }) => { ... });
|
||||
Events.on('surface.unregistered', ({ surface }) => { ... });
|
||||
```
|
||||
|
||||
### 6.4 Core Surface
|
||||
|
||||
Chat mode is the default surface. It's not special architecturally — it's
|
||||
the surface that's active when no extension surface is selected. Pragmatically
|
||||
it stays in core because everything depends on it.
|
||||
|
||||
### 6.5 Planned Modes
|
||||
|
||||
**Editor Mode** (extension)
|
||||
- File tree in sidebar, code editor in main, AI chat in split/overlay.
|
||||
- Tools: `read_file`, `write_file`, `search_replace`, `git_status`,
|
||||
`git_commit` — browser tools backed by a git provider API.
|
||||
- This is ai-editor rebuilt properly: tool calls are server-side, logged,
|
||||
token-counted, auditable.
|
||||
|
||||
**Article Mode** (extension)
|
||||
- Outline in sidebar, rich text editor in main, AI assistant in panel.
|
||||
- Tools: `fetch_url`, `summarize_section`, `check_citation`.
|
||||
- The conversation is hidden; only the document matters.
|
||||
|
||||
**Cluster Manager Mode** (2-3 cooperating extensions)
|
||||
- `k8s-manager`: kubectl tools, pod/deployment views.
|
||||
- `ceph-manager`: ceph status, OSD management.
|
||||
- `node-manager`: SSH commands, system metrics.
|
||||
- These talk to each other via EventBus. When `k8s-manager` detects a
|
||||
node is NotReady, it publishes `cluster.node.unhealthy`. `ceph-manager`
|
||||
subscribes and checks OSD placement.
|
||||
- The LLM sees ALL tools from ALL active cluster extensions. "Drain node-3,
|
||||
ensure Ceph rebalances, then cordon it" → `kubectl_drain`, `ceph_osd_out`,
|
||||
`kubectl_cordon` — each routed to the appropriate extension.
|
||||
A single extension can combine multiple types — e.g. a surface for
|
||||
configuration plus a tool for LLM interaction plus a renderer for
|
||||
custom output formatting.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user