Skip to content

Leafdesk 0.5.2

Choose a tag to compare

@erhanerbas erhanerbas released this 15 Oct 08:59

Upgrading from 0.5.1

  • Migrations (0060–0067) run automatically when the container starts. Nothing changes in
    docker-compose.yml or .env.
  • The AI chat's memory is on. Where AI is on, the chat may keep notes about the people who use
    it (asking them first, unless the mode is Auto), and agents' runs may propose notes for owners
    to review. Owners who don't want it turn it off per workspace under Settings → General → AI →
    AI memory; each person can also turn it off for themselves in the Memory dialog.
  • Write tokens and MCP apps reach agents. For a workspace owner, an API token or MCP app with
    pages:write can now change the workspace's agents (pause them, set a monthly token limit) and
    ask them for runs, which use the workspace's AI allowance. Give integrations that only read a
    pages:read token, or let apps only read under Settings → Security.
  • Apps that reach a workspace show when each app or token last reached it from this version
    on; earlier use isn't known.

Added

  • Memory for the AI chat. The chat keeps short notes about each person in a workspace (who
    they are, what they work on, how they want answers) when they tell it about themselves or ask it
    to remember something, and drops one when asked to forget, with new remember and forget tools
    offered in every mode. Unless the mode is Auto, the chat asks the person (Yes or No) before
    it keeps or drops a note, also in Read only, so text it read can't slip in a lasting note; each
    note kept, dropped or declined shows among the answer's steps and is kept with the conversation
    also when the answer fails, and Answer again carries it to the new answer. Only what the
    person says in their questions is kept, never what pages or tool results say. The notes go with
    the person's later questions in that workspace as data, never with anyone else's or in another
    workspace, and never widen what the chat may read or change. The new Memory dialog (the brain
    button in the chat's header and panel) lists them, adds, changes and deletes notes, and forgets
    everything. Up to 30 notes of 300 characters per person and workspace; they are deleted when the
    person leaves the workspace or deletes their account. Migration 0063_ai_memory adds
    ai_memory. Covered in scripts/ai-memory-e2e.ts.
  • Switches for the AI chat's memory. Use memory at the top of the Memory dialog turns the
    memory off for the person in that workspace, and owners can turn it off for the whole workspace
    under Settings → General → AI → AI memory, which also hides the Memory button. While it is
    off, questions carry no notes and the chat isn't offered remember or forget; no note is
    deleted, and owners' changes are in the audit log. Migration 0064_ai_memory_switch adds
    workspace_member.ai_memory. Covered in scripts/ai-memory-e2e.ts and
    scripts/ai-chat-e2e.ts.
  • Memory for agents. Agents keep short notes that go with each of their runs (where things go
    in the workspace, how a recurring case is handled). Because everything a run reads was written by
    someone else, a run only proposes notes, with a new remember tool: each proposal shows among the
    run's steps, with credentials masked, and goes with no run until an owner keeps it. The agent's
    new Memory tab (and a "notes to review" link in the list of agents) shows proposals with the run's
    row and time, to keep as they are or changed, or dismiss; owners also write, change and delete
    notes and make the agent forget everything. A proposal from a row an owner can't open is shown to
    them without its text, and only dismissed. Runs drop notes at once with forget. Runs no member
    stands behind (anonymous or outside form answers, untrusted triggers) get neither tool but still
    get the kept notes, which reach the model as data inside <memory> and never widen what it may
    change. Up to 30 notes of 300 characters per agent and 10 proposals waiting; an unanswered
    proposal goes with its run after 30 days. The workspace's AI memory switch holds for agents
    too: off, runs carry no notes and propose none. Changes are recorded in the audit log, counted. MCP's
    get_agent lists the notes and proposals. Migration 0065_agent_memory adds status and
    agent_run_id to ai_memory. Covered in scripts/agent-memory-e2e.ts.
  • Owners hear of an agent's proposed notes. When a run proposes a note, each owner of the
    workspace gets one inbox item for that run, pushed too (without the note's text) and never
    emailed, whatever their notification choices. It shows the first proposal's text, unless the run
    was on a row that owner can't open, and how many more there are; it opens the agent's Memory
    tab (?tab=agents&agent=<id>&agentTab=memory), can be snoozed, and goes away once every proposal
    of the run is kept or dismissed. Answering an agent's call no longer takes the run's other inbox
    items with it. MCP adds keep_agent_memory and dismiss_agent_memory for proposals, and
    add_agent_memory, update_agent_memory and delete_agent_memory for an owner's own notes,
    each answering with the agent's memory as get_agent shows it; list_notifications summarizes
    the new item. Migration 0066_agent_memory_notice lets agent_memory notifications have no page
    and keeps one per run and owner. Covered in scripts/agent-memory-e2e.ts and scripts/mcp-e2e.ts.
  • Skills. A page or database row can be marked Use as skill in its ⋯ menu (edit access;
    not databases, templates or the pages in them): its body is instructions to reuse, and a bar
    under the title says what it is for. The sidebar's new skills button opens the workspace's
    skills library (searchable, with New skill). In the AI chat, / at the start of the empty box
    picks a skill whose instructions the next question follows, without widening what the chat may
    change; the question keeps it, and Answer again and Edit use it again. MCP clients get
    list_skills, get_skill (which refuses a title several skills share) and set_skill,
    get_page says whether a page is a skill, and every skill the user can open is also a prompt of
    its name, unique across their workspaces. The page
    menu and the library export a skill as a ZIP holding <name>/SKILL.md. Skills follow page
    access everywhere and leave every list while in the trash. Migration 0060_skills adds
    page.is_skill and page.skill_description. Covered in scripts/skills-e2e.ts and
    scripts/mcp-e2e.ts.
  • Skills for agents. An agent's new Skills tab gives it up to 10 skills of the workspace,
    whose instructions each run sends to the model after the agent's own. Only skills no one besides
    the workspace's owners can edit (not members, teamspaces, groups, guests or agents, the agent
    itself included) can be given; a run checks again and leaves out, saying so in its steps, a skill
    someone else can edit by then, one no longer marked as a skill, or one that doesn't fit in what a
    run may read (12,000 characters together), and the tab shows each skill's state. A run started
    by a member's change or a public form leaves out the skills that person can't open, and a run
    that goes on after an approval checks its skills again. MCP clients get set_agent_skill, and
    get_agent lists the agent's skills. Giving and taking a skill is recorded in the audit log.
    Migration 0061_agent_skills adds agent_skill. Covered in scripts/agent-skills-e2e.ts.
  • Apps that reach a workspace. Settings → Security shows its owners the MCP apps the
    workspace's people connected and their REST API tokens for it, with what each may do, who
    connected it and when it last reached this workspace (not before this version), the 100 apps
    and 100 tokens used here most recently first. An owner can
    disconnect one person's app or revoke their token; as both belong to the person, it stops
    reaching all of their workspaces, and this workspace's audit log records it with the owner as
    who did it. Migration 0062_connected_app_use adds connected_app_use. Covered in
    scripts/workspace-apps-e2e.ts.
  • About. Settings (and the account page) have an About tab: the Leafdesk version the server
    runs with a link to its release notes, who makes it, the license, the website, the source code,
    where to report a problem and the third-party notices. The version is read from package.json,
    which the MCP server now reports too. No migration.
  • Copy ID. A page's, database's or row's menu (also in the row panel) has Copy ID, and a
    column's menu, in the table and on a row's page, Copy property ID: the ids the REST API and MCP
    clients take, where a property's name may change. No migration.
  • High contrast. Settings → Preferences → Appearance has Contrast: follow the system (its
    "increase contrast" setting, prefers-contrast: more), Standard or High, kept for the
    browser in a cookie like the theme and carried by <html data-contrast>. High contrast keeps
    the backgrounds and makes, in either theme, secondary text at least 7:1 on the page and 4.5:1 on
    hovered and selected rows, faint text (hints, placeholders) at least 4.5:1 everywhere, lines and
    control edges at least 3:1, the accent and danger colors stronger and the focus ring more opaque; colored and black page backgrounds get the same lines
    and text. The editor follows, as it draws with the same colors. src/lib/contrast.test.ts
    checks the ratios from globals.css. No migration.
  • Agents in the Share menu. Typing in a page's Share menu finds the workspace's agents by name
    too (archived ones aren't offered; a paused one says so) for members with full access to the
    page; one picked starts at Can view, as from the agent's settings. An agent's row shows its
    icon and "Agent", and its levels are view, comment and edit only. The server already let anyone
    with full access to a page share it with an agent; the menu now offers it.
  • Agents over the REST API, and runs owners ask for. New endpoints list a workspace's agents
    (GET /workspaces/{id}/agents), read and change one (GET and PATCH /agents/{id}: settings,
    pausing and resuming, the monthly token limit), ask one for a task now
    (POST /agents/{id}/runs), and read its runs (GET /agents/{id}/runs,
    GET /agents/{id}/runs/{run_id}) and usage (GET /agents/{id}/usage), owners only except the
    list. MCP clients get start_agent_run. A run an owner asks for works on a database row (and may
    change and comment on it) or on none (it only reads and answers), held to the owner's access as
    well as the agent's; it shows who asked, from where and the task, and each request is recorded in
    the audit log. Asking is refused with 409 while the agent is paused or archived or AI is off
    (agent_unavailable), once it used its monthly limit (limit_reached), or while 5 runs asked of
    it still wait (too_many_runs). Covered in scripts/agent-api-e2e.ts.
  • Agents' usage and a monthly token limit. Each turn a run takes is added to the agent's usage
    for the calendar month (UTC): runs, input and output tokens and cost, kept for 12 months. The
    agent's Runs tab shows this month against its limit and the months before; MCP's get_agent
    shows them too. An owner can set a monthly token limit in the agent's settings (or with
    update_agent and PATCH /agents/{id}): once the month reaches it, a run under way stops at its
    next turn as limitReached and no run starts until the next month. Migration 0067_agent_usage
    adds agent_usage and workspace_agent.monthly_token_limit. Covered in
    scripts/agent-api-e2e.ts.
  • Dashboards. The /dashboard block shows numbers, charts and lists from any of the
    workspace's databases on one page, in a grid of up to 12 widgets that each take a quarter, half,
    three quarters or all of its width (two columns on narrow pages, one on phones), and that can be
    moved and removed from their menu. A widget is a database seen through its own view: a new
    Number chart type gives one value (a count, or a sum, average or other calculation over the
    rows its filters keep), charts and lists are worked out on the server for each reader (only the
    rows and values they may see, and no rows sent for a chart), and other layouts show as a linked
    view. Widgets are set up in place with the linked view's own toolbar, update while their rows
    change, say under them how many rows they count, by what, with how many filters and when, and
    open the rows behind a number, bar or slice. A widget on a database the reader can't open says
    only that. Published pages show numbers and lists, and charts as a table of their figures; a
    widget on a database outside the publication shows nothing of it. In Markdown a dashboard is the
    line <!-- leafdesk:dashboard <id> -->, which keeps it through a rewrite. MCP's new
    add_dashboard and update_dashboard_widget add a dashboard and add, change, move or remove its
    widgets, and get_page lists dashboards and their widgets. Copies of published pages keep the
    widgets whose database was copied too. No migration. Covered in scripts/dashboard-e2e.ts.
  • Colored dashboard widgets. A widget's menu has a Color row: a widget can take one of the
    option colors as its background, the same light tint board columns use, in light and dark
    themes. Published pages and the print view show the color too. MCP's add_dashboard and
    update_dashboard_widget take color ("none" for a plain box), and get_page lists each
    widget's color. Covered in scripts/dashboard-e2e.ts.

Changed

  • Published charts show their figures. A chart view on a published page (a published
    database's tab or a linked view in its body) shows its number, or a table of each group's value
    (and each stacked series'), worked out on the server from the public properties only, instead of
    a table of its rows; no rows are sent. A chart grouped or measured by a property visitors can't
    see shows nothing to group by, or counts rows. Covered in scripts/chart-e2e.ts.
  • Dashboards do less work. An open dashboard used to reload every widget whenever any page in
    the workspace was created, renamed, moved or shared. Now a widget reloads when its own database's
    rows or properties change. Changes elsewhere in the workspace cost one request for the whole
    dashboard, which checks its databases' names, icons, trash state and the reader's access, and
    only the widgets of a database that changed reload. Sharing a single row now also refreshes open
    views of its database. A published or printed page reads each database once, however many
    widgets and database blocks show it, and each widget still applies its own filters, chart and
    list length. Covered in scripts/dashboard-e2e.ts.

Fixed

  • A level set for an agent stays when an automation lets go. An automation that runs an agent
    gives it edit access to its database and gives back the agent's previous level once no
    automation runs it. A level someone set or removed meanwhile from the Share menu was overwritten
    then (only the agent's settings counted as setting it); now any change to the agent's own entry
    keeps it. Covered in scripts/agents-e2e.ts.
  • Sign-in recovers when the database was down at startup. The sign-in library queries the
    database when it is set up, and it was set up once, when the server loaded it: if the database
    couldn't be reached then, sign-in, sessions, MCP and its keys kept failing until a restart. It
    is now set up on first use and again after a failed setup, and next build no longer logs a
    failed query from every worker.
  • list_agent_runs names the waiting status as it returns it. Its description said
    waiting_for_approval for a run that waits for an owner; runs come back as awaiting_approval.