Repository navigation
feat(assistant): answer questions about Lens itself from its docs and this server - #400
Merged
Merged
Conversation
… this server The assistant had no idea what Lens is or does: asked for the MCP address, or how to connect an app, it said the archive doesn't cover it. A lens_help tool now answers from this server's own facts (version, the web app, MCP and API addresses as the person uses them, what is turned on, their access) and from Lens's docs, cut at their headings into an in-memory SQLite FTS5 index and found by words. Both are cited: This Lens server, and Docs · page › section, which opens that heading. Agents get the same tool over MCP, and chat rooms list its sources with their links. The Docker Compose files mount docs/ read-only at /docs; Cloudron's image copies it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Merged
16 of 22 tasks
adeelahmad
added a commit
that referenced
this pull request
Oct 15, 2026
…pages and notes as built (#424) Move usage analytics (#274) and assets and people (#273) out of the README's In progress list, and add what merged since #383: a namespace's own MCP server, chat completions and one-namespace API keys; editing and merging entities and topics with undo, from agents too; entity pages at wiki addresses; Connect with Google and rclone sign-in on the server; the notes tree, today's note, pins, search and Recently deleted; backups that keep Lens's files; and grouped, searchable settings. In progress now lists the open feature PRs (#398, #400, #402, #408, #419), and the docs index links usage analytics. Claude-Session: https://claude.ai/code/session_01HDx7PPUauyjMn1LZs8JAsS Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
Web citations from main and lens_help's docs and server citations share the url passages; the Toolbox's web app address is now web_app, since main's self.web is the web-search switch. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Brings in #512, the fix for the upgrade check's entity count. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Brings in the chat tool picker (#510, #511); lens_help joins it as the "help" group (Lens's docs). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Brings in conversation export (#474, #484). Exports keep a docs or server citation's source (lens_help) instead of calling it a web page; the export schema lists both. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
20 of 23 tasks
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
adeelahmad
added a commit
that referenced
this pull request
Oct 17, 2026
…525) threat-model.yaml kept a sha256 of the whole prose, so any two pull requests that changed threat-model.md both rewrote that one line and the second to merge conflicted (#400, #508). The YAML's prose_version now names the prose in the same commit, and the validator's new --base check (run by CI against the merge commit's parent) fails a change to the prose that changes neither companion, which is what the hash enforced, without a line every change edits. Adds tests, including two branches that change the prose in different places merging cleanly and still validating. Fixes #507 Claude-Session: https://claude.ai/code/session_01Bwc5go44W4hjHKu329MepB Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
Brings in #525: prose_version no longer hashes the prose. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
The clicks survey hung after its first chat answer, one run in six: the reader navigated away before the streamed answer ended, the garbage collector closed the abandoned generator on the event loop's thread in the middle of that thread's own query, and the answer's cleanup (on.end()) waited for the one embedded connection that same thread held. Every request then waited behind it. DB.conn now gives a thread the connection it already holds; a test closes a generator mid-query and fails in time instead of hanging. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
Ported from #400 so this PR's clicks survey passes while that lands: the survey hung after its first chat answer when the garbage collector closed an abandoned streamed answer mid-query on the thread holding the one embedded connection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BHjm8NXrMmJrZH8D71s4MN
20 of 21 tasks
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
… saved ones (#539) * fix(settings): test the LLM address and model on screen, not only the saved ones The Test button in Settings → LLM provider tested the saved settings, so a new address or model typed but not saved was never tried. The test route now takes base_url, model and api_key; the saved key goes only to the saved address. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BHjm8NXrMmJrZH8D71s4MN * fix(store): a thread holding the embedded connection can query again Ported from #400 so this PR's clicks survey passes while that lands: the survey hung after its first chat answer when the garbage collector closed an abandoned streamed answer mid-query on the thread holding the one embedded connection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BHjm8NXrMmJrZH8D71s4MN --------- Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
Keeps both sides of the Toolbox docstring (web_app and allowed_out), and lists both the lens help tool and deep research in the threat model's prose, JSON and YAML; the YAML had lost the lens help entry in an earlier merge. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
…-2dbl54 Also lists #400 (released in v0.15.0) as built rather than in progress, as #536 does, so the requirements check passes again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QTanM4rqSWyCsV6x3En1N6
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
Release 0.15.0 carries #400, so the requirements check failed on main with it still under In progress; it moves to the built list with its checks. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ln25ykE6uBDqx21WBU94SX
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
…sed, and #400 listed as built Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTrHPwWHtEvFJFq3M1YpH4
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
Also lists the assistant's answers about Lens itself (#400, released in v0.15.0) as built, which check_requirements now asks for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xa7Hz2SLg6sNrGksMEzBaz
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
…is released Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dzm4YHdHn2qZy7aXer3KeH
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Nbf5G7PvMgThj8BbUPGT8
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
…leased) The same change as #575, so the requirements check passes here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015ZmJ29Kc4iXuyKqCRifAH5
21 of 23 tasks
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
Keeps main's entity filter tests beside the feed ones, moves the web app's Feeds note to Unreleased, and lists #400 (released in v0.15.0) as built with its checks, which the requirements check asks for. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CDEiKGoyQX8Vmnv9bi5JpD
This was referenced Oct 18, 2026
Merged
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
v0.15.0 released #400, so the requirements check fails while it stays under In progress. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GbBS222wEEQgkuui6CHo6c
21 of 23 tasks
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
#400 is released, so the requirements check wants it out of In progress and in the built list with its checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016j3Y4Dh3DLGwyFYBH23QML
10 of 23 tasks
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
…rt of #578) The requirements check fails on main since #400 was released; the same change as #578, a no-op once that merges. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SETHpH6NUGKT1Bwd6xyPCA
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
…tion and decide nodes (#576) * feat(workflows): draw an automation's workflow on the canvas, with action and decide nodes Event workflows open on the workflow canvas: What happened starts them, the palette lists every action in the catalog, an action node's settings are drawn from its params by SchemaForm with a badge for whether it asks first, Decide gets a port per option and unsure, the canvas checks the leaf rule and settings as the backend does, and Try on a sample runs the graph on a kind's sample and says what each action would do. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AjJqXgjj1cNdKGRQbX5frb * docs(readme): list answering questions about Lens itself (#400) as built Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AjJqXgjj1cNdKGRQbX5frb --------- Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
adeelahmad
pushed a commit
that referenced
this pull request
Oct 18, 2026
Keeps both the publishing nodes and main's automation actions in the workflow model, canvas and settings, and main's wording for #400. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CDEiKGoyQX8Vmnv9bi5JpD
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
…edule and the backup (#535) * feat(schedules): one Schedules page for every routine, automation schedule and the backup Lens's crontab: GET/PATCH /api/v1/schedules and POST /run, MCP tools schedules, set_schedule and run_schedule, and an Automate > Schedules page to switch, re-time and run anything on a clock. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NwZdhpvjjidN5Y45CLSi8m * fix(schedules): take the nav row Routines had so the phone nav fits as before The clicks check found Admin one swipe further down on a phone with a new nav row. Schedules now has Routines' row (the Routines page and New routine open from its top), the routine-create journey goes through it, and isActive marks Schedules on /routines pages. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NwZdhpvjjidN5Y45CLSi8m * fix(schedules): one New routine on the page, in its header An empty Schedules page had New routine twice (the header and the empty state), which made the routine-create clicks journey's link ambiguous. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NwZdhpvjjidN5Y45CLSi8m * docs(requirements): list the assistant's answers about Lens itself as built #400 shipped in v0.15.0, so its In progress line failed make requirements on main. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NwZdhpvjjidN5Y45CLSi8m --------- Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
…secret field (#577) * feat(web): Settings › Secrets, and a Vaultwarden picker beside every secret field Settings › Secrets sets up the Vaultwarden vault secret fields can refer to and tests its sign-in, and lists every field that refers to it with whether it could be read. Every secret field gets From Vaultwarden, which lists the vault's items by name and fills in a reference; a saved reference shows itself and its read status, never a value. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019okSDRfFHV74BTpMzinTFg * docs(readme): list the assistant's answers about Lens itself as built #400 shipped in 0.15.0, so make requirements failed on main with it still under In progress. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019okSDRfFHV74BTpMzinTFg --------- Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
) * feat(routines): graph workflows find wrong types and noise to tidy The Find what to tidy node (candidates) looks for two more kinds: entities whose type the naming rules read differently now (retype), and noise to hide (hide). Ask the model judges them a kind at a time, and Apply changes makes the sure ones and proposes the rest, each undoable like a merge. A change someone dismissed or undid is no longer found again, so a run never redoes it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Nbf5G7PvMgThj8BbUPGT8 * Merge origin/main; list the assistant's Lens help (#400) as built Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Nbf5G7PvMgThj8BbUPGT8 --------- Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
…ts (#563) * feat(cli): lens ext lists, pulls, checks and pushes extension manifests `lens ext pull` writes extensions' manifests into a folder, `push` saves the changed ones as new versions and the new ones as extensions, `check` checks them without saving, and `list` lists them (--json for agents). It works on this install's database, as the first admin or --as, or on any Lens server with --url and an API token. Pulled files carry `version: N`, so a push won't save over changes made in Lens since, and a pull won't overwrite a file's own changes, without --force. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FbmJ86QaV2YwusjgNowpf8 * fix(cli): lens ext pushes neither of two files with one name Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FbmJ86QaV2YwusjgNowpf8 * docs(readme): list answering questions about Lens itself as built, now #400 is released Main's requirements check fails since v0.15.0 released #400 while the README still listed it In progress. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FbmJ86QaV2YwusjgNowpf8 * Merge main; move the changelog entry to changelog.d Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FbmJ86QaV2YwusjgNowpf8 --------- Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
…553) * feat(mesh): run Nebula on the primary in an optional mesh container The primary's half of the mesh: Lens's server can't create network devices, so Nebula runs in a container of its own, `mesh` (mesh/sidecar.py in the plain Python image), the only one holding NET_ADMIN and /dev/net/tun. It makes this machine's key pair itself and keeps the private key in its own volume; it puts the public key in the folder it shares with Lens's server, and the keeper (mesh.Keeper, one process at a time on a lease) signs it and writes the config back. The container checks each config with `nebula -test`, reloads Nebula on SIGHUP when it can (the blocklist, the firewall) and restarts it when it must, and relays port 8000 on the mesh address to the database and 8080 to the API, for the machines Nebula's firewall lets in. It fetches Nebula's release with the same pinned checksums as Lens. Adding a node asks the upgrade agent to start the container (profile `mesh`), and turning the mesh off stops it; GET /api/v1/mesh shows how it runs under `service`, and the primary's row carries its report. Default installs are unchanged: the profile is off and nothing listens. Tested with a stand-in Nebula in CI, and with Nebula 1.11.2 in Docker: a worker node reached the database and the API through the container, a compute node the API only, and a removed node nothing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTrHPwWHtEvFJFq3M1YpH4 * docs(readme): the mesh's in-progress line points at its open pull request Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTrHPwWHtEvFJFq3M1YpH4 * test(mcp): the services tool lists the mesh container too Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTrHPwWHtEvFJFq3M1YpH4 * style(mesh): the sidecar is linted and formatted as the server's code, by pre-commit too Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTrHPwWHtEvFJFq3M1YpH4 * chore: merge main; the mesh container's changelog entry under Unreleased, and #400 listed as built Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTrHPwWHtEvFJFq3M1YpH4 * chore: merge main; the mesh container's changelog entry as a fragment in changelog.d Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTrHPwWHtEvFJFq3M1YpH4 --------- Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
…s graph changes to review (#560) * feat(notifications): tell targets when a routine's run fails or leaves graph changes to review Two new events, routine.failed and routine.proposed, sent through Matterbridge, signed webhooks, Slack and Discord to each namespace a routine runs over. Default events for new targets stay as they were. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AnPBc76gCvHKeWvSLd1L7h * docs(readme): list the assistant's answers about Lens itself as built, now that #400 is released Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AnPBc76gCvHKeWvSLd1L7h --------- Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
* feat(enhance): enhance low quality images before they're read
The new enhance step, first in the standard pipeline, measures each image
(size, sharpness, noise, contrast, and face size where the namespace finds
faces) and keeps an enhanced copy of a low quality one that read, faces,
objects and descriptions then work from. The original stays as it is.
Off by default (Settings → Enhance). The classic engine (Pillow) needs
nothing; Real-ESRGAN general x4v3 (BSD-3-Clause, 5 MB ONNX) is fetched the
first time it's chosen. The copy is encrypted like the namespace's files,
re-keyed and deleted with them, and downloadable by members only.
Agents: POST /resources/{rid}/enhance, the MCP tool enhance and the enhance
automation action enhance an image on request. The web app has the settings
section, the pipeline step and an Enhance row in the Details tab.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012m72U9mPLCbuH8rSAZGSuZ
* test(imports): a transcript's import skips enhance too
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012m72U9mPLCbuH8rSAZGSuZ
* docs(threat-model): the Real-ESRGAN model the enhance step can fetch
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012m72U9mPLCbuH8rSAZGSuZ
* docs(configuration): rewrap the Settings paragraph
* docs(readme): enhancing images is built, not in progress
* docs(threat-model): list Real-ESRGAN among the dependencies
The threat model's YAML now changes with the prose, as the validator asks
since main's same-commit scheme.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012m72U9mPLCbuH8rSAZGSuZ
* docs(readme): answering about Lens itself is built, not in progress
#400 is released, so the requirements check on main was red; its In
progress line goes, and its checks join the built list.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012m72U9mPLCbuH8rSAZGSuZ
* docs(readme): keep the enhance step in the built list after merging main
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012m72U9mPLCbuH8rSAZGSuZ
---------
Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
* feat(workflows): an HTTP call node behind the web tools' guard Asset and graph workflows call a web address through netguard, as the assistant's web tools do: public addresses on the web's ports (or networks an admin allowed), the host written out so what flows through can't move it, credential headers sealed to their header and host, and a try on the canvas that only reads. Redirects now keep any credential header, not only Authorization, from another server. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016j3Y4Dh3DLGwyFYBH23QML * docs(readme): list the assistant's answers about Lens (#400) as built #400 is released, so the requirements check wants it out of In progress and in the built list with its checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016j3Y4Dh3DLGwyFYBH23QML --------- Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
* feat(timeline): emoji reactions and comments on activities
The timeline becomes a feed everyone in a namespace talks on. An opened item has a React button with a palette and shows everyone's reactions as chips; its comments open as threads with Reply, where Enter sends. A closed line sums its items' reactions and says how many comments it has. A comment on an asset's arrival is a comment on the asset, so the same thread shows on its page.
Each reaction is a reaction.added activity (noisy, by the person, with the activity as its object) and each comment a comment.added with the activity as its target, following the activity's audience, so automations and agents can act on them. Agents react and comment over MCP (react_to_activity, activity_comments, comment_on_activity) and through POST /activities/{id}/react and /activities/{id}/comments.
Reactions are one event_reaction row per person and activity, as marks are; comments reuse the comment table with an activity field. No model call is involved.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ln25ykE6uBDqx21WBU94SX
* docs(readme): list the assistant's answers about Lens itself as built
Release 0.15.0 carries #400, so the requirements check failed on main
with it still under In progress; it moves to the built list with its
checks.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ln25ykE6uBDqx21WBU94SX
* fix(chat): show a new conversation's first answer when its first load raced the stream
The page moves to /chat/{id} as a new conversation's first answer
streams. On a slow device that first load of the conversation is still
in flight when the answer ends, and the query cache folds the refetch
asked for then into the load, which predates the answer: the page showed
"No answer was saved for this question" until reloaded (the phone
clicks survey's chat-ask journey in CI). After an answer, when the
conversation read back lacks it, it is read once more.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ln25ykE6uBDqx21WBU94SX
* Revert "fix(chat): show a new conversation's first answer when its first load raced the stream"
This reverts commit 7f260ec: #582 carries
the same fix for main (refetchFresh in every chat panel, and the answer
written on a thread of its own), so this PR stays one concern.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ln25ykE6uBDqx21WBU94SX
* docs(changelog): move the reactions and comments entry to a changelog.d fragment, and name them in the README
The release commit folds Unreleased into the version section and #581 moved new entries to changelog.d/, so the
entry becomes changelog.d/timeline-social.md. The README's built line lost its reactions and comments clause in an
earlier merge; it is back.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ln25ykE6uBDqx21WBU94SX
---------
Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
…ay and clipper sign-in as built (#536) Since the last README refresh, #474, #484, #510, #511, #497, #495, #406, #516, #517, #491, #400 and #506 merged. The README's built list now says the assistant answers questions about Lens itself; a conversation exports as Markdown, PDF or JSON and its answers, questions and code copy; a Tools chip picks an answer's tools, limit and namespaces; sandbox runs open under the answer with downloads, and Settings starts the gateway; deep research plans, runs and returns a cited report; ready-made MCP servers, the MCP servers page and the optional containers start from the web app; and the web clipper signs in or takes an API token. Each has its checks in docs/requirements.md. In progress lists only open PRs; the Nebula mesh (#546, merged, partly built) moves to Planned with what's next; the Planned proof item keeps only the Raspberry Pi timing; the docs index links requirements and checks, and published feeds. Claude-Session: https://claude.ai/code/session_01HDx7PPUauyjMn1LZs8JAsS Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
adeelahmad
added a commit
that referenced
this pull request
Oct 18, 2026
…ine (#538) * feat(voice): read answers and podcasts aloud with Kokoro on this machine Kokoro v1.0 (hexgrad's Kokoro-82M, Apache-2.0) as a text-to-speech provider, voice.tts_provider "kokoro": spoken answers and podcast hosts are read on the server's own CPU through kokoro-onnx on ONNX Runtime, in any of its 54 voices across nine languages, with nothing sent anywhere and nothing billed. It's opt-in and fetched once it's picked: the `kokoro` extra (espeak-ng and phonemizer are GPL-3.0, so they stay out of the default install), and the model (voice.kokoro_model: fp32, fp16 or int8) and voices files from kokoro-onnx's release, checked against their SHA-256. Settings → AI assistant → Voice offers it with the model size and the voice picker; a podcast's second host gets a voice in the first host's language. kokoro.yml fetches and reads with each model on x64 and arm64. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dzm4YHdHn2qZy7aXer3KeH * test(settings): carry ai.auto_title in the Kokoro settings fixture main's conversation titles (#531) added ai.auto_title to the section the Kokoro settings test renders, so its fixture names it too; without it Save sent an ai update beside the voice one. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dzm4YHdHn2qZy7aXer3KeH * docs(threat-model): count the Kokoro row in the JSON companion The threat model workflow's validate job wants a change to threat-model.md to change a companion too (#507): the Kokoro row is documented, so the JSON's documented count goes up by one, as #518 did for Moondream. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dzm4YHdHn2qZy7aXer3KeH * fix(voice): offer Kokoro in full precision and 8-bit only On GitHub's arm64 runner, ONNX Runtime's CPU provider returned an empty waveform for kokoro-onnx's fp16 export, and kokoro-onnx's pause insertion then failed on a zero-size array. On x64 it was no faster than fp32, so voice.kokoro_model is now fp32 (the default) or int8, and the fp16 file is no longer pinned. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dzm4YHdHn2qZy7aXer3KeH * test(settings): carry the research section in the Kokoro settings fixture Main's deep research (#517) added a research section to Settings › AI assistant, so the fixture carries its defaults and Save sends only the voice change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dzm4YHdHn2qZy7aXer3KeH * test(settings): carry ai.compact_at in the Kokoro settings fixture Main added ai.compact_at (summarise long conversations early), so the fixture carries its default and Save sends only the voice change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dzm4YHdHn2qZy7aXer3KeH * docs(readme): list answers about Lens itself as built, now that #400 is released Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dzm4YHdHn2qZy7aXer3KeH * docs(changelog): name the Kokoro fragment after its pull request Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dzm4YHdHn2qZy7aXer3KeH * docs(threat-model): count the Kokoro entries against main's newest model Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dzm4YHdHn2qZy7aXer3KeH * docs(readme): take Kokoro out of In progress, now that it's built Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dzm4YHdHn2qZy7aXer3KeH --------- Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by Adeel · project thread
Description
Before: asked "what is the MCP address?", "how do I connect Claude?" or "is Telegram on?", the assistant said the archive doesn't cover it. It only knew the archive.
After: it answers from a new
lens_helptool and cites it. The tool gives this server's own facts (version; the web app, MCP and API addresses as the person is using them; remote access and HTTPS addresses when on; what is turned on; their own access; admins also get each setting's page) and the matching sections of Lens's docs, plus the docs' contents. Citations read "This Lens server" and "Docs · MCP server › Connecting"; a docs citation opens that heading. Agents get the same tool over MCP, chat rooms list its sources with their links, the tool picker offers it as thehelpgroup, and conversation exports keep a docs or server citation's source and link.How:
app/domain/manual.pycutsdocs/*.mdat their headings into an in-memory SQLite FTS5 index (English stemming, BM25: the word index's own engine, standard library, no model, no network), built on first use and again when a page changes (~40 ms for the whole manual). The docs are read fromLENS_DOCS_DIR, elsedocs/next to the code; both Docker Compose files mount the install'sdocs/read-only at/docs, so the assistant reads the docs of the version it runs, and the Cloudron image copies them.Passagegainsurlandsource, andrecording_idbecomes optional, so citations can point at a page instead of a recording (make openapi). The web app opens those in a new tab. The tool prompt tells the model to uselens_helpfor questions about Lens rather than answering from memory. MCP results fromlens_helpskip the injection flag, since they are Lens's own docs (which describe "ignore previous instructions" as an example).Also fixed, found when the clicks survey hung after its first chat answer (one run in six, reproduced locally with a thread dump): a reader navigating away before a streamed answer ends leaves its generator to the garbage collector, which closes it on whatever thread is running, mid-query, and the answer's cleanup (
on.end()) then waited for the one embedded database connection that same thread held, freezing every request.store.DB.connnow gives a thread the connection it already holds (tests/domain/test_store_reentrant.pycloses a generator mid-query and fails in time instead of hanging). Eight local survey runs after the fix: no hang.Motivation and Context
Adeel: the assistant had no idea about the platform, its capabilities, or general asks like the MCP address. This grounds it in Lens's docs and live instance facts through an internal tool.
Types of changes
!in the title)Checklist:
make hookschecks it on commit).tests/api/test_lens_help.py,tests/api/test_chat_export.py,tests/domain/test_store_reentrant.py,__tests__/chat.test.tsx).docs/accordingly (assistant.md "Questions about Lens itself" and thehelptool group, mcp.md, configuration.mdLENS_DOCS_DIR, schemas/chat-export.schema.json).## UnreleasedinCHANGELOG.md. n/a: the title says it.Done questions (AGENTS.md)
lens_helpis on the MCP server and in the assistant (web, voice, chat rooms, Telegram, Slack, email).docs/themselves; no new prerequisite or.envedit.ai.disabled_tools(Settings → AI assistant → Tools) turns it off, listed there with a label; no new setting otherwise.recording_id; the new fields are optional).make openapi).🤖 Generated with Claude Code
https://claude.ai/code/session_01YHrWfYDCaCbKKDX4w9at9C
Generated by Claude Code