import { ExtensionLayerResolvers } from "../../builders/cli/extensionAssembler/index.cjs"; import { LayerResolvers, MajorModesConfig } from "@agimon-ai/doompi-config/majorModes"; import { HarnessState } from "@agimon-ai/doompi-config/types"; import { DoomMcpProjection } from "@agimon-ai/doompi-core/mcp-projection"; import { SyncIdentity, SyncLocation } from "@agimon-ai/doompi-core/sync-location"; import { SYNC_STATE_VERSION } from "@agimon-ai/doompi-core/sync-state-contract"; //#region src/composition/syncState/index.d.ts export interface SyncSelection { majorMode: string; domains: string[]; profile?: string; preset: string; } /** Paths to the resources sync staged, before any live switch replaces them. */ export interface SyncBaseline { mcpConfigPath?: string; personaFile?: string; themePath: string; themeName: string; } export interface SyncPrecompileState { /** Version of the lightweight freshness contract used by package startup. */ version: number; strategy: 'bundle'; /** Package entry the generated bootstrap bundles. */ bootstrapEntry: string; /** Compiler manifest whose output is the graph-bundled package bootstrap. */ bootstrapManifest: string; /** Compiler manifest for each graph-bundled composition. */ bundleManifests: Record; } export interface SyncServerBundleState { descriptorPath: string; fingerprint: string; compilerManifests: Record; sourcesHash: string; } export interface SyncMcpBundleState { descriptorPath: string; fingerprint: string; compilerManifests: Record; sourcesHash: string; } export interface SyncState { version: number; root: string; /** Canonical repository and worktree namespace that owns this state. */ identity: SyncIdentity; /** Hash of the config that produced this state, for the staleness warning. */ inputsHash: string; /** * Hash of the cockpit sources and package versions this state was built from. * * Absent in a state written before cockpit sources were tracked, which reads * as "cannot be compared" rather than as a change, so an old state does not * force a resync on sight. */ webSourcesHash?: string; /** Canonical composition selected when this state was recorded. */ compositionFingerprint: string; selection: SyncSelection; /** Harness environment the extension applies when the values are unset. */ env: Record; /** * State the environment does not carry, so it has to be recorded on its own. * * Plugin hooks, the profile's environment defaults, and the neutral MCP * projection live in the session state file rather than in variables. */ fileState: Pick & { mcpProjection: DoomMcpProjection; }; /** Entry name to absolute path, covering every layer, not just the selected mode's. */ resolved: Record; /** * The same entries after TypeScript ones were bundled to plain ESM. * * Kept apart from `resolved` so the staleness check still compares resolution * against resolution; a state written before this existed simply has none and * falls back to loading the source. */ compiled?: Record; /** Aggregate entry by canonical composition fingerprint. */ bundles?: Record; /** Graph-compiled synced bootstrap dynamically loaded by the package entry. */ bootstrap?: string; /** Inputs used to validate generated artifacts without loading the compiler. */ precompile?: SyncPrecompileState; /** Absent only in generations produced before the server descriptor cutover. */ serverBundle?: SyncServerBundleState; /** Explicit remote-only session capabilities staged with this generation. */ mcpBundle?: SyncMcpBundleState; baseline: SyncBaseline; } export declare function syncDirectory(repoRoot: string, homeDirectory?: string): string; export declare function syncStatePath(repoRoot: string, homeDirectory?: string): string; export declare function legacySyncDirectory(repoRoot: string): string; export declare function legacySyncStatePath(repoRoot: string): string; /** Whether generated state belongs to the repository that is reading it. */ export declare function syncStateRootMatches(repoRoot: string, stateRoot: string): boolean; /** * Per-process scratch directory for live `/domains` and `/profile` switches. * * Switching rewrites the MCP config and the persona prompt. Writing those back * into the synced directory would both mutate the pinned baseline and let two * Pi sessions in one repository overwrite each other, which the launcher avoids * by giving every run its own temporary directory. */ export declare function runDirectory(repoRoot: string, processId?: number, homeDirectory?: string): string; /** * How a Pi project settings file should refer to a generated path. * * Relative to `.pi` when the target lives in the repository, which keeps the * committed settings file identical on every machine. A doom-pi installed * outside the repository stays absolute: Pi accepts both, and a relative path * climbing out of the project would be neither portable nor readable. */ export declare function settingsRelativePath(repoRoot: string, target: string): string; /** * Hashes the cockpit sources and package versions a sync compiled. * * The cockpit bundle is built from each installed package's `web/` folder by * `syncWebBundle`, straight from source, with no compiler manifest recording * what went in. Nothing else in the drift check reads those files, so editing a * plugin surface and rebuilding left the hub serving the previously bundled * cockpit with nothing reporting a reason. Compiled entries are covered * elsewhere, by the content digests in their compiler manifests, so only the * entry identity and its package version are folded in here. * * Bounded on purpose: the web sources of a full composition are a few hundred * small files, which is cheap enough for the hub to poll. */ export declare function computeWebSourcesHash(resolved: Record): string; /** Include declaration changes even for packages that did not previously expose a server facet. */ export declare function computeServerSourcesHash(resolved: Record): string; /** Include MCP declarations and their attributed source files in sync freshness. */ export declare function computeMcpSourcesHash(resolved: Record): string; /** * Hashes the configuration a sync consumed. * * Deliberately cheap: the extension recomputes this on every session start, so * it reads config, marketplace, local plugin manifests, and profile persona text * without downloading plugins or re-resolving packages. A dependency upgrade that * moves a package path therefore does not show up here; `doom-pi sync --check` * re-resolves and is the check that catches that. */ export declare function computeInputsHash(repoRoot: string, selection: SyncSelection, homeDirectory?: string): string; export interface LocatedSyncState { state: SyncState; location: SyncLocation; layout: 'global'; } /** Reads only state reached through this repository/worktree's validated registration. */ export declare function readLocatedSyncState(repoRoot: string, homeDirectory?: string): LocatedSyncState | undefined; /** Reads the synced state, or undefined when the repository was never synced. */ export declare function readSyncState(repoRoot: string, homeDirectory?: string): SyncState | undefined; export declare function serializeSyncState(state: SyncState): string; export declare function writeSyncState(repoRoot: string, state: SyncState, homeDirectory?: string, targetPath?: string): Promise; export declare function ownKey(name: string): string; export declare function packageKey(specifier: string): string; export declare function packageEntryKey(specifier: string, index: number): string; /** * Keyed by the absolute target, because the same relative specifier means * different files under the repository and the global config directory. */ export declare function localKey(specifier: string, baseDirectory: string): string; export declare function localEntryKey(specifier: string, baseDirectory: string, index: number): string; export declare function localPackageNameKey(specifier: string, baseDirectory: string): string; export interface RecordingResolvers extends ExtensionLayerResolvers { /** Every name this resolver was asked for, keyed for the state file. */ readonly resolved: Record; packageEntries(name: string): string[]; optionalPackageEntries(name: string): string[] | undefined; localEntries(specifier: string, baseDirectory: string): string[] | undefined; } /** * Resolvers that record what they resolve. * * Sync composes once with every layer selected and hands the recording to the * state file, so the extension never has to resolve a specifier itself. */ export declare function createRecordingResolvers(base?: LayerResolvers): RecordingResolvers; /** * Resolves every entry any layer could contribute, in one pass. * * Composing with every layer selected and the widest options is what makes the * map complete: a later `/mode` switch inside a Pi session can then pick a * different set without resolving anything itself. The persona entry is asked * for separately because it remains a fixed host entry rather than a layer. */ export declare function recordResolvedEntries(majorModesConfig: MajorModesConfig, base?: LayerResolvers): Record; /** Resolvers backed by a synced map, for composing inside a Pi session. */ export declare function createMapResolvers(resolved: Record, compiled?: Record): ExtensionLayerResolvers; /** Reads the resolved MCP servers back out of a generated config. */ export declare function readMcpServerNames(configPath: string): string[]; //#endregion export { SYNC_STATE_VERSION }; //# sourceMappingURL=index.d.cts.map