122 lines · 3.7 KB · Lua
RawDownload
-- plugins/tasks.lua-- Session task list as a single tool with an action verb.---- One tool with actions (add, list, done, remove) instead of four separate-- tools. Saves ~600 tokens per turn in schema overhead. local tasks = {}local next_id = 1 local function render()    if #tasks == 0 then        return "no tasks."    end    local lines = {}    for _, t in ipairs(tasks) do        lines[#lines + 1] = string.format(            "[%s] %d. %s", t.done and "x" or " ", t.id, t.text)    end    return table.concat(lines, "\n")end local function find(id)    for i, t in ipairs(tasks) do        if t.id == id then            return t, i        end    end    return nil, nilend clm.tool_register("tasks", {    description = "Manage the session task list. "        .. "Actions: add, list, done, remove, update.",    no_prompt = true,    params_schema = {        type = "object",        properties = {            action = {                type = "string",                description = "one of: add, list, done, remove, update",            },            text = {                type = "string",                description = "task description (required for add and update)",            },            id = {                type = "integer",                description = "task id (required for done, remove, and update)",            },        },        required = { "action" },    },    invoke = function(args, ctx)        local action = args.action         if action == "add" then            local text = args.text            if not text or text == "" then                ctx:fail("'add' requires a 'text' argument")                return            end            local t = { id = next_id, text = text, done = false }            next_id = next_id + 1            tasks[#tasks + 1] = t            ctx:complete(string.format("added task %d: %s", t.id, t.text))         elseif action == "list" then            ctx:complete(render())         elseif action == "done" then            local id = args.id            if type(id) ~= "number" then                ctx:fail("'done' requires an 'id' argument")                return            end            local t = find(id)            if not t then                ctx:fail(string.format("no task with id %d", id))                return            end            t.done = true            ctx:complete(string.format("completed task %d: %s", t.id, t.text))         elseif action == "remove" then            local id = args.id            if type(id) ~= "number" then                ctx:fail("'remove' requires an 'id' argument")                return            end            local t, idx = find(id)            if not t then                ctx:fail(string.format("no task with id %d", id))                return            end            table.remove(tasks, idx)            ctx:complete(string.format("removed task %d: %s", t.id, t.text))         elseif action == "update" then            local id = args.id            if type(id) ~= "number" then                ctx:fail("'update' requires an 'id' argument")                return            end            local text = args.text            if not text or text == "" then                ctx:fail("'update' requires a 'text' argument")                return            end            local t = find(id)            if not t then                ctx:fail(string.format("no task with id %d", id))                return            end            t.text = text            ctx:complete(string.format("updated task %d: %s", t.id, t.text))         else            ctx:fail("unknown action '" .. tostring(action)                .. "'; use add, list, done, remove, or update")        end    end,})