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

Method persistInstructionFiles

coderd/x/chatd/chatd.go:9021–9123  ·  view source on GitHub ↗

persistInstructionFiles fetches AGENTS.md instruction files and skills from the workspace agent, persisting both as message parts. This is called once when a workspace is first attached to a chat (or when the agent changes). Returns the formatted instruction string and skill index for injection into

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

Source from the content-addressed store, hash-verified

9019// instruction string and skill index for injection into the
9020// current turn's prompt.
9021func (p *Server) persistInstructionFiles(
9022 ctx context.Context,
9023 chat database.Chat,
9024 modelConfigID uuid.UUID,
9025 getWorkspaceAgent func(context.Context) (database.WorkspaceAgent, error),
9026 getWorkspaceConn func(context.Context) (workspacesdk.AgentConn, error),
9027) (instruction string, skills []chattool.SkillMeta, err error) {
9028 agent, agentParts, discoveredSkills, workspaceConnOK := p.fetchWorkspaceContext(
9029 ctx, chat, getWorkspaceAgent, getWorkspaceConn,
9030 )
9031 // Defensive guard: fetchWorkspaceContext returns nil when the
9032 // chat has no valid workspace or the agent lookup fails. It's
9033 // cheaper to guard here than push the precondition up to all
9034 // callers.
9035 if agent == nil {
9036 return "", nil, nil
9037 }
9038
9039 agentID := uuid.NullUUID{UUID: agent.ID, Valid: true}
9040 hasContent := false
9041 hasContextFilePart := false
9042 for _, part := range agentParts {
9043 if part.Type == codersdk.ChatMessagePartTypeContextFile {
9044 hasContextFilePart = true
9045 if part.ContextFileContent != "" {
9046 hasContent = true
9047 }
9048 }
9049 }
9050 directory := agent.ExpandedDirectory
9051 if directory == "" {
9052 directory = agent.Directory
9053 }
9054
9055 if !hasContent {
9056 if !workspaceConnOK {
9057 return "", nil, nil
9058 }
9059 // Persist a blank context-file marker (plus any skill-only
9060 // parts) so subsequent turns skip the workspace agent dial.
9061 if !hasContextFilePart {
9062 agentParts = append([]codersdk.ChatMessagePart{{
9063 Type: codersdk.ChatMessagePartTypeContextFile,
9064 ContextFileAgentID: agentID,
9065 }}, agentParts...)
9066 }
9067 content, err := chatprompt.MarshalParts(agentParts)
9068 if err != nil {
9069 return "", nil, nil
9070 }
9071 contextAPIKeyID, _ := aibridge.DelegatedAPIKeyIDFromContext(ctx)
9072 msgParams := database.InsertChatMessagesParams{ //nolint:exhaustruct // Fields populated by appendUserChatMessage.
9073 ChatID: chat.ID,
9074 }
9075 appendUserChatMessage(&msgParams, newUserChatMessage(
9076 contextAPIKeyID,
9077 content,
9078 database.ChatMessageVisibilityBoth,

Calls 11

fetchWorkspaceContextMethod · 0.95
MarshalPartsFunction · 0.92
appendUserChatMessageFunction · 0.85
newUserChatMessageFunction · 0.85
filterSkillPartsFunction · 0.85
formatSystemInstructionsFunction · 0.85
StripInternalMethod · 0.80
InsertChatMessagesMethod · 0.65
ErrorfMethod · 0.45