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
4 changes: 4 additions & 0 deletions apps/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
"@ff-labs/fff-node": "0.9.4",
"@opencode-ai/sdk": "^1.3.15",
"@pierre/diffs": "catalog:",
"@sigstore/bundle": "4.0.0",
"@sigstore/core": "3.2.1",
"@sigstore/tuf": "4.0.0",
"@sigstore/verify": "3.0.0",
"effect": "catalog:",
"msgpackr-extract": "3.0.4",
"node-pty": "^1.1.0",
Expand Down
75 changes: 74 additions & 1 deletion apps/server/src/provider/Drivers/PrimeAgentDriver.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { PrimeAgentSettings, ProviderDriverKind, type ServerProvider } from "@t3tools/contracts";
import {
PrimeAgentSettings,
ProviderDriverKind,
type ServerProvider,
type ServerProviderDistribution,
} from "@t3tools/contracts";
import { HostProcessPlatform } from "@t3tools/shared/hostProcess";
import { resolveCommandPath } from "@t3tools/shared/shell";
import * as Crypto from "effect/Crypto";
Expand Down Expand Up @@ -32,6 +37,12 @@ import { readPrimeAgentBackends, readPrimeAgentCapacity } from "../primeAgentBac
const PRIME_AGENT_TURN_END_CAPACITY_FRESH_MS = 60_000;
import { makePrimeAgentDaemonAdapter } from "../prime/PrimeAgentDaemonAdapter.ts";
import { negotiatePrimeAgentBackend } from "../prime/PrimeAgentBackendSelection.ts";
import { locatePrimeAgentPublicPackage } from "../prime/PrimeAgentDaemonBridge.ts";
import {
inspectPrimeAgentDistribution,
makeLatestPrimePublicationLoader,
makePrimeDistributionNetworkDependencies,
} from "../prime/PrimeAgentDistributionVerifier.ts";
import { makePrimeAgentDaemonManager } from "../prime/PrimeAgentDaemonManager.ts";
import {
defaultProviderContinuationIdentity,
Expand Down Expand Up @@ -137,6 +148,67 @@ export const PrimeAgentDriver: ProviderDriver<PrimeAgentSettings, PrimeAgentDriv
continuationGroupKey: continuationIdentity.continuationKey,
});
const effectiveConfig = { ...config, enabled } satisfies PrimeAgentSettings;
const loadLatestVerifiedPublication = makeLatestPrimePublicationLoader(
makePrimeDistributionNetworkDependencies({
tufCachePath: path.join(serverConfig.stateDir, "sigstore-tuf"),
}),
);
const inspectDistribution = (
snapshot: ServerProvider,
enableUpdateChecks: boolean | undefined,
): Effect.Effect<ServerProviderDistribution> => {
if (!snapshot.enabled || !snapshot.installed) {
return Effect.succeed({
classification: "stock-or-custom" as const,
channel: null,
buildId: null,
sequence: null,
latestBuildId: null,
latestSequence: null,
updateAvailable: false,
checkedAt: snapshot.checkedAt,
message: "This Prime installation is maintained manually.",
});
}
return Effect.gen(function* () {
const executablePath = path.resolve(
yield* resolveCommandPath(effectiveConfig.binaryPath || "prime-agent", {
env: processEnv,
}),
);
const publicPackage = yield* locatePrimeAgentPublicPackage(executablePath);
return yield* Effect.promise(() =>
inspectPrimeAgentDistribution(
{
stateDir: serverConfig.stateDir,
instanceId,
packageRoot: publicPackage.packageRoot,
platform: hostPlatform,
checkedAt: snapshot.checkedAt,
...(enableUpdateChecks === undefined ? {} : { enableUpdateChecks }),
},
{ loadLatestVerifiedPublication },
),
);
}).pipe(
Effect.catchCause(() =>
Effect.succeed({
classification: "stock-or-custom" as const,
channel: null,
buildId: null,
sequence: null,
latestBuildId: null,
latestSequence: null,
updateAvailable: false,
checkedAt: snapshot.checkedAt,
message:
"Pylon could not inspect the selected Prime distribution; Prime remains ready and manually maintained.",
}),
),
Effect.provideService(FileSystem.FileSystem, fileSystem),
Effect.provideService(Path.Path, path),
);
};
const maintenanceCapabilities = yield* resolveProviderMaintenanceCapabilitiesEffect(UPDATE, {
binaryPath: effectiveConfig.binaryPath,
env: processEnv,
Expand Down Expand Up @@ -286,6 +358,7 @@ export const PrimeAgentDriver: ProviderDriver<PrimeAgentSettings, PrimeAgentDriv
snapshot: currentSnapshot,
maintenanceCapabilities,
enableProviderUpdateChecks: settings.enableProviderUpdateChecks,
distribution: inspectDistribution(currentSnapshot, settings.enableProviderUpdateChecks),
publishSnapshot,
httpClient,
}),
Expand Down
47 changes: 46 additions & 1 deletion apps/server/src/provider/Layers/PrimeAgentProvider.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import * as NodeServices from "@effect/platform-node/NodeServices";
import { describe, expect, it } from "@effect/vitest";
import { PrimeAgentSettings, ProviderDriverKind, ProviderInstanceId } from "@t3tools/contracts";
import {
PrimeAgentSettings,
ProviderDriverKind,
ProviderInstanceId,
type ServerProvider,
} from "@t3tools/contracts";
import * as Cause from "effect/Cause";
import * as Deferred from "effect/Deferred";
import * as Effect from "effect/Effect";
Expand All @@ -24,6 +29,7 @@ import {
sharedUsageReadKey,
} from "../sharedUsageReadCache.ts";
import {
applyPrimeAgentDistribution,
buildInitialPrimeAgentProviderSnapshot,
checkPrimeAgentProviderStatus,
parsePrimeAgentModelDiscoveryOutput,
Expand Down Expand Up @@ -98,6 +104,45 @@ function mockPrimeAgentSpawner(input: {
);
}

describe("PrimeAgentProvider distribution", () => {
it("keeps runtime readiness independent and maps only signed build identity to advisory", () => {
const snapshot: ServerProvider = {
instanceId: ProviderInstanceId.make("primeAgent"),
driver: ProviderDriverKind.make("primeAgent"),
enabled: true,
installed: true,
version: "0.8.1",
status: "ready",
auth: { status: "authenticated" },
checkedAt: "2026-08-20T12:00:00.000Z",
models: [],
slashCommands: [],
skills: [],
};
const result = applyPrimeAgentDistribution(snapshot, {
classification: "pylon-managed",
channel: "preview",
buildId: "pylon-build-g0123456789ab-r1",
sequence: 9,
latestBuildId: "pylon-build-gabcdef012345-r1",
latestSequence: 10,
updateAvailable: true,
checkedAt: "2026-08-20T12:00:00.000Z",
message: "A signed preview build is available.",
});

expect(result.status).toBe("ready");
expect(result.version).toBe("0.8.1");
expect(result.versionAdvisory).toMatchObject({
status: "behind_latest",
currentVersion: "pylon-build-g0123456789ab-r1",
latestVersion: "pylon-build-gabcdef012345-r1",
canUpdate: false,
updateCommand: null,
});
});
});

describe("PrimeAgentProvider models", () => {
it("always publishes the synthetic default model before unique custom models", () => {
expect(
Expand Down
39 changes: 34 additions & 5 deletions apps/server/src/provider/Layers/PrimeAgentProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
type ModelCapabilities,
type PrimeAgentSettings,
type ServerProvider,
type ServerProviderDistribution,
type ServerProviderModel,
type ServerProviderBackend,
} from "@t3tools/contracts";
Expand Down Expand Up @@ -534,20 +535,48 @@ ${versionOutput.stderr}`);
});
});

export function applyPrimeAgentDistribution(
snapshot: ServerProvider,
distribution: ServerProviderDistribution,
): ServerProvider {
const versionAdvisory =
distribution.classification === "pylon-managed"
? {
status: distribution.updateAvailable ? ("behind_latest" as const) : ("current" as const),
currentVersion: distribution.buildId,
latestVersion: distribution.latestBuildId,
updateCommand: null,
canUpdate: false,
checkedAt: distribution.checkedAt,
message: distribution.updateAvailable ? distribution.message : null,
}
: snapshot.versionAdvisory;
return {
...snapshot,
distribution,
...(versionAdvisory ? { versionAdvisory } : {}),
};
}

export const enrichPrimeAgentSnapshot = (input: {
readonly snapshot: ServerProvider;
readonly maintenanceCapabilities: ProviderMaintenanceCapabilities;
readonly enableProviderUpdateChecks?: boolean;
readonly distribution: Effect.Effect<ServerProviderDistribution>;
readonly publishSnapshot: (snapshot: ServerProvider) => Effect.Effect<void>;
readonly httpClient: HttpClient.HttpClient;
}): Effect.Effect<void> =>
enrichProviderSnapshotWithVersionAdvisory(input.snapshot, input.maintenanceCapabilities, {
enableProviderUpdateChecks: input.enableProviderUpdateChecks,
Effect.gen(function* () {
const snapshot = yield* enrichProviderSnapshotWithVersionAdvisory(
input.snapshot,
input.maintenanceCapabilities,
{ enableProviderUpdateChecks: input.enableProviderUpdateChecks },
).pipe(Effect.provideService(HttpClient.HttpClient, input.httpClient));
const distribution = yield* input.distribution;
yield* input.publishSnapshot(applyPrimeAgentDistribution(snapshot, distribution));
}).pipe(
Effect.provideService(HttpClient.HttpClient, input.httpClient),
Effect.flatMap(input.publishSnapshot),
Effect.catchCause((cause) =>
Effect.logWarning("Prime Agent version advisory enrichment failed", { cause }),
Effect.logWarning("Prime Agent distribution advisory enrichment failed", { cause }),
),
Effect.asVoid,
);
Loading
Loading