Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions apps/server/src/auth/Layers/AuthControlPlane.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,16 @@ export const makeAuthControlPlane = Effect.gen(function* () {

const listPairingLinks: AuthControlPlaneShape["listPairingLinks"] = (input) =>
bootstrapCredentials.listActive().pipe(
Effect.map((pairingLinks) =>
pairingLinks
.filter((pairingLink) => (input?.role ? pairingLink.role === input.role : true))
.filter((pairingLink) => !input?.excludeSubjects?.includes(pairingLink.subject))
.map((pairingLink) =>
Effect.map((pairingLinks) => {
const activeLinks: Array<AuthPairingLink> = [];
for (const pairingLink of pairingLinks) {
if (input?.role && pairingLink.role !== input.role) {
continue;
}
if (input?.excludeSubjects?.includes(pairingLink.subject)) {
continue;
}
activeLinks.push(
pairingLink.label
? ({
id: pairingLink.id,
Expand All @@ -87,11 +92,12 @@ export const makeAuthControlPlane = Effect.gen(function* () {
createdAt: pairingLink.createdAt,
expiresAt: pairingLink.expiresAt,
} satisfies AuthPairingLink),
)
.toSorted(
(left, right) => right.createdAt.epochMilliseconds - left.createdAt.epochMilliseconds,
),
),
);
}
return activeLinks.toSorted(
(left, right) => right.createdAt.epochMilliseconds - left.createdAt.epochMilliseconds,
);
}),
Effect.mapError(toAuthControlPlaneError("Failed to list pairing links.")),
);

Expand Down
12 changes: 8 additions & 4 deletions apps/server/src/git/remoteRefs.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
export function parseRemoteNamesInGitOrder(stdout: string): ReadonlyArray<string> {
return stdout
.split("\n")
.map((line) => line.trim())
.filter((line) => line.length > 0);
const remoteNames: Array<string> = [];
for (const line of stdout.split("\n")) {
const remoteName = line.trim();
if (remoteName.length > 0) {
remoteNames.push(remoteName);
}
}
return remoteNames;
}

export function parseRemoteNames(stdout: string): ReadonlyArray<string> {
Expand Down
11 changes: 7 additions & 4 deletions apps/server/src/imageMime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,13 @@ export function parseBase64DataUrl(
const match = /^data:([^,]+),([a-z0-9+/=\r\n ]+)$/i.exec(dataUrl.trim());
if (!match) return null;

const headerParts = (match[1] ?? "")
.split(";")
.map((part) => part.trim())
.filter((part) => part.length > 0);
const headerParts: Array<string> = [];
for (const part of (match[1] ?? "").split(";")) {
const trimmed = part.trim();
if (trimmed.length > 0) {
headerParts.push(trimmed);
}
}
if (headerParts.length < 2) {
return null;
}
Expand Down
9 changes: 6 additions & 3 deletions apps/server/src/keybindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import * as Layer from "effect/Layer";
import * as Option from "effect/Option";
import * as Predicate from "effect/Predicate";
import * as PubSub from "effect/PubSub";
import * as Result from "effect/Result";
import * as Schema from "effect/Schema";
import * as SchemaIssue from "effect/SchemaIssue";
import * as SchemaTransformation from "effect/SchemaTransformation";
Expand Down Expand Up @@ -538,9 +539,11 @@ const makeKeybindings = Effect.gen(function* () {
return;
}

const matchingDefaults = DEFAULT_KEYBINDINGS.filter((defaultRule) =>
customConfig.some((entry) => isSameKeybindingRule(entry, defaultRule)),
).map((rule) => rule.command);
const matchingDefaults = Array.filterMap(DEFAULT_KEYBINDINGS, (defaultRule) =>
customConfig.some((entry) => isSameKeybindingRule(entry, defaultRule))
? Result.succeed(defaultRule.command)
: Result.failVoid,
);
if (matchingDefaults.length > 0) {
yield* Effect.logWarning("default keybinding rule already defined in user config", {
path: keybindingsConfigPath,
Expand Down
10 changes: 7 additions & 3 deletions apps/server/src/orchestration/Layers/CheckpointReactor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
CommandId,
type CheckpointRef,
EventId,
MessageId,
type ProjectId,
Expand Down Expand Up @@ -701,9 +702,12 @@ const make = Effect.gen(function* () {
});
}

const staleCheckpointRefs = thread.checkpoints
.filter((checkpoint) => checkpoint.checkpointTurnCount > event.payload.turnCount)
.map((checkpoint) => checkpoint.checkpointRef);
const staleCheckpointRefs: Array<CheckpointRef> = [];
for (const checkpoint of thread.checkpoints) {
if (checkpoint.checkpointTurnCount > event.payload.turnCount) {
staleCheckpointRefs.push(checkpoint.checkpointRef);
}
}

if (staleCheckpointRefs.length > 0) {
yield* checkpointStore.deleteCheckpointRefs({
Expand Down
15 changes: 9 additions & 6 deletions apps/server/src/orchestration/Layers/ProjectionPipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -537,12 +537,15 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
projectionPendingApprovalRepository.listByThreadId({ threadId }),
]);

const latestUserMessageAt =
messages
.filter((message) => message.role === "user")
.map((message) => message.createdAt)
.toSorted()
.at(-1) ?? null;
let latestUserMessageAt: string | null = null;
for (const message of messages) {
if (
message.role === "user" &&
(latestUserMessageAt === null || message.createdAt > latestUserMessageAt)
) {
latestUserMessageAt = message.createdAt;
}
}

const pendingApprovalCount = pendingApprovals.filter(
(approval) => approval.status === "pending",
Expand Down
72 changes: 39 additions & 33 deletions apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ import {
ProjectId,
ThreadId,
} from "@t3tools/contracts";
import * as Arr from "effect/Array";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as Option from "effect/Option";
import * as Result from "effect/Result";
import * as Schema from "effect/Schema";
import * as Struct from "effect/Struct";
import * as SqlClient from "effect/unstable/sql/SqlClient";
Expand Down Expand Up @@ -1488,34 +1490,36 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {

const snapshot = {
snapshotSequence: computeSnapshotSequence(stateRows),
projects: projectRows
.filter((row) => row.deletedAt === null)
.map((row) =>
mapProjectShellRow(row, repositoryIdentities.get(row.projectId) ?? null),
),
threads: threadRows
.filter((row) => row.deletedAt === null)
.map(
(row): OrchestrationThreadShell => ({
id: row.threadId,
projectId: row.projectId,
title: row.title,
modelSelection: row.modelSelection,
runtimeMode: row.runtimeMode,
interactionMode: row.interactionMode,
branch: row.branch,
worktreePath: row.worktreePath,
latestTurn: latestTurnByThread.get(row.threadId) ?? null,
createdAt: row.createdAt,
updatedAt: row.updatedAt,
archivedAt: row.archivedAt,
session: sessionByThread.get(row.threadId) ?? null,
latestUserMessageAt: row.latestUserMessageAt,
hasPendingApprovals: row.pendingApprovalCount > 0,
hasPendingUserInput: row.pendingUserInputCount > 0,
hasActionableProposedPlan: row.hasActionableProposedPlan > 0,
}),
),
projects: Arr.filterMap(projectRows, (row) =>
row.deletedAt === null
? Result.succeed(
mapProjectShellRow(row, repositoryIdentities.get(row.projectId) ?? null),
)
: Result.failVoid,
),
threads: Arr.filterMap(threadRows, (row) =>
row.deletedAt === null
? Result.succeed({
id: row.threadId,
projectId: row.projectId,
title: row.title,
modelSelection: row.modelSelection,
runtimeMode: row.runtimeMode,
interactionMode: row.interactionMode,
branch: row.branch,
worktreePath: row.worktreePath,
latestTurn: latestTurnByThread.get(row.threadId) ?? null,
createdAt: row.createdAt,
updatedAt: row.updatedAt,
archivedAt: row.archivedAt,
session: sessionByThread.get(row.threadId) ?? null,
latestUserMessageAt: row.latestUserMessageAt,
hasPendingApprovals: row.pendingApprovalCount > 0,
hasPendingUserInput: row.pendingUserInputCount > 0,
hasActionableProposedPlan: row.hasActionableProposedPlan > 0,
} satisfies OrchestrationThreadShell)
: Result.failVoid,
),
updatedAt: updatedAt ?? "1970-01-01T00:00:00.000Z",
};

Expand Down Expand Up @@ -1621,11 +1625,13 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {

const snapshot = {
snapshotSequence: computeSnapshotSequence(stateRows),
projects: projectRows
.filter((row) => row.deletedAt === null && activeProjectIds.has(row.projectId))
.map((row) =>
mapProjectShellRow(row, repositoryIdentities.get(row.projectId) ?? null),
),
projects: Arr.filterMap(projectRows, (row) =>
row.deletedAt === null && activeProjectIds.has(row.projectId)
? Result.succeed(
mapProjectShellRow(row, repositoryIdentities.get(row.projectId) ?? null),
)
: Result.failVoid,
),
threads: threadRows.map(
(row): OrchestrationThreadShell => ({
id: row.threadId,
Expand Down
10 changes: 7 additions & 3 deletions apps/server/src/provider/Layers/ClaudeAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,13 @@ function toProcessError(
function normalizeClaudeStreamMessages(
cause: Cause.Cause<{ readonly message: string }>,
): ReadonlyArray<string> {
const errors = Cause.prettyErrors(cause)
.map((error) => error.message.trim())
.filter((message) => message.length > 0);
const errors: Array<string> = [];
for (const error of Cause.prettyErrors(cause)) {
const message = error.message.trim();
if (message.length > 0) {
errors.push(message);
}
}
if (errors.length > 0) {
return errors;
}
Expand Down
12 changes: 7 additions & 5 deletions apps/server/src/provider/Layers/ClaudeProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,11 +317,13 @@ export function resolveClaudeApiModelId(modelSelection: ModelSelection): string
}

function toTitleCaseWords(value: string): string {
return value
.split(/[\s_-]+/g)
.filter(Boolean)
.map((part) => part[0]!.toUpperCase() + part.slice(1).toLowerCase())
.join(" ");
const parts: Array<string> = [];
for (const part of value.split(/[\s_-]+/g)) {
if (part.length > 0) {
parts.push(part[0]!.toUpperCase() + part.slice(1).toLowerCase());
}
}
return parts.join(" ");
}

function claudeSubscriptionLabel(subscriptionType: string | undefined): string | undefined {
Expand Down
25 changes: 15 additions & 10 deletions apps/server/src/provider/Layers/CodexProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,16 +319,21 @@ const probeCodexAppServerProvider = Effect.fn("probeCodexAppServerProvider")(fun
} satisfies CodexAppServerProviderSnapshot;
});

const emptyCodexModelsFromSettings = (codexSettings: CodexSettings): ServerProvider["models"] =>
codexSettings.customModels
.map((model) => model.trim())
.filter((model, index, models) => model.length > 0 && models.indexOf(model) === index)
.map((model) => ({
slug: model,
name: model,
isCustom: true,
capabilities: null,
}));
const emptyCodexModelsFromSettings = (codexSettings: CodexSettings): ServerProvider["models"] => {
const models = new Set<string>();
for (const model of codexSettings.customModels) {
const trimmed = model.trim();
if (trimmed.length > 0) {
models.add(trimmed);
}
}
return Array.from(models, (model) => ({
slug: model,
name: model,
isCustom: true,
capabilities: null,
}));
};

const makePendingCodexProvider = (
codexSettings: CodexSettings,
Expand Down
33 changes: 20 additions & 13 deletions apps/server/src/provider/Layers/CursorProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -596,11 +596,12 @@ export const discoverCursorModelCapabilitiesViaAcp = (
);
}

const targetModelSlugs = new Set(
existingModels
.filter((model) => !model.isCustom && !hasCursorModelCapabilities(model))
.map((model) => model.slug),
);
const targetModelSlugs = new Set<string>();
for (const model of existingModels) {
if (!model.isCustom && !hasCursorModelCapabilities(model)) {
targetModelSlugs.add(model.slug);
}
}
if (targetModelSlugs.size === 0) {
return buildCursorDiscoveredModels(
modelChoices.map((modelChoice) => ({
Expand Down Expand Up @@ -721,9 +722,13 @@ export interface CursorAboutResult {
}

function joinProviderMessages(...messages: ReadonlyArray<string | undefined>): string | undefined {
const parts = messages
.map((message) => message?.trim())
.filter((message): message is string => Boolean(message));
const parts: Array<string> = [];
for (const message of messages) {
const trimmed = message?.trim();
if (trimmed) {
parts.push(trimmed);
}
}
return parts.length > 0 ? parts.join(" ") : undefined;
}

Expand Down Expand Up @@ -790,11 +795,13 @@ export function parseCursorCliConfigChannel(raw: string): string | undefined {
}

function toTitleCaseWords(value: string): string {
return value
.split(/[\s_-]+/g)
.filter((part) => part.length > 0)
.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
.join(" ");
const parts: Array<string> = [];
for (const part of value.split(/[\s_-]+/g)) {
if (part.length > 0) {
parts.push(part.charAt(0).toUpperCase() + part.slice(1).toLowerCase());
}
}
return parts.join(" ");
}

function cursorSubscriptionLabel(subscriptionType: string | undefined): string | undefined {
Expand Down
15 changes: 9 additions & 6 deletions apps/server/src/provider/Layers/OpenCodeAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1366,12 +1366,15 @@ export function makeOpenCodeAdapter(
}),
).pipe(Effect.mapError(toRequestError));

const turns = (messages.data ?? [])
.filter((entry) => entry.info.role === "assistant")
.map((entry) => ({
id: TurnId.make(entry.info.id),
items: [entry.info, ...entry.parts],
}));
const turns: Array<OpenCodeTurnSnapshot> = [];
for (const entry of messages.data ?? []) {
if (entry.info.role === "assistant") {
turns.push({
id: TurnId.make(entry.info.id),
items: [entry.info, ...entry.parts],
});
}
}

return {
threadId,
Expand Down
Loading
Loading