import { type AgentCapabilities, type FirstPartyMcpToolName, type MachineView } from "@opengeni/contracts"; import type { CreateSessionRequest, NewSessionDraftOptions, NewSessionSelectionHistory, PersonalResourceAttachmentIntent } from "@opengeni/sdk"; import type { LatencyMode, ReasoningEffort, ResourceRef, SandboxBackend, ToolRef, TurnSubmission } from "../types.js"; /** A platform-owned ephemeral sandbox. `backend === ""` is the deployment * default. The composer no longer exposes a managed-backend override; keep the * field so drafts/API mapping stay stable if we re-enable it later. */ export type ManagedSandboxTarget = { kind: "sandbox"; backend: SandboxBackend | ""; }; /** The working folder on a connected machine. `root` selects the reported * launch root; `path` is absolute or relative to it. */ export type MachineFolder = { kind: "root"; } | { kind: "path"; path: string; }; /** A user-owned enrolled machine the platform attaches to (no clone, no teardown, * the machine's own env & git auth). `sandboxId` is `null` until one is picked. */ export type ConnectedMachineTarget = { kind: "machine"; sandboxId: string | null; folder: MachineFolder; }; export type ComputeTarget = ManagedSandboxTarget | ConnectedMachineTarget; export declare function rememberedProjectCompute(history: NewSessionSelectionHistory, channelId: string | null, defaultSandboxBackend?: SandboxBackend): ComputeTarget | null; export declare function rememberedMachineFolder(history: NewSessionSelectionHistory, channelId: string | null, sandboxId: string): MachineFolder; export type SessionDraft = { agentLearning?: import("@opengeni/sdk").AgentLearningOverrides | undefined; visibility: "private" | "workspace"; compute: ComputeTarget; rigId: string; goalText: string; goalSuccessCriteria: string; goalMaxAutoContinuations: string; customMcpPermissions: boolean; mcpPermissions: Set; firstPartyMcpTools: Set; /** * "Customize for this chat" capabilities. Undefined follows the workspace's * defaults and sends no `agent` at all. */ agentCapabilities?: AgentCapabilities | undefined; /** * This chat's own instructions, from a draft another page prepared (the * signup setup chat). Not edited in the composer; sent as `agent.instructions`. */ agentInstructions?: string | undefined; /** * The chat's "+" > Secrets choice. Undefined means every vault the person * can reach (no narrowing); sent as `agent.vaultPolicy`. */ vaultPolicy?: import("@opengeni/sdk").VaultPolicy | undefined; }; /** * Label for the composer's empty Sandbox Environment choice. The empty choice * sends no rigId, so the server binds the workspace default. Name that * default so people can see what they * would replace by picking another environment; say "None" when the * workspace has no default, because the empty choice then means no * environment at all. */ export declare function workspaceDefaultRigOptionLabel(workspaceDefaultRigId: string | null | undefined, rigs: readonly { id: string; name: string; }[]): string; export declare function emptySessionDraft(defaultFirstPartyMcpTools?: readonly FirstPartyMcpToolName[], defaultSandboxBackend?: SandboxBackend): SessionDraft; /** * The composer's connector policy for a chat with its own capabilities: * Workspace connectors off sends no connector choice at all (the server then * attaches none), and a built-in server of a capability that is off is left * out instead of being refused. Applied to the draft and the create alike, so * the draft snapshot the server checks matches the request. */ export declare function fitToolPolicyToAgentCapabilities(policy: Policy, capabilities: AgentCapabilities | undefined): Policy; /** True once the draft can be submitted: a connected machine needs a picked * machine; a managed sandbox is always ready. */ export declare function isSessionDraftComputeReady(draft: SessionDraft): boolean; /** Personal workspace access is already owner-only. Use private session tenancy * when the server supports it, without making its activation a prerequisite. */ export declare function newSessionCreateVisibility(personalWorkspace: boolean, selectedVisibility: "private" | "workspace", canCreatePrivate: boolean): "private" | "workspace"; export type SessionDraftSubmission = { /** TurnSubmission extras merged into the create payload. */ extras: Omit; /** Top-level create fields threaded into `startSession` separately. */ options: { targetSandboxId: string | null; workingDir: string | null; visibility?: "private" | "workspace" | undefined; }; /** When true (a connected machine) the workspace's selected repos must NOT be * cloned: the machine uses its own checkout & git auth (D3). This is the UI * half of the clone-gating footgun fix — the selection is retained in context * (lossless toggle-back) but excluded from the create's `resources[]`. */ omitWorkspaceResources: boolean; }; export type BuildCreateSessionRequestInput = { currentResources: ResourceRef[]; submission: TurnSubmission; /** Session-scoped system guidance that is not rendered in the chat timeline. */ instructions?: string | undefined; /** Installed session-selected Skills to freeze onto the new session. */ installedSkillIds?: string[] | undefined; startMode?: "realtime" | undefined; visibility?: "private" | "workspace" | undefined; omitWorkspaceResources?: boolean | undefined; selectedTools: ToolRef[]; /** Exact policy acknowledged by the revision-fenced new-session draft. */ newSessionDraftToolPolicy?: { tools: ToolRef[]; toolsProvided: boolean; excludedMcpServerIds?: string[] | undefined; } | undefined; defaultModel: string; defaultReasoningEffort: ReasoningEffort; defaultLatencyMode: LatencyMode; clientEventId: string; idempotencyKey: string; targetSandboxId?: string | null | undefined; workingDir?: string | null | undefined; channelId?: string | null | undefined; expectedNewSessionDraftRevision?: number | undefined; agentLearning?: import("@opengeni/sdk").AgentLearningOverrides | undefined; /** * Per-task usage limit in USD micros. Only sent when the server advertises * `sessionUsageLimits.enabled` and a limit was chosen; null or omitted sends * nothing (no limit), so older servers never see the field. */ usageLimitMicros?: number | null | undefined; /** Server-authoritative omitted-tools defaults, including mandatory opengeni. */ workspaceDefaultMcpServerIds?: string[] | undefined; /** Prevent a partially hydrated capability catalog from becoming a pin. */ workspaceMcpCatalogReady?: boolean | undefined; }; export type PendingCreateAttempt = { client: object; workspaceId: string; signature: string; idempotencyKey: string; eventId: string; }; export declare function classifyCreateSessionFailure(error: unknown): { error: Error; outcomeUnknown: boolean; }; /** A create may be retried with the same key only when the transport cannot * prove whether the server committed it. Definitive HTTP results end that * logical attempt so a corrected, reconfirmed request gets a fresh key. */ export declare function retainCreateSessionAttemptAfterFailure(input: { current: PendingCreateAttempt | null; attempted: PendingCreateAttempt; outcomeUnknown: boolean; }): PendingCreateAttempt | null; /** * Build the one canonical create payload without mutating UI state. Resource * identity and mount conflicts are resolved by the shared contract helper; * exact duplicates collapse while order remains first-seen stable. */ export declare function buildCreateSessionRequest(input: BuildCreateSessionRequestInput): CreateSessionRequest; /** * Bind create and first-message identities to the exact logical request. A * transport retry must retain both: otherwise a committed first event cannot * reconcile with the optimistic handoff returned by the replay. A draft may * acquire a new OCC revision while retaining the same create value. * A changed value, workspace, or authenticated client starts a new logical * create instead of reviving a partially initialized session with stale input. */ export declare function prepareCreateSessionAttempt(input: { pending: PendingCreateAttempt | null; client: object; workspaceId: string; request: CreateSessionRequest; freshIdempotencyKey: string; }): { pending: PendingCreateAttempt; request: CreateSessionRequest; }; /** The single submit mapper: turns a `SessionDraft` into the create payload, * branching on the compute kind (the one discriminant). */ export declare function submissionFromSessionDraft(draft: SessionDraft, defaultFirstPartyMcpTools?: readonly FirstPartyMcpToolName[], personalResourceAttachment?: PersonalResourceAttachmentIntent | undefined): SessionDraftSubmission; /** * Project the editable create form into the deliberately narrow set of options * that may survive before a session exists. Attempt-scoped ids and credential * material have no representation here by construction. */ export declare function newSessionDraftOptionsFromSessionDraft(draft: SessionDraft, defaultFirstPartyMcpTools?: readonly FirstPartyMcpToolName[], effectiveVisibility?: "private" | "workspace"): NewSessionDraftOptions; /** Restore server-authoritative create options into the single UI draft form. */ export declare function sessionDraftFromNewSessionDraftOptions(options: NewSessionDraftOptions, defaultFirstPartyMcpTools?: readonly FirstPartyMcpToolName[], defaultSandboxBackend?: SandboxBackend): SessionDraft; export type ManagedBackendOption = { value: SandboxBackend | ""; label: string; /** Capability summary chips, e.g. ["Desktop", "Recording", "24h"]. */ chips: string[]; }; /** Managed backend choices (deployment default first). Excludes `selfhosted` * (Connected Machine kind). Kept for tests / a possible future override UI — * the create composer no longer surfaces this control. */ export declare function managedBackendOptions(): ManagedBackendOption[]; /** The capability chips for a connected (selfhosted) machine, reflecting the * SELECTED machine's real capabilities — not the static descriptor. * FileSystem/Terminal/Git are always available, so they show even before a * machine is picked. The static descriptor *proclaims* DesktopStream, but that * is consent-gated at enrollment and absent on a headless machine — so the * "Desktop" chip is shown only when the picked machine actually has a display * (`hasDisplay`). A headless machine therefore never shows "Desktop"; the caller * surfaces a distinct "no display" indicator instead. */ export declare function selfhostedCapabilityChips(machine?: MachineView | null): string[];