import { type Locale } from '../i18n/index.js'; import type { CliTurnPayload } from '../types.js'; import { type DashboardImageUpload } from './dashboard-images.js'; /** 协作模式: * - 'all' 「一起开工」——每个被选 bot 各起一条会话、拿同一份内容。 * - 'lead' 「Lead 分配」——只有 lead bot 起会话,内容带编排上下文,由它决定何时 * 在群里 @ 拉起 sub bot。 */ export declare const CREATE_SESSION_MODES: readonly ["all", "lead"]; export type CreateSessionMode = (typeof CREATE_SESSION_MODES)[number]; /** 入列:建完后会话落在看板哪一列。 * - 'in_progress' 直接开跑(立即 forkWorker)。 * - 'backlog' 入待办池(parked,不起 CLI,等激活)。 */ export declare const CREATE_SESSION_COLUMNS: readonly ["in_progress", "backlog"]; export type CreateSessionColumn = (typeof CREATE_SESSION_COLUMNS)[number]; /** 单个 bot 在新群里扮演的角色,决定它的首轮 prompt 怎么包: * - 'solo' 只有它一个 worker(单 bot,或 lead 模式下的 lead 且没 sub)。 * - 'lead' lead 分配模式的 lead,prompt 前置编排上下文(列出 sub bot)。 * - 'collab' 一起开工模式的并列 worker,prompt 前置一句「还有谁在一起干」。 */ export type SpawnRole = 'solo' | 'lead' | 'collab'; export declare const SPAWN_ROLES: readonly SpawnRole[]; export interface Coworker { name: string; openId?: string; } export declare function normalizeCreateMode(value: unknown): CreateSessionMode | null; export declare function normalizeCreateColumn(value: unknown): CreateSessionColumn | null; /** 会话标题:取内容首个非空行,压空白、限长。空内容回退占位。 */ export declare function deriveSessionTitleFromContent(content: string): string; /** Dashboard group name follows the same visible first-line rule as the * session title. Keeping it here prevents the browser placeholder and the * actual Lark chat name from drifting apart. */ export declare function deriveCreateGroupName(explicitName: unknown, content: string): string; /** Decide which already-joined bots receive the opening turn. The content is * intentionally absent from this decision: an @sub inside Lead instructions * must not wake that sub before the Lead delegates. */ export declare function selectCreateSessionTargets(mode: CreateSessionMode, joinedIds: readonly string[], leadLarkAppId?: string): string[]; /** Lead 分配模式下,prepend 到用户内容前的编排上下文块。列出群里可协作的 sub * bot(名字 + open_id,便于 @),并交代「你是 lead、自行决定何时拉起谁」。 */ export declare function buildLeadDispatchPreamble(coworkers: Coworker[], locale?: Locale): string; /** 一起开工模式下,prepend 一句「本群还有谁在并行干同一任务」的轻量提示。 * 没有其他 coworker 时返回空串(退化成 solo)。 */ export declare function buildCollabNote(coworkers: Coworker[], locale?: Locale): string; /** System-generated dashboard role context kept separate from the human task * for Codex App clean-input materialization. Legacy CLIs still receive the * concatenated string from composeSpawnUserContent(). */ export declare function composeSpawnCodexAppContext(args: { role: SpawnRole; coworkers?: Coworker[]; locale?: Locale; }): string | undefined; /** 组装喂给 buildNewTopicPrompt 的「用户内容」——按角色在原始 content 前拼上 * lead 编排前言 / 协作提示。solo 原样返回。 */ export declare function composeSpawnUserContent(args: { content: string; role: SpawnRole; coworkers?: Coworker[]; locale?: Locale; }): string; /** Merge a parked dashboard task with the first message that activates it. * The legacy prompt combines queuedPrompt + current wrapped prompt elsewhere; * this helper independently combines only raw user texts and metadata-only * contexts so the visible Codex App turn neither drops nor duplicates the * original dashboard task. */ export declare function mergeQueuedCodexAppTurn(args: { queued: boolean; queuedText?: string; queuedMessageContext?: string; currentText: string; currentMessageContext?: string; }): { text: string; messageContext?: string; }; /** Final compatibility gate for a queued dashboard task activated by a topic * reply. Sessions parked before clean-input was introduced have queuedPrompt * but no queuedCodexAppText. Their legacy content already contains both the * queued task and the current reply, while the newly-built structured sidecar * can only contain the current reply. Remove that incomplete sidecar so Codex * App consumes the complete legacy prompt instead. * * A valid string field (including an explicitly stored empty string) identifies * the new schema. Missing, null, or malformed persisted values fail closed to * legacy content. Non-Codex payloads have no sidecar and remain unchanged. */ export declare function applyQueuedCodexAppLegacyFallback(payload: CliTurnPayload, args: { queued: boolean; queuedText?: unknown; }): CliTurnPayload; export interface SpawnRequest { chatId: string; content: string; column: CreateSessionColumn; role: SpawnRole; coworkers: Coworker[]; ownerOpenId?: string; ownerUnionId?: string; title?: string; images: DashboardImageUpload[]; } export type ParseResult = { ok: true; value: T; } | { ok: false; error: string; }; /** 校验 daemon /api/sessions/spawn 的请求体。content 去尾空白后不能为空、限长; * chatId 必须是飞书群 id(oc_ 前缀);column/role 必须合法。 */ export declare function parseSpawnRequest(body: unknown): ParseResult; //# sourceMappingURL=session-create.d.ts.map