mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-08 20:58:45 +02:00
feat: support project copilot customization
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -183,6 +183,7 @@ public sealed class RunTurnCommandDto : SidecarCommandEnvelope
|
||||
public string WorkspaceKind { get; init; } = "project";
|
||||
public string Mode { get; init; } = "interactive";
|
||||
public string MessageMode { get; init; } = "enqueue";
|
||||
public string? ProjectInstructions { get; init; }
|
||||
public PatternDefinitionDto Pattern { get; init; } = new();
|
||||
public IReadOnlyList<ChatMessageDto> Messages { get; init; } = [];
|
||||
public RunTurnToolingConfigDto? Tooling { get; init; }
|
||||
|
||||
@@ -9,9 +9,11 @@ internal static class AgentInstructionComposer
|
||||
PatternAgentDefinitionDto agent,
|
||||
int agentIndex,
|
||||
string workspaceKind = "project",
|
||||
string interactionMode = "interactive")
|
||||
string interactionMode = "interactive",
|
||||
string? projectInstructions = null)
|
||||
{
|
||||
string baseInstructions = agent.Instructions.Trim();
|
||||
string repositoryInstructions = projectInstructions?.Trim() ?? string.Empty;
|
||||
string workspaceGuidance = string.Equals(workspaceKind, "scratchpad", StringComparison.OrdinalIgnoreCase)
|
||||
? """
|
||||
You are operating in scratchpad mode.
|
||||
@@ -46,12 +48,12 @@ internal static class AgentInstructionComposer
|
||||
Focus on refining the answer already in progress.
|
||||
""";
|
||||
|
||||
return JoinInstructionBlocks(baseInstructions, workspaceGuidance, planModeGuidance, groupChatGuidance);
|
||||
return JoinInstructionBlocks(baseInstructions, repositoryInstructions, workspaceGuidance, planModeGuidance, groupChatGuidance);
|
||||
}
|
||||
|
||||
if (!string.Equals(pattern.Mode, "handoff", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return JoinInstructionBlocks(baseInstructions, workspaceGuidance, planModeGuidance);
|
||||
return JoinInstructionBlocks(baseInstructions, repositoryInstructions, workspaceGuidance, planModeGuidance);
|
||||
}
|
||||
|
||||
string runtimeGuidance = agentIndex == 0
|
||||
@@ -69,7 +71,7 @@ internal static class AgentInstructionComposer
|
||||
Do not push the actual work back to triage unless you are blocked or the request is clearly outside your specialty.
|
||||
""";
|
||||
|
||||
return JoinInstructionBlocks(baseInstructions, workspaceGuidance, planModeGuidance, runtimeGuidance);
|
||||
return JoinInstructionBlocks(baseInstructions, repositoryInstructions, workspaceGuidance, planModeGuidance, runtimeGuidance);
|
||||
}
|
||||
|
||||
private static string JoinInstructionBlocks(params string[] blocks)
|
||||
|
||||
@@ -103,7 +103,8 @@ internal sealed class CopilotAgentBundle : IAsyncDisposable
|
||||
definition,
|
||||
agentIndex,
|
||||
command.WorkspaceKind,
|
||||
command.Mode),
|
||||
command.Mode,
|
||||
command.ProjectInstructions),
|
||||
},
|
||||
WorkingDirectory = command.ProjectPath,
|
||||
OnPermissionRequest = onPermissionRequest,
|
||||
|
||||
@@ -151,6 +151,39 @@ public sealed class AgentInstructionComposerTests
|
||||
Assert.Contains("Do not continue into implementation", instructions, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Compose_InsertsProjectInstructionsBetweenBaseAndRuntimeGuidance()
|
||||
{
|
||||
PatternDefinitionDto pattern = new()
|
||||
{
|
||||
Id = "pattern-single",
|
||||
Name = "Single",
|
||||
Mode = "single",
|
||||
Availability = "available",
|
||||
};
|
||||
PatternAgentDefinitionDto agent = CreateAgent(
|
||||
id: "agent-primary",
|
||||
name: "Primary Agent",
|
||||
instructions: "You are a helpful assistant.");
|
||||
|
||||
string instructions = AgentInstructionComposer.Compose(
|
||||
pattern,
|
||||
agent,
|
||||
agentIndex: 0,
|
||||
workspaceKind: "scratchpad",
|
||||
projectInstructions: "Follow the repository guide.");
|
||||
|
||||
Assert.Contains("You are a helpful assistant.", instructions, StringComparison.Ordinal);
|
||||
Assert.Contains("Follow the repository guide.", instructions, StringComparison.Ordinal);
|
||||
Assert.Contains("scratchpad mode", instructions, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.True(
|
||||
instructions.IndexOf("You are a helpful assistant.", StringComparison.Ordinal)
|
||||
< instructions.IndexOf("Follow the repository guide.", StringComparison.Ordinal));
|
||||
Assert.True(
|
||||
instructions.IndexOf("Follow the repository guide.", StringComparison.Ordinal)
|
||||
< instructions.IndexOf("scratchpad mode", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private static PatternAgentDefinitionDto CreateAgent(string id, string name, string instructions)
|
||||
{
|
||||
return new PatternAgentDefinitionDto
|
||||
|
||||
@@ -250,6 +250,43 @@ public sealed class CopilotAgentBundleTests
|
||||
Assert.NotNull(sessionConfig.Hooks);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateSessionConfig_PassesProjectInstructionsIntoTheSystemMessage()
|
||||
{
|
||||
RunTurnCommandDto command = new()
|
||||
{
|
||||
SessionId = "session-1",
|
||||
ProjectPath = @"C:\workspace\project",
|
||||
WorkspaceKind = "project",
|
||||
Mode = "interactive",
|
||||
ProjectInstructions = "Follow repository guidance.",
|
||||
Pattern = new PatternDefinitionDto
|
||||
{
|
||||
Id = "pattern-1",
|
||||
Name = "Pattern",
|
||||
Mode = "single",
|
||||
Availability = "available",
|
||||
Agents =
|
||||
[
|
||||
new PatternAgentDefinitionDto
|
||||
{
|
||||
Id = "agent-1",
|
||||
Name = "Primary",
|
||||
Model = "gpt-5.4",
|
||||
Instructions = "Help.",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
SessionConfig sessionConfig = CopilotAgentBundle.CreateSessionConfig(
|
||||
command,
|
||||
command.Pattern.Agents[0],
|
||||
agentIndex: 0);
|
||||
|
||||
Assert.Equal("Help.\n\nFollow repository guidance.", sessionConfig.SystemMessage?.Content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CopilotSessionHooks_Create_UsesApprovalPolicyForPreToolUse()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user