Skip to content

Commit bd438fb

Browse files
authored
fix(acp): preserve native slash command prompt shape (pingdotgg#19393)
1 parent 0b896d9 commit bd438fb

2 files changed

Lines changed: 39 additions & 25 deletions

File tree

‎apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts‎

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -511,19 +511,19 @@ function rawProtocolRequestParam(
511511
return typeof params === "object" && params !== null ? Reflect.get(params, key) : undefined;
512512
}
513513

514-
function rawProtocolPromptText(event: EffectAcpProtocol.AcpProtocolLogEvent): string {
514+
function rawProtocolPromptTextBlocks(
515+
event: EffectAcpProtocol.AcpProtocolLogEvent,
516+
): Array<{ type: "text"; text: string }> {
515517
const prompt = rawProtocolRequestParam(event, "prompt");
516-
if (!Array.isArray(prompt)) return "";
517-
return prompt
518-
.flatMap((block) =>
519-
typeof block === "object" &&
520-
block !== null &&
521-
Reflect.get(block, "type") === "text" &&
522-
typeof Reflect.get(block, "text") === "string"
523-
? [Reflect.get(block, "text") as string]
524-
: [],
525-
)
526-
.join("\n");
518+
if (!Array.isArray(prompt)) return [];
519+
return prompt.flatMap((block) =>
520+
typeof block === "object" &&
521+
block !== null &&
522+
Reflect.get(block, "type") === "text" &&
523+
typeof Reflect.get(block, "text") === "string"
524+
? [{ type: "text" as const, text: Reflect.get(block, "text") as string }]
525+
: [],
526+
);
527527
}
528528

529529
const pollProtocolMethods = (events: Queue.Queue<EffectAcpProtocol.AcpProtocolLogEvent>) =>
@@ -841,15 +841,26 @@ describe("AcpAdapterV2", () => {
841841
if (method === undefined) continue;
842842
methods.push(method);
843843
if (method === "session/prompt") {
844-
return { methods, prompt: rawProtocolPromptText(event) };
844+
const promptBlocks = rawProtocolPromptTextBlocks(event);
845+
return {
846+
methods,
847+
prompt: promptBlocks.map((block) => block.text).join("\n"),
848+
textBlockCount: promptBlocks.length,
849+
};
845850
}
846851
}
847852
});
848853

849854
const command = yield* runTurn(0, defaultPolicy, "/compact");
850855
assert.isTrue(command.prompt.startsWith("/compact"));
851856
assert.notInclude(command.prompt, "<t3_code_instructions>");
852-
const firstDefault = yield* runTurn(1, defaultPolicy, "First default request.");
857+
assert.equal(command.textBlockCount, 1);
858+
const whitespaceCommand = yield* runTurn(1, defaultPolicy, " /repro-skill");
859+
assert.equal(whitespaceCommand.prompt, " /repro-skill");
860+
assert.equal(whitespaceCommand.textBlockCount, 1);
861+
assert.notInclude(whitespaceCommand.prompt, "<t3_code_instructions>");
862+
const firstDefault = yield* runTurn(2, defaultPolicy, "First default request.");
863+
assert.equal(firstDefault.textBlockCount, 2);
853864
assert.include(firstDefault.prompt, "T3 Code interaction mode: Default");
854865
assert.include(firstDefault.prompt, "T3 Code collaborative browser");
855866
assert.include(firstDefault.prompt, "T3 Code orchestration");
@@ -859,19 +870,19 @@ describe("AcpAdapterV2", () => {
859870
"Build should preserve the agent's advertised mode default",
860871
);
861872
assert.include(
862-
(yield* runTurn(2, defaultPolicy, "Second default request.")).prompt,
873+
(yield* runTurn(3, defaultPolicy, "Second default request.")).prompt,
863874
"Second default request.",
864875
);
865876

866877
const planPolicy = policy("plan");
867-
const firstPlan = yield* runTurn(3, planPolicy, "Plan this change.");
878+
const firstPlan = yield* runTurn(4, planPolicy, "Plan this change.");
868879
assert.include(firstPlan.prompt, "T3 Code interaction mode: Plan");
869880
assert.include(firstPlan.methods, "session/set_config_option");
870881
assert.include(
871-
(yield* runTurn(4, planPolicy, "Continue planning.")).prompt,
882+
(yield* runTurn(5, planPolicy, "Continue planning.")).prompt,
872883
"Continue planning.",
873884
);
874-
const restoredBuild = yield* runTurn(5, defaultPolicy, "Implement the change.");
885+
const restoredBuild = yield* runTurn(6, defaultPolicy, "Implement the change.");
875886
assert.include(restoredBuild.prompt, "T3 Code interaction mode: Default");
876887
assert.include(
877888
restoredBuild.methods,

‎packages/provider-acp/src/server/adapter.ts‎

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6316,6 +6316,7 @@ export const makeAcpAdapterV2 = Effect.fn("makeAcpAdapterV2")(function* (
63166316
attachments: turnInput.message.attachments,
63176317
resolveAttachmentPath: host.resolveAttachmentPath,
63186318
});
6319+
const isNativeSlashCommand = turnInput.message.text.trimStart().startsWith("/");
63196320
const text = t3AcpPromptWithInstructions({
63206321
prompt: messageText,
63216322
state: instructionState,
@@ -6365,13 +6366,15 @@ export const makeAcpAdapterV2 = Effect.fn("makeAcpAdapterV2")(function* (
63656366
detail: "ACP turn requires non-empty text or attachments",
63666367
});
63676368
}
6368-
prompt.push({
6369-
type: "text",
6370-
text: buildRuntimeInstructions({
6371-
harness: flavor.runtimeHarness ?? driver,
6372-
model: turnInput.modelSelection.model,
6373-
}),
6374-
});
6369+
if (!isNativeSlashCommand) {
6370+
prompt.push({
6371+
type: "text",
6372+
text: buildRuntimeInstructions({
6373+
harness: flavor.runtimeHarness ?? driver,
6374+
model: turnInput.modelSelection.model,
6375+
}),
6376+
});
6377+
}
63756378
return { prompt, instructionState: text === messageText ? undefined : instructionState };
63766379
});
63776380

0 commit comments

Comments
 (0)