Changeset 0.21.3 (#89)
This commit is contained in:
@@ -300,28 +300,36 @@ tools. The editor extension defines `read_file`, `write_file`,
|
||||
|
||||
## 6. Surfaces (Modes)
|
||||
|
||||
*Implemented in v0.21.3.*
|
||||
|
||||
A "mode" is an extension that registers a **surface** — a UI region that
|
||||
replaces or augments the default chat area.
|
||||
replaces or augments the default chat area. The surface system preserves
|
||||
DOM state across mode switches (critical for CM6 editor instances).
|
||||
|
||||
### 6.1 Surface Regions
|
||||
|
||||
The following `data-surface-region` attributes are present in `index.html`:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ sidebar-top │ surface-header │
|
||||
│ │ (model-bar) │
|
||||
│ mode-selector │ │
|
||||
│ (auto-shown │ surface-main │
|
||||
│ when ≥2 │ (chatMessages) │
|
||||
│ surfaces) │ │
|
||||
│ │ │
|
||||
│ sidebar-nav │ │
|
||||
│ (mode selector) │ surface-main │
|
||||
│ │ (chat, editor, article, │
|
||||
│ sidebar-content │ cluster, ...) │
|
||||
│ (context panel) │ │
|
||||
│ sidebar-content │ surface-footer │
|
||||
│ (search+chats) │ (input-area) │
|
||||
│ │ │
|
||||
│ sidebar-bottom │ surface-footer │
|
||||
│ │ (input area) │
|
||||
│ sidebar-bottom │ │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 6.2 Surface Registration
|
||||
|
||||
**Manifest-based** (planned — extension loader integration):
|
||||
|
||||
```json
|
||||
{
|
||||
"surfaces": [
|
||||
@@ -336,11 +344,16 @@ replaces or augments the default chat area.
|
||||
}
|
||||
```
|
||||
|
||||
**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());
|
||||
@@ -356,12 +369,35 @@ Extensions.register({
|
||||
});
|
||||
```
|
||||
|
||||
**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.
|
||||
Clicking a mode calls `activate()` on that surface and `deactivate()` on
|
||||
the current one. The bus event `surface.activated` fires so other
|
||||
extensions can react.
|
||||
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
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ v0.21.0 Workspace Storage Primitive ✅
|
||||
│
|
||||
┌───────┴──────────────┐
|
||||
│ │
|
||||
v0.21.1 Workspace ✅ v0.21.3 Surface Infra
|
||||
v0.21.1 Workspace ✅ v0.21.3 Surface Infra ✅
|
||||
Tools + Bindings + REPL (parallel)
|
||||
│ │
|
||||
v0.21.2 Workspace ✅ v0.21.5 Editor Surface
|
||||
@@ -724,15 +724,28 @@ Embed text files for semantic search. Reuses `knowledge.SplitText` + `knowledge.
|
||||
- [x] Graceful degradation when no embedding role configured
|
||||
- [x] Mock store updated for FS unit tests
|
||||
|
||||
### v0.21.3 — Surface Infrastructure + REPL
|
||||
### v0.21.3 — Surface Infrastructure + REPL ✅
|
||||
|
||||
Pure UI architecture. No workspace dependency (parallel development).
|
||||
|
||||
- [ ] Surface registration: `ctx.surfaces.register()` with label, icon, regions, activate/deactivate
|
||||
- [ ] Region management: `ctx.ui.replace()` / `ctx.ui.restore()` for CM6 state preservation
|
||||
- [ ] Mode selector in sidebar when ≥1 extension surface registered
|
||||
- [ ] `surface.activated` / `surface.deactivated` events
|
||||
- [ ] REPL console ([#70](https://git.gobha.me/xcaliber/chat-switchboard/issues/70)): fourth debug modal tab, AsyncFunction wrapper, injected globals, command history, tab-completion, admin-gated
|
||||
- [x] `data-surface-region` attributes on index.html containers (surface-header, surface-main, surface-footer, sidebar-content)
|
||||
- [x] `surfaces.js` — SurfaceRegistry: register, activate, deactivate, getCurrent, list
|
||||
- [x] `ctx.ui.replace()` / `ctx.ui.restore()` with DOM preservation (DocumentFragment-based)
|
||||
- [x] `ctx.surfaces.register()` API for extensions
|
||||
- [x] Mode selector component in sidebar (`#modeSelectorWrap`, auto-shown when ≥2 surfaces)
|
||||
- [x] Chat as default surface (implicit, always registered)
|
||||
- [x] `surface.activated` / `surface.deactivated` / `surface.registered` / `surface.unregistered` EventBus events
|
||||
- [x] REPL tab: AsyncFunction wrapper, global injection (API, Events, Extensions, Surfaces, DebugLog, Panels, UI, $, $$, sleep)
|
||||
- [x] REPL tab: pretty-print results (collapsible JSON, type-colored primitives, DOM element summaries)
|
||||
- [x] REPL tab: command history (sessionStorage, ↑/↓ navigation)
|
||||
- [x] REPL tab: tab-completion on object graphs, event labels, globals
|
||||
- [x] REPL tab: event label hints (Events.on/emit completion)
|
||||
- [x] REPL tab: admin gate (admin role OR ?debug=1 URL param)
|
||||
- [x] REPL tab: toolbar (clear, copy, help)
|
||||
- [x] CSS: mode selector + REPL styles
|
||||
- [x] Documentation in EXTENSIONS.md §6 updated with implementation details
|
||||
- [ ] Mobile: mode selector collapses to hamburger/bottom nav (deferred — functions via sidebar on mobile)
|
||||
- [ ] Integration with extension loader (surfaces from manifest — deferred to extension loader update)
|
||||
|
||||
### v0.21.4 — Git Integration
|
||||
|
||||
|
||||
Reference in New Issue
Block a user