Skip to content

Enhancement: Support Agent Client Protocol to integrate crush with IDE's #990

Description

@deepakdinesh1123

Zed industries have created the Agent Client Protocol which makes it easier and sets a standard for integrating coding agents with IDE's that support the protocol.

Popular coding agents like gemini cli and claude code are already integrated into zed using the protocol and others may follow soon.

Crush could implement this protocol to integrate with IDE's rather than having to build a custom implementation for each IDE. I am trying to integrate crush with zed using ACP and did a minimal implementation to test it out. Please let me know your thoughts on this and whether this is something that crush would like to implement (happy to contribute in that case).

func (a *ACPAgent) Prompt(ctx context.Context, params acp.PromptRequest) (acp.PromptResponse, error) {
	_, err := a.app.Sessions.Get(ctx, string(params.SessionId))
	if err != nil {
		return acp.PromptResponse{}, fmt.Errorf("session %s not found", string(params.SessionId))
	}

	.....
	done, err := a.app.CoderAgent.Run(ctx, string(params.SessionId), content)
	if err != nil {
		return acp.PromptResponse{}, err
	}

	messageEvents := a.app.Messages.Subscribe(ctx)

	for {
		select {
		case result := <-done:
			if result.Error != nil {
				if errors.Is(result.Error, context.Canceled) || errors.Is(result.Error, agent.ErrRequestCancelled) {
					slog.Info("agent processing cancelled", "session_id", params.SessionId)
					return acp.PromptResponse{StopReason: acp.StopReasonCancelled}, nil
				}
				return acp.PromptResponse{StopReason: acp.StopReasonCancelled}, nil
			}
		case event, ok := <-messageEvents:
			if !ok {
				// Stream closed, agent finished
				return acp.PromptResponse{StopReason: acp.StopReasonEndTurn}, nil
			}

			switch event.Payload.Role {
			case message.Assistant:
				for _, part := range event.Payload.Parts {
					switch part := part.(type) {
					case message.ReasoningContent:
                                                  ....
					case message.BinaryContent:
					case message.ImageURLContent:
					case message.Finish:
					case message.TextContent:
						if a.conn != nil {
							if err := a.conn.SessionUpdate(ctx, acp.SessionNotification{
								SessionId: params.SessionId,
								Update: acp.SessionUpdate{
									AgentMessageChunk: &acp.SessionUpdateAgentMessageChunk{
										SessionUpdate: "agent_message_chunk",
										Content: acp.ContentBlock{
											Text: &acp.ContentBlockText{
												Text: part.Text,
												Type: "text",
											},
										},
									},
								},
							}); err != nil {
								slog.Error("error sending", "agent text chunk", err)
								continue
							}
						}
					case message.ToolCall:
					case message.ToolResult:
					}
				}
			case message.System:
			case message.Tool:
			case message.User:
			}
		}
	}

}

Ref: https://github.com/deepakdinesh1123/crush/blob/feat/acp/internal/acpagent/acp.go

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions