Skip to content

feat(context)!: switch from contexts to function calling #1029

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 72 commits into from
Jul 28, 2025

Conversation

deathbeam
Copy link
Collaborator

@deathbeam deathbeam commented Mar 17, 2025

BEGIN_COMMIT_OVERRIDE
feat(context)!: switch from contexts to function calling

This change modernizes the CopilotChat architecture by implementing a tools-based
approach using function calling. Each tool has a schema definition that enables
structured parameter collection and validation. Resources are now handled more
consistently, with a clearer distinction between content types.

https://platform.openai.com/docs/guides/function-calling?api-mode=responses
https://modelcontextprotocol.info/specification/2024-11-05/server/tools/

BREAKING CHANGE: Multiple breaking changes due to big refactor:

  • The context API has changed from callback-based input handling to schema-based definitions.
  • config.contexts renamed to config.tools
  • config.context removed, use config.sticky
  • diagnostics moved to separate tool call, selection and buffer calls no longer include them by default
  • non-resource based tool calls can no longer be soft stored in sticky, now they are auto expanded to prompt
  • gi renamed to gc, now also includes selection
  • filenames renamed to glob
  • files removed (use glob together with tool calling instead, or buffers/quickfix)
  • copilot extension agents removed, tools + mcp servers can replace this feature and maintaining them was pain, they can still be implemented via custom providers anyway
  • actions and integrations action removed as they were deprecated for a while
  • config.questionHeader, config.answerHeader moved to config.headers.user/config.headers.assistant

Closes #1045
Closes #1053
Closes #1076
Closes #1090
Closes #1096
Closes #526

END_COMMIT_OVERRIDE

TODO:

  • Improve response format from contexts
  • Maybe rename contexts to tools?
  • Add names of tool to embedded context value
  • Inline contexts/tools - expand directly to user prompt
  • Split diagnostics to separate context
  • Mark built in tools as safe, mark everything else unsafe
  • How to resolve MCP resources? How to resolve built in resources? Currently hardcoded for file and url, not good
  • Rest of commands resources for reuse? git?
  • Properly store tool responses using "tool" role and also send tool_calls in history
    • When tool_call response is received, new tool_call prompt, user submitable, editable, sends only tools
    • On submit replace with tool_call responses, send proper "tool" role, wait response
  • Parse resource template to schema for input, pass uri to input for resolution
  • Rename agent to group, allow sharing single tools as well

https://github.com/ravitemer/mcphub.nvim integration:

local mcp = require('mcphub')
mcp.setup()
mcp.on({ 'servers_updated', 'tool_list_changed', 'resource_list_changed' }, function()
    local hub = mcp.get_hub_instance()
    if not hub then
        return
    end

    local async = require('plenary.async')
    local call_tool = async.wrap(function(server, tool, input, callback)
        hub:call_tool(server, tool, input, {
            callback = function(res, err)
                callback(res, err)
            end,
        })
    end, 4)

    local access_resource = async.wrap(function(server, uri, callback)
        hub:access_resource(server, uri, {
            callback = function(res, err)
                callback(res, err)
            end,
        })
    end, 3)

    local resources = hub:get_resources()
    for _, resource in ipairs(resources) do
        local name = resource.name:lower():gsub(' ', '_'):gsub(':', '')
        chat.config.functions[name] = {
            uri = resource.uri,
            description = type(resource.description) == 'string' and resource.description or '',
            resolve = function()
                local res, err = access_resource(resource.server_name, resource.uri)
                if err then
                    error(err)
                end

                res = res or {}
                local result = res.result or {}
                local content = result.contents or {}
                local out = {}

                for _, message in ipairs(content) do
                    if message.text then
                        table.insert(out, {
                            uri = message.uri,
                            data = message.text,
                            mimetype = message.mimeType,
                        })
                    end
                end

                return out
            end
        }
    end

    local tools = hub:get_tools()
    for _, tool in ipairs(tools) do
        chat.config.functions[tool.name] = {
            group = tool.server_name,
            description = tool.description,
            schema = tool.inputSchema,
            resolve = function(input)
                local res, err = call_tool(tool.server_name, tool.name, input)
                if err then
                    error(err)
                end

                res = res or {}
                local result = res.result or {}
                local content = result.content or {}
                local out = {}

                for _, message in ipairs(content) do
                    if message.type == 'text' then
                        table.insert(out, {
                            data = message.text
                        })
                    elseif message.type == 'resource' and message.resource and message.resource.text then
                        table.insert(out, {
                            uri = message.resource.uri,
                            data = message.resource.text,
                            mimetype = message.resource.mimeType,
                        })
                    end
                end

                return out
            end
        }
    end
end)

@deathbeam deathbeam added the enhancement New feature or request label Mar 17, 2025
@deathbeam deathbeam force-pushed the tools branch 5 times, most recently from 7885523 to 41c7751 Compare March 17, 2025 19:14
@deathbeam deathbeam marked this pull request as ready for review March 17, 2025 19:17
@deathbeam deathbeam force-pushed the tools branch 5 times, most recently from 24fed0a to b6c7b19 Compare March 17, 2025 20:00
@deathbeam deathbeam changed the title feat(context): implement schema-based input for providers feat(context)!: implement schema-based input for providers Mar 17, 2025
@deathbeam deathbeam changed the title feat(context)!: implement schema-based input for providers feat(context)!: implement schema-based input for contexts Mar 17, 2025
@deathbeam deathbeam force-pushed the tools branch 2 times, most recently from a23ccfa to eaba359 Compare March 17, 2025 20:03
@deathbeam deathbeam changed the title feat(context)!: implement schema-based input for contexts feat(context)!: implement schema-based context providers Mar 17, 2025
@deathbeam deathbeam changed the title feat(context)!: implement schema-based context providers feat(context)!: implement schema-based contexts Mar 17, 2025
@deathbeam deathbeam force-pushed the tools branch 8 times, most recently from f4e0432 to cc4b04f Compare March 17, 2025 21:24
@deathbeam deathbeam marked this pull request as draft March 17, 2025 21:33
@deathbeam deathbeam force-pushed the tools branch 2 times, most recently from baa2848 to 7604698 Compare March 18, 2025 08:46
deathbeam added 23 commits July 10, 2025 20:09
* main:
  chore(doc): auto generate docs
  Properly null check opts.glob when rigpgrep is not available (CopilotC-Nvim#1183)
  docs: add adborden as a contributor for code (CopilotC-Nvim#1171)
  fix: CopilotC-Nvim#1153 use filepath on accept (CopilotC-Nvim#1170)
  chore(doc): auto generate docs
  chore(main): release 3.12.1 (CopilotC-Nvim#1164)
  docs: add fredrikaverpil as a contributor for code (CopilotC-Nvim#1165)
  chore(doc): auto generate docs
  fix: move plenary import into function (CopilotC-Nvim#1162)
  chore(doc): auto generate docs
  chore(main): release 3.12.0 (CopilotC-Nvim#1131)
  docs: add azdanov as a contributor for doc, and code (CopilotC-Nvim#1130)
  chore(doc): auto generate docs
  docs: update mentions of default model to gpt-4.1
  feat: switch to new default model gpt-4.1
  chore(doc): auto generate docs
  chore(main): release 3.11.1 (CopilotC-Nvim#1116)
  chore(doc): auto generate docs
  [pre-commit.ci] pre-commit autoupdate
Signed-off-by: Tomas Slusny <[email protected]>
Signed-off-by: Tomas Slusny <[email protected]>
Signed-off-by: Tomas Slusny <[email protected]>
Signed-off-by: Tomas Slusny <[email protected]>
Signed-off-by: Tomas Slusny <[email protected]>
Signed-off-by: Tomas Slusny <[email protected]>
Signed-off-by: Tomas Slusny <[email protected]>
Signed-off-by: Tomas Slusny <[email protected]>
Signed-off-by: Tomas Slusny <[email protected]>
Signed-off-by: Tomas Slusny <[email protected]>
Signed-off-by: Tomas Slusny <[email protected]>
Signed-off-by: Tomas Slusny <[email protected]>
Signed-off-by: Tomas Slusny <[email protected]>
Signed-off-by: Tomas Slusny <[email protected]>
@deathbeam
Copy link
Collaborator Author

image

did not rly had time to work on this at all in past few months but I think I got nice interface now working with separate tool call message and proper highlights so its clearly visible what is happening

@deathbeam
Copy link
Collaborator Author

So only 1 thing remains and that is better resource template handling, but I think I can just skip it for now, so will test this a bit more (any more testing would be helpful too) and then probably merge, but its a lot of breaking changes to configs and everything

* main:
  docs: add AtifChy as a contributor for code, and doc (CopilotC-Nvim#1192)
  chore(doc): auto generate docs
  feat: add Windows_NT support in Makefile and dynamic library loading (CopilotC-Nvim#1190)
  chore(doc): auto generate docs
  chore(main): release 3.12.2 (CopilotC-Nvim#1172)
@deathbeam deathbeam merged commit 057b8e4 into CopilotC-Nvim:main Jul 28, 2025
3 of 4 checks passed
@deathbeam
Copy link
Collaborator Author

Well lets see if this works :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
7 participants