Skip to content

Commit 9aeaba9

Browse files
authored
Merge pull request #252 from pylon-code/upstream/2026-09-02-server-perf
perf(server): adopt the upstream server performance pass
2 parents 5ac5778 + 02b9a45 commit 9aeaba9

38 files changed

Lines changed: 2528 additions & 279 deletions

apps/server/src/orchestration/ActivityPayloadProjection.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,28 @@ describe("projectActivityPayload", () => {
6464
expect(JSON.stringify(projected.payload).length).toBeLessThan(500);
6565
});
6666

67+
it("keeps preview normalization and fence-only fallback while scanning lines", () => {
68+
const preview = projectActivityPayload(
69+
activity({
70+
itemType: "command_execution",
71+
data: { rawOutput: `\`\`\`\n actual\tresult \n${"x".repeat(5000)}` },
72+
}),
73+
);
74+
const fences = projectActivityPayload(
75+
activity({
76+
itemType: "command_execution",
77+
data: { rawOutput: "```\r\n \t \n```\n" },
78+
}),
79+
);
80+
81+
expect((preview.payload as { data: { rawOutput: unknown } }).data.rawOutput).toEqual({
82+
content: "actual result",
83+
});
84+
expect((fences.payload as { data: { rawOutput: unknown } }).data.rawOutput).toEqual({
85+
content: "2 lines",
86+
});
87+
});
88+
6789
it("keeps bounded Claude and ACP command output summaries", () => {
6890
const claude = projectActivityPayload(
6991
activity({

apps/server/src/orchestration/ActivityPayloadProjection.ts

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -144,22 +144,29 @@ function projectCommandValue(data: Record<string, unknown>): unknown {
144144
}
145145

146146
function summarizeToolTextOutput(value: string): string | null {
147-
const lines: string[] = [];
148-
for (const rawLine of value.split(/\r?\n/u)) {
149-
const line = rawLine.replace(/\s+/g, " ").trim();
147+
let meaningfulLineCount = 0;
148+
let offset = 0;
149+
150+
while (offset <= value.length) {
151+
const newlineIndex = value.indexOf("\n", offset);
152+
const lineEnd = newlineIndex === -1 ? value.length : newlineIndex;
153+
const line = value.slice(offset, lineEnd).replace(/\s+/g, " ").trim();
150154
if (line.length > 0) {
151-
lines.push(line);
155+
meaningfulLineCount += 1;
156+
if (line !== "```") {
157+
const summary = line.length <= 84 ? line : `${line.slice(0, 83).trimEnd()}…`;
158+
// V8 can retain the full tool output behind a short sliced string.
159+
// Join a tiny character array so the returned preview owns its bytes.
160+
return Array.from(summary).join("");
161+
}
152162
}
163+
if (newlineIndex === -1) {
164+
break;
165+
}
166+
offset = newlineIndex + 1;
153167
}
154168

155-
const firstLine = lines.find((line) => line !== "```");
156-
if (firstLine) {
157-
return firstLine.length <= 84 ? firstLine : `${firstLine.slice(0, 83).trimEnd()}…`;
158-
}
159-
if (lines.length > 1) {
160-
return `${lines.length.toLocaleString()} lines`;
161-
}
162-
return null;
169+
return meaningfulLineCount > 1 ? `${meaningfulLineCount.toLocaleString()} lines` : null;
163170
}
164171

165172
/**
@@ -488,9 +495,6 @@ function toolLifecycleIdentity(activity: OrchestrationThreadActivity): string |
488495
* update within the turn — a later update belongs to a subsequent call that
489496
* reuses the same identity and is still in flight. Rows without a lifecycle
490497
* identity pass through, matching the clients, which never collapse them.
491-
* Live `thread.activity-appended` events are untouched: updates still stream
492-
* in real time and the completion supersedes them on the client as before.
493-
*
494498
* Deliberate divergence from client collapse: clients fold only *adjacent*
495499
* lifecycle rows, so a superseded update separated from its completion by an
496500
* interleaved parallel call renders as its own row today, and this drop
@@ -517,7 +521,7 @@ function dropSupersededToolUpdatedActivities(
517521
if (!identity) {
518522
continue;
519523
}
520-
const key = `${activity.turnId ?? ""}
524+
const key = `${activity.turnId ?? ""}\u0000${identity}`;
521525
const indices = completionIndicesByKey.get(key);
522526
if (indices) {
523527
indices.push(index);
@@ -537,7 +541,7 @@ function dropSupersededToolUpdatedActivities(
537541
if (!identity) {
538542
return true;
539543
}
540-
const indices = completionIndicesByKey.get(`${activity.turnId ?? ""}
544+
const indices = completionIndicesByKey.get(`${activity.turnId ?? ""}\u0000${identity}`);
541545
return !indices?.some((completionIndex) => completionIndex > index);
542546
});
543547
}

apps/server/src/orchestration/Layers/CheckpointReactor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ const make = Effect.gen(function* () {
176176

177177
const resolveThreadDetail = Effect.fn("resolveThreadDetail")(function* (threadId: ThreadId) {
178178
return yield* projectionSnapshotQuery
179-
.getThreadDetailById(threadId)
179+
.getThreadDetailById(threadId, { activityKinds: [] })
180180
.pipe(Effect.map(Option.getOrUndefined));
181181
});
182182

0 commit comments

Comments
 (0)