Files
openclaw/extensions/logbook/openclaw.plugin.json
Peter Steinberger c730d8f1f1 feat(logbook): automatic work journal plugin with Control UI timeline tab (#99930)
* feat(logbook): automatic work journal plugin with a plugin-contributed Control UI tab

Squash of PR #99930 work for rebase onto the Control UI route refactor:
- extensions/logbook: Dayflow-style capture -> observations -> timeline cards
  pipeline with SQLite store, node capture commands, standup/ask, retention
- plugin SDK/gateway seam: surface "tab" Control UI descriptors projected
  into hello-ok controlUiTabs (scope-filtered, deterministic order)
- Control UI: dynamic plugin tabs with bundled Logbook view
- docs, tests, labeler wiring

* feat(ui): port plugin tabs and Logbook to the route-owned Control UI architecture

- shared /plugin route carries the tab id in the query (?id=<tab>), matching
  the router's exact-path contract
- openclaw-plugin-page renders bundled views (Logbook), sandboxed plugin
  frames (descriptor path), or the unavailable card
- sidebar renders hello controlUiTabs after each group's static routes
- Logbook view/controller live under ui/src/pages/plugin/

* fix(ui): namespace plugin tabs by pluginId to prevent cross-plugin tab id collisions

* fix(logbook): prefer app capture nodes and rotate off failing nodes

* fix(plugins): reject protocol-relative Control UI tab paths

* fix(logbook): harden automatic journal

* docs(changelog): remove maintainer self-credit

* chore(ui): refresh locale metadata after rebase

* fix(logbook): preserve analysis window boundaries

* fix(logbook): align status privacy and timezone

* fix(ui): stop hidden plugin tab polling
2026-07-05 11:50:44 -07:00

84 lines
2.4 KiB
JSON

{
"id": "logbook",
"name": "Logbook",
"description": "Automatic work journal: captures periodic screen snapshots from a paired node and turns them into a reviewable timeline of your day.",
"enabledByDefault": false,
"activation": {
"onStartup": true
},
"uiHints": {
"captureIntervalSeconds": {
"label": "Capture Interval (s)",
"help": "Seconds between screen snapshots. Lower is more detailed but uses more disk and analysis tokens."
},
"analysisIntervalMinutes": {
"label": "Analysis Window (min)",
"help": "Snapshot window size summarized per analysis batch."
},
"nodeId": {
"label": "Capture Node",
"help": "Node id or name that provides screen.snapshot. Defaults to the first connected node that supports it."
},
"screenIndex": {
"label": "Screen Index",
"help": "Zero-based display index to capture.",
"advanced": true
},
"maxWidth": {
"label": "Snapshot Max Width (px)",
"help": "Snapshots are scaled down to this width before storage and analysis.",
"advanced": true
},
"visionModel": {
"label": "Vision Model",
"placeholder": "codex/gpt-5.5",
"help": "provider/model used to read snapshots; the provider must support structured extraction (the bundled Codex plugin does). Defaults to the first image-capable Codex entry under tools.media."
},
"captureEnabled": {
"label": "Capture Enabled",
"help": "Master switch for the snapshot loop. The timeline UI stays available when off."
},
"retentionDays": {
"label": "Frame Retention (days)",
"help": "Snapshots older than this are deleted. Timeline cards are kept.",
"advanced": true
}
},
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"captureEnabled": {
"type": "boolean",
"default": true
},
"captureIntervalSeconds": {
"type": "number",
"default": 30
},
"analysisIntervalMinutes": {
"type": "number",
"default": 15
},
"nodeId": {
"type": "string"
},
"screenIndex": {
"type": "number",
"default": 0
},
"maxWidth": {
"type": "number",
"default": 1440
},
"visionModel": {
"type": "string"
},
"retentionDays": {
"type": "number",
"default": 14
}
}
}
}