MCPcopy Index your code
hub / github.com/coder/coder / fetchWorkspaceContext

Method fetchWorkspaceContext

coderd/x/chatd/chatd.go:8940–9013  ·  view source on GitHub ↗

fetchWorkspaceContext retrieves fresh instruction files and skills from the workspace agent without persisting. It handles agent connection, context configuration fetching, content sanitization, and metadata stamping. Returns the workspace agent, the stamped parts, discovered skills, and whether the

(
	ctx context.Context,
	chat database.Chat,
	getWorkspaceAgent func(context.Context) (database.WorkspaceAgent, error),
	getWorkspaceConn func(context.Context) (workspacesdk.AgentConn, error),
)

Source from the content-addressed store, hash-verified

8938// no valid workspace or the agent lookup failed;
8939// workspaceConnOK is false in that case.
8940func (p *Server) fetchWorkspaceContext(
8941 ctx context.Context,
8942 chat database.Chat,
8943 getWorkspaceAgent func(context.Context) (database.WorkspaceAgent, error),
8944 getWorkspaceConn func(context.Context) (workspacesdk.AgentConn, error),
8945) (agent *database.WorkspaceAgent, agentParts []codersdk.ChatMessagePart, discoveredSkills []chattool.SkillMeta, workspaceConnOK bool) {
8946 if !chat.WorkspaceID.Valid || getWorkspaceAgent == nil {
8947 return nil, nil, nil, false
8948 }
8949
8950 loadedAgent, agentErr := getWorkspaceAgent(ctx)
8951 if agentErr != nil {
8952 return nil, nil, nil, false
8953 }
8954
8955 directory := loadedAgent.ExpandedDirectory
8956 if directory == "" {
8957 directory = loadedAgent.Directory
8958 }
8959
8960 // Fetch context configuration from the agent. Parts
8961 // arrive pre-populated with context-file and skill entries
8962 // so we don't need additional round-trips.
8963 if getWorkspaceConn != nil {
8964 instructionCtx, cancel := context.WithTimeout(ctx, p.instructionLookupTimeout)
8965 defer cancel()
8966
8967 conn, connErr := getWorkspaceConn(instructionCtx)
8968 if connErr != nil {
8969 p.logger.Debug(ctx, "failed to resolve workspace connection for instruction files",
8970 slog.F("chat_id", chat.ID),
8971 slog.Error(connErr),
8972 )
8973 } else {
8974 workspaceConnOK = true
8975
8976 agentCfg, cfgErr := conn.ContextConfig(instructionCtx)
8977 if cfgErr != nil {
8978 p.logger.Debug(ctx, "failed to fetch context config from agent",
8979 slog.F("chat_id", chat.ID), slog.Error(cfgErr))
8980 // Treat a transient ContextConfig failure the
8981 // same as a failed connection so no sentinel is
8982 // persisted. The next turn will retry.
8983 workspaceConnOK = false
8984 } else {
8985 agentParts = agentCfg.Parts
8986 }
8987 }
8988 }
8989
8990 // Stamp server-side fields and sanitize content. The
8991 // agent cannot know its own UUID, OS metadata, or
8992 // directory — those are added here at the trust boundary.
8993 agentID := uuid.NullUUID{UUID: loadedAgent.ID, Valid: true}
8994
8995 for i := range agentParts {
8996 agentParts[i].ContextFileAgentID = agentID
8997 switch agentParts[i].Type {

Callers 1

Calls 4

SanitizePromptTextFunction · 0.85
ContextConfigMethod · 0.65
getWorkspaceAgentFunction · 0.50
ErrorMethod · 0.45

Tested by

no test coverage detected