import { RewriteRule } from '@forgeax/workbench-host/browser'; export { RewriteRule } from '@forgeax/workbench-host/browser'; import { createExtensionClient } from '@forgeax/workbench-host/extension'; /** * @deprecated Prefer `rewriteUrl` / `createRewritingFetch` from * `@forgeax/workbench-host/browser`. This shim keeps mount-lifecycle rules * for one transition release. */ type ForgeaxHttpDefaults = { rewrite: RewriteRule[]; }; type ForgeaxHttp = { defaults: ForgeaxHttpDefaults; fetch: typeof fetch; rewriteUrl: (url: string) => string; }; /** @deprecated */ declare const forgeaxHttp: ForgeaxHttp; type WorkbenchHostClient = ReturnType; /** * Local copy of the platform `chat.reference.accept@1` envelope. * * wb-game-video runs both in-process inside Arrival and as an iframe inside * ForgeaX Studio, so it cannot import this shape from agentstudio — it owns * its own producer-side copy and stays structurally compatible with the * platform capability contract (see * docs/superpowers/specs/2026-08-05-chat-context-reference-capability-design.md). */ interface ContextReference { /** Namespaced, e.g. `wb-game-video.blueprint-node.v1`. */ readonly refKind: string; readonly sourceExtensionId: string; readonly display: { title: string; icon?: string; subtitle?: string; }; /** Structured payload for the agent; JSON-serializable, not a UI instruction. */ readonly payload: unknown; /** * Write-back / action hint. Agents may ignore unknown protocols. * - tools = via Host MCP tools * - path-edit = snippet/asset-style path write-back * - none = context only, no write-back */ readonly action?: { protocol: 'tools' | 'path-edit' | 'none'; toolHints?: readonly string[]; }; } /** 项目叙事文档类别;正文落在游戏根 `docs/`,由 manifest 登记。 */ type DocumentType = 'intake' | 'design-options' | 'core' | 'inquiry' | 'pillar'; type Locale = 'en' | 'zh'; interface DesignOptionsGate { busy?: boolean; onApplied?: (optionId: 'A' | 'B' | 'C', option?: { title?: string; }) => void | Promise; onRegenerate?: () => void | Promise; } type WorkbenchInitOptions = { rewrite?: RewriteRule[]; pane?: 'left' | 'center' | null; slug?: string | null; /** * A ready workbench client for in-process mounts. Without it the extension * falls back to the iframe handshake, which has no parent to answer it. */ host?: WorkbenchHostClient; /** * In-process `chat.reference.accept@1` channel. When provided, "引用到 Chat" * calls this directly instead of falling back to the iframe * `FORGEAX_COMPOSER_INSERT` postMessage handshake. */ acceptReference?: (reference: ContextReference) => void | Promise; /** * Host-owned DOM slot for the node inspector panel. When set, GraphStudio * portals the panel here and skips the canvas-embedded inspector. */ inspectorEl?: HTMLElement; /** Host-owned DOM slot for video generation inside the node preview column. */ videoGenerationEl?: HTMLElement; /** * Host-owned DOM slot for the node preview surface (video + timeline) and its * toggle pill. Only honoured together with `inspectorEl`: it splits the node * panel's two columns into two host-positioned surfaces, so the form can track * a resizable host sidebar while the preview stays a sibling beside it. */ previewEl?: HTMLElement; /** * Fired when the preview drawer opens or closes, so a host owning `previewEl` * can size its column. Errors thrown by the callback are swallowed. */ onPreviewOpenChange?: (open: boolean) => void; /** * Fired when canvas node selection changes. Pass `null` when selection clears. * Errors thrown by the callback are swallowed so selection still updates. */ onNodeSelect?: (nodeId: string | null) => void; /** * Declares what the host's inspector tab shows. Every view that fills * `inspectorEl` owns its own label, so the tab beside Agent is a generic slot * rather than a blueprint-only "节点编辑". * * `selected` drives the host's auto-switch: true focuses the slot tab, false * returns to Agent. Errors thrown by the callback are swallowed. */ onInspectorTabChange?: (tab: { label: string; selected: boolean; }) => void; /** Fired when the node preview column's video generation tab opens/closes. */ onVideoGenerationTabChange?: (tab: { label: string; selected: boolean; available: boolean; }) => void; /** * Host-owned DOM slot for document header actions (e.g. author gate bar). * DocumentLibraryView hosts this element under `.gdx-header`; the host keeps * React ownership of the slot's children. */ docActionSlotEl?: HTMLElement; /** * Initial pending document types for sidebar badges. Live updates go through * `GameVideoMountHandle.setPendingDocumentTypes` without remounting. */ pendingDocumentTypes?: DocumentType[]; /** Live actions for the design-options Slide (apply and regenerate). */ designOptionsGate?: DesignOptionsGate | null; /** * When true, an `uninitialized` package is seeded silently (via the extension * `createSeed` empty library) instead of showing the "从模板新建" guide. Hosts * opt in per mount; the default preserves the manual confirmation. */ autoInitialize?: boolean; /** * Host-controlled UI locale for in-process mounts. The mount handle can * update it without remounting when the host language changes. */ locale?: Locale; }; declare function applyHostInit(options?: WorkbenchInitOptions): void; /** * 宿主顶栏两档切换器的档位。所有编辑视图共用 `workfile` 一档——顶栏只回答 * 「在做工 / 在试玩」,具体在哪个编辑视图由侧栏决定。 */ type TopView = 'workfile' | 'play'; /** Published production-plane contracts for the video-game workbench. */ declare const PRODUCT_PHASES: readonly ["requirements-collection", "planning-design", "feature-development", "asset-generation"]; type ProductPhase = typeof PRODUCT_PHASES[number]; declare const VIDEO_GAME_ACTIVITIES: readonly ["brief.collecting", "document.inquiry", "document.core", "document.pillar", "blueprint.outline", "characters.modeling", "characters.previewing", "scenes.modeling", "scenes.previewing", "rules.catalog", "rules.binding", "ui.authoring", "game.finalizing", "assets.character", "assets.scene", "video.presets.binding", "video.presets.validating", "playtest.validating"]; type VideoGameActivity = typeof VIDEO_GAME_ACTIVITIES[number]; type ProductPhaseStatus = 'not-started' | 'working' | 'awaiting-user' | 'blocked' | 'complete'; type ActivityStatus = ProductPhaseStatus | 'not-required'; type ModuleAvailability = 'hidden' | 'working' | 'ready' | 'blocked'; type WorkbenchLocation = { kind: 'document'; documentType: 'intake' | 'design-options' | 'core' | 'inquiry' | 'pillar'; } | { kind: 'blueprint'; blueprintId?: string; nodeId?: string; } | { kind: 'rule'; section: 'entities' | 'variables' | 'formulas'; itemId?: string; } | { kind: 'ui'; treeNodeId?: string; overlayId?: string; } | { kind: 'asset'; root: 'character' | 'scene' | 'image' | 'video' | 'audio' | 'font'; folderId?: string; entryId?: string; } | { kind: 'play'; nodeId?: string; }; interface ArtifactRef { kind: string; id: string; revision: number; /** Manifest revision paired with a cross-file asset-lane commit. */ assetRevision?: number; /** Compound node identities covered by a node.media binding receipt. */ nodeRefs?: Array<{ blueprintId: string; nodeId: string; }>; /** Stable replay identity of the mutation that produced this artifact. */ idempotencyKey?: string; /** Exact asset entities covered by an asset-lane completion receipt. */ targetIds?: string[]; status?: 'working' | 'ready' | 'failed'; } interface ValidationIssue { level: 'error' | 'warning'; code: string; message: string; location?: WorkbenchLocation; /** * 该由哪个活动返工。只读活动(如 `playtest.validating`)看得见问题却改不了, * 归属靠模型判断会判错(实测把界面缺口当成整装的活,同样的边改了三遍), * 所以由 Host 按码推导(见 `issue-owner.ts`)。认不出时缺省。 */ owner?: VideoGameActivity; } interface ValidationEvidence { schemaVersion: 1; activity: VideoGameActivity; activityRevision: number; projectRevision?: number; checkId: string; /** * `warn` 是质量提示而不是失败:语言漂移这类问题应该被看见, * 但拦住 `complete_activity` 会把一次润色变成一次撞墙(设计 §11.4)。 */ status: 'pass' | 'fail' | 'not-required' | 'warn'; observedAt: string; details?: Record; issues?: ValidationIssue[]; } interface ValidationSummary { projectRevision: number; structural: 'pass' | 'fail' | 'not-run'; semantic: 'pass' | 'fail' | 'not-run'; references: 'pass' | 'fail' | 'not-run'; productionReadiness: 'pass' | 'fail' | 'not-required' | 'not-run'; choices: 'pass' | 'fail' | 'not-required' | 'not-run'; playable: 'pass' | 'fail' | 'not-run'; issues: ValidationIssue[]; } interface WorkflowBlocker { code: string; message: string; retryable: boolean; activity: VideoGameActivity; activityRevision: number; location?: WorkbenchLocation; createdAt: string; } interface ActivityNotice { activity: VideoGameActivity; activityRevision: number; noticeRevision: number; /** * `upcoming` = 上一步交付完、下一步还没开始的那段间隙。作者已经确认过支柱了, * 提示条还写「正在建立游戏支柱…」会让人以为流程卡住,所以这段报下一步。 */ kind: 'progress' | 'upcoming' | 'awaiting-user' | 'blocked' | 'retrying'; messageKey: string; params?: Record; location?: WorkbenchLocation; } interface ActivityRecord { revision: number; status: ActivityStatus; startedAt?: string; completedAt?: string; artifactRefs: ArtifactRef[]; evidence: ValidationEvidence[]; blocker?: WorkflowBlocker; } interface PhaseRecord { revision: number; status: ProductPhaseStatus; openedAt?: string; completedAt?: string; } /** 六维需求契约。删除 `document.intake` 后,它是需求的唯一留存形态(设计 §9.10)。 */ interface RequirementContract { schemaVersion: 1; /** 作者第一句原文,原样保留不改写。 */ rawIntent: string; dimensions: Record; visualStyle?: { id: string; name: string; }; locale: string; collectedAt: string; /** 超长输入被截断时置位,便于诊断而不是静默丢内容。 */ truncated?: boolean; } /** 核心方案生成前的一次性高影响取舍;不落文档,也不产生侧边栏入口。 */ interface InquiryContract { schemaVersion: 1; answers: Array<{ question: string; answer: string; }>; collectedAt: string; truncated?: boolean; } interface ActiveGroupRecord { id: string; activities: VideoGameActivity[]; status: ProductPhaseStatus; revision: number; } type AssetPipelineStatus = 'not-started' | 'working' | 'partial' | 'blocked' | 'ready'; type AssetReadinessStatus = 'pending' | 'working' | 'ready' | 'failed'; interface AssetPipelineState { schemaVersion: 1; revision: number; status: AssetPipelineStatus; activeActivities: VideoGameActivity[]; blockers: WorkflowBlocker[]; readiness: { characters: AssetReadinessStatus; scenes: AssetReadinessStatus; videoPresets: AssetReadinessStatus; }; } interface VideoGameWorkflowState { schemaVersion: 2; gameId: string; revision: number; productPhase: ProductPhase; phaseRevision: number; phaseStatus: ProductPhaseStatus; /** * 组内代表活动,保留给旧读取方(阶段条、旧 UI)。 * 并发下应读 `activeGroup.activities`,不要假设只有一个活动在跑。 */ activity: VideoGameActivity; activityRevision: number; activityStatus: ActivityStatus; activeGroup: ActiveGroupRecord; assetPipeline: AssetPipelineState; requirementContract?: RequirementContract; inquiryContract?: InquiryContract; phases: Record; activities: Partial>; artifactRefs: ArtifactRef[]; validationEvidence: ValidationEvidence[]; blockers: WorkflowBlocker[]; gates: Record; productionRefs: string[]; history: Array<{ revision: number; activity: VideoGameActivity; activityRevision: number; status: ActivityStatus; at: string; reason?: string; }>; noticeRevision: number; focus?: { location: WorkbenchLocation; reason: 'activity-started' | 'artifact-created' | 'user-action-required' | 'validation-failed'; revision: number; }; updatedAt: string; } interface ProductionProjection { schemaVersion: 1; gameId: string; workflowRevision: number; phase: ProductPhase; phaseRevision: number; phaseStatus: ProductPhaseStatus; /** 代表活动,保留兼容;并发下请读 `activeActivities`。 */ activity: VideoGameActivity; activityRevision: number; activityStatus: ActivityStatus; /** 当前组内所有正在进行的活动。串行段长度为 1,并发段可为多个。 */ activeActivities: VideoGameActivity[]; group: { id: string; status: ProductPhaseStatus; revision: number; }; phases: Record; modules: Record; gates: VideoGameWorkflowState['gates']; artifacts: ArtifactRef[]; assetPipeline?: AssetPipelineState; validation?: ValidationSummary; notice?: ActivityNotice; focus?: VideoGameWorkflowState['focus']; } /** 宿主顶栏两档切换器的档位;所有编辑视图共用 `workfile`。 */ type GameVideoTopView = TopView; interface GameVideoMountHandle { unmount(): void; openDocument(type: DocumentType): void; setPendingDocumentTypes(types: readonly DocumentType[]): void; setDesignOptionsGate(gate: DesignOptionsGate | null): void; /** * 宿主插槽页签的激活态。宿主把 Agent 页签切到前台时传 false:节点面板不可见, * 预览抽屉与挂在画布上的开关拉片一并收起(拉片在扩展 DOM 里,宿主藏不掉)。 */ setInspectorActive(active: boolean): void; getTopView(): GameVideoTopView; /** * 顶栏两档切换。与侧栏「试玩」写的是同一个 view store,所以两处入口天然同步; * `'workfile'` 回到进试玩前的那个编辑视图,不硬编码回蓝图。 */ setTopView(view: GameVideoTopView): void; /** 只在档位真的换了时回调——侧栏在编辑视图之间跳不该惊动顶栏。 */ subscribeTopView(listener: (view: GameVideoTopView) => void): () => void; /** Update every mounted wb-game-video component to the host locale. */ setLocale(locale: Locale): void; /** Host/Agent semantic navigation. This never reaches into DOM selectors. */ navigate(location: WorkbenchLocation): boolean; /** Apply a versioned server-side projection and follow its focus when enabled. */ setProductionProjection(projection: ProductionProjection): void; } declare function mount(rootEl: HTMLElement, options?: WorkbenchInitOptions): GameVideoMountHandle; export { type GameVideoMountHandle, type GameVideoTopView, type Locale, type ProductionProjection, type WorkbenchHostClient, type WorkbenchInitOptions, type WorkbenchLocation, applyHostInit, forgeaxHttp, mount };