@easytwin/devkit 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/config.ts","../src/client.ts","../src/scene.ts","../src/upload.ts","../src/workspace.ts","../src/assetsPath.ts","../src/skills.ts","../src/bundle.ts","../src/apps.ts","../src/twinAppHost.ts"],"sourcesContent":["import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\n\n/** 配置文件名(项目根)。 */\nexport const CONFIG_FILE_NAME = \"easytwin.config.json\";\n\n/**\n * 官方缺省域名(正式环境)。该常量是全仓唯一收口点,只允许写在这里。\n */\nexport const DEFAULT_BASE_URL = \"http://saas-twin.k8s.dtstack.cn/\";\n/** 官方测试环境域名。 */\nexport const TEST_BASE_URL = \"http://172.16.125.3:10100/\";\n/**\n * 当前测试 OP 网关缺省头(与编辑器 curl 一致)。配置/环境变量可覆盖。\n * 免网关接口到位后删除(D13)。\n */\nexport const TEST_OP_ACCOUNT_ID = \"25\";\nexport const TEST_OP_USER_ID = \"25\";\nexport const TEST_SPACE_ID = \"54\";\n/**\n * 官方 OSS(twin runtime baseOSSUrl)。系统资产由此拼出:\n * `{ossUrl}/easytwin/system/libs/webp-wasm.wasm`、\n * `{ossUrl}/easytwin/system/libs/draco/`、\n * `{ossUrl}/easytwin/system/components/custom/{type}/{version}/script.js`。\n * 不得用 API baseUrl 代替:场景/上传走 API,系统库与组件脚本走 OSS。\n */\nexport const DEFAULT_OSS_URL = \"https://dt-easyv-test.oss-cn-hangzhou.aliyuncs.com/\";\n\n/** 服务环境,决定缺省 baseUrl。 */\nexport type EasyTwinEnv = \"prod\" | \"test\";\n/** 本地测试模式哨兵凭据:appId 与 appSecret 均为该值时,场景/上传走本地 mock,不发网络请求(见 AGENTS.md 4.4)。 */\nexport const MOCK_APP_ID = \"test\";\nexport const MOCK_APP_SECRET = \"test\";\n\n/** appId/appSecret 是否命中本地测试模式哨兵值。 */\nexport function isMockCredentials(appId: string, appSecret: string): boolean {\n return appId === MOCK_APP_ID && appSecret === MOCK_APP_SECRET;\n}\n\n/** 磁盘上的配置结构(4.3 配置契约)。 */\nexport interface EasyTwinConfig {\n appId: string;\n appSecret: string;\n /** 服务环境,缺省 prod。 */\n env?: EasyTwinEnv;\n baseUrl?: string;\n /** twin runtime 资产根(baseOSSUrl);缺省官方 OSS,可覆盖为 CDN/自建存储。 */\n ossUrl?: string;\n /** 过渡期 OP 网关头;免网关接口到位后删除(D13)。 */\n opAccountId?: string;\n opUserId?: string;\n spaceId?: string;\n /**\n * 关联场景摘要,由 scene list / 场景树刷新写入(D17)。\n * 不含场景 JSON 本体;下次 list 全量覆盖。\n */\n scenes?: ConfigScene[];\n}\n\n/** 写入 easytwin.config.json 的关联场景摘要(对应 listScenes 的可序列化子集)。 */\nexport interface ConfigScene {\n /** Scene Key,与 `easytwin scene pull <id>` 对应。 */\n id: string;\n name: string;\n linkedSceneId?: string;\n snapshotUrl?: string;\n defaultLoading?: boolean;\n}\n\n/** 解析 + 环境变量覆盖后的最终配置。 */\nexport interface ResolvedConfig {\n appId: string;\n appSecret: string;\n baseUrl: string;\n /** twin runtime baseOSSUrl(系统库 draco/basis/webp、custom script 与相对路径资产);缺省官方 OSS。 */\n ossUrl: string;\n /** 本地测试模式:appId/appSecret 均为 \"test\" 时启用,scene/upload/pull 走本地 mock 不发请求。 */\n mock: boolean;\n source: \"file\" | \"env\";\n /** 过渡期 OP 网关头;env=test 时缺省 25/25/54。免网关接口到位后删除(D13)。 */\n opAccountId?: string;\n opUserId?: string;\n spaceId?: string;\n}\n\nexport class ConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigError\";\n }\n}\n\nexport function configFilePath(cwd: string): string {\n return path.join(cwd, CONFIG_FILE_NAME);\n}\n\nexport function parseConfig(raw: string): EasyTwinConfig {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new ConfigError(`配置文件不是合法 JSON:${CONFIG_FILE_NAME}`);\n }\n return validateConfigShape(parsed);\n}\n\nexport function validateConfigShape(value: unknown): EasyTwinConfig {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new ConfigError(\"配置必须是 JSON 对象\");\n }\n const v = value as Record<string, unknown>;\n if (typeof v.appId !== \"string\" || v.appId.length === 0) {\n throw new ConfigError(\"配置缺少必填字段 appId\");\n }\n if (typeof v.appSecret !== \"string\" || v.appSecret.length === 0) {\n throw new ConfigError(\"配置缺少必填字段 appSecret\");\n }\n if (v.baseUrl !== undefined && (typeof v.baseUrl !== \"string\" || v.baseUrl.length === 0)) {\n throw new ConfigError(\"baseUrl 必须是非空字符串\");\n }\n if (v.ossUrl !== undefined && (typeof v.ossUrl !== \"string\" || v.ossUrl.length === 0)) {\n throw new ConfigError(\"ossUrl 必须是非空字符串\");\n }\n if (v.env !== undefined && v.env !== \"prod\" && v.env !== \"test\") {\n throw new ConfigError(\"env 必须是 prod 或 test\");\n }\n const opAccountId = optionalGatewayId(v.opAccountId);\n const opUserId = optionalGatewayId(v.opUserId);\n const spaceId = optionalGatewayId(v.spaceId);\n const config: EasyTwinConfig = { appId: v.appId, appSecret: v.appSecret };\n if (v.env === \"prod\" || v.env === \"test\") config.env = v.env;\n if (typeof v.baseUrl === \"string\") config.baseUrl = v.baseUrl;\n if (typeof v.ossUrl === \"string\") config.ossUrl = v.ossUrl;\n if (opAccountId) config.opAccountId = opAccountId;\n if (opUserId) config.opUserId = opUserId;\n if (spaceId) config.spaceId = spaceId;\n const scenes = parseConfigScenes(v.scenes);\n if (scenes) config.scenes = scenes;\n return config;\n}\n\n/** 过渡期网关头:字符串或数字均可,空串视为未配置。 */\nfunction optionalGatewayId(value: unknown): string | undefined {\n if (typeof value === \"string\") {\n const t = value.trim();\n return t.length > 0 ? t : undefined;\n }\n if (typeof value === \"number\" && Number.isFinite(value)) return String(value);\n if (value !== undefined) throw new ConfigError(\"opAccountId / opUserId / spaceId 必须是字符串或数字\");\n return undefined;\n}\n\nfunction parseConfigScenes(value: unknown): ConfigScene[] | undefined {\n if (value === undefined) return undefined;\n if (!Array.isArray(value)) throw new ConfigError(\"scenes 必须是数组\");\n return value.map((item, i) => {\n if (typeof item !== \"object\" || item === null || Array.isArray(item)) {\n throw new ConfigError(`scenes[${i}] 必须是对象`);\n }\n const it = item as Record<string, unknown>;\n if (typeof it.id !== \"string\" || it.id.length === 0) {\n throw new ConfigError(`scenes[${i}] 缺少必填字段 id`);\n }\n if (typeof it.name !== \"string\" || it.name.length === 0) {\n throw new ConfigError(`scenes[${i}] 缺少必填字段 name`);\n }\n const scene: ConfigScene = { id: it.id, name: it.name };\n if (it.linkedSceneId !== undefined) {\n if (typeof it.linkedSceneId !== \"string\") throw new ConfigError(`scenes[${i}].linkedSceneId 必须是字符串`);\n if (it.linkedSceneId.length > 0) scene.linkedSceneId = it.linkedSceneId;\n }\n if (it.snapshotUrl !== undefined) {\n if (typeof it.snapshotUrl !== \"string\") throw new ConfigError(`scenes[${i}].snapshotUrl 必须是字符串`);\n if (it.snapshotUrl.length > 0) scene.snapshotUrl = it.snapshotUrl;\n }\n if (it.defaultLoading !== undefined) {\n if (typeof it.defaultLoading !== \"boolean\") throw new ConfigError(`scenes[${i}].defaultLoading 必须是布尔值`);\n scene.defaultLoading = it.defaultLoading;\n }\n return scene;\n });\n}\n\nexport async function readConfigFile(cwd: string): Promise<EasyTwinConfig> {\n const file = configFilePath(cwd);\n let raw: string;\n try {\n raw = await fs.readFile(file, \"utf8\");\n } catch {\n throw new ConfigError(`未找到配置文件 ${file},请先运行 \\`easytwin init\\``);\n }\n return parseConfig(raw);\n}\n\n/** 环境变量优先于文件(CI 与不落盘场景)。 */\nexport function resolveConfig(file: EasyTwinConfig, env: NodeJS.ProcessEnv = process.env): ResolvedConfig {\n const appId = env.EASYTWIN_APP_ID ?? file.appId;\n const appSecret = env.EASYTWIN_APP_SECRET ?? file.appSecret;\n const easyEnv: EasyTwinEnv =\n env.EASYTWIN_ENV === \"test\" || env.EASYTWIN_ENV === \"prod\" ? env.EASYTWIN_ENV : file.env ?? \"prod\";\n const baseUrl = env.EASYTWIN_BASE_URL ?? file.baseUrl ?? (easyEnv === \"test\" ? TEST_BASE_URL : DEFAULT_BASE_URL);\n // 资产根缺省官方 OSS,与 API baseUrl 分离;EASYTWIN_OSS_URL / 文件 ossUrl 始终优先。\n const ossUrl = env.EASYTWIN_OSS_URL ?? file.ossUrl ?? DEFAULT_OSS_URL;\n if (!appId) throw new ConfigError(\"缺少 appId:配置文件中未提供,且未设置环境变量 EASYTWIN_APP_ID\");\n if (!appSecret) throw new ConfigError(\"缺少 appSecret:配置文件中未提供,且未设置环境变量 EASYTWIN_APP_SECRET\");\n const source: ResolvedConfig[\"source\"] =\n env.EASYTWIN_APP_ID !== undefined || env.EASYTWIN_APP_SECRET !== undefined ? \"env\" : \"file\";\n const useTestGateway = easyEnv === \"test\";\n const opAccountId =\n optionalGatewayId(env.EASYTWIN_OP_ACCOUNT_ID) ?? file.opAccountId ?? (useTestGateway ? TEST_OP_ACCOUNT_ID : undefined);\n const opUserId =\n optionalGatewayId(env.EASYTWIN_OP_USER_ID) ?? file.opUserId ?? (useTestGateway ? TEST_OP_USER_ID : undefined);\n const spaceId =\n optionalGatewayId(env.EASYTWIN_SPACE_ID) ?? file.spaceId ?? (useTestGateway ? TEST_SPACE_ID : undefined);\n const resolved: ResolvedConfig = { appId, appSecret, baseUrl, ossUrl, mock: isMockCredentials(appId, appSecret), source };\n if (opAccountId) resolved.opAccountId = opAccountId;\n if (opUserId) resolved.opUserId = opUserId;\n if (spaceId) resolved.spaceId = spaceId;\n return resolved;\n}\n\nexport async function loadConfig(cwd: string, env: NodeJS.ProcessEnv = process.env): Promise<ResolvedConfig> {\n const file = await readConfigFile(cwd);\n const resolved = resolveConfig(file, env);\n // 测试环境缺网关头时回写缺省值,让 easytwin.config.json 里能看到实际发出的 op-*。\n if (file.env === \"test\" && env.EASYTWIN_OP_ACCOUNT_ID === undefined && env.EASYTWIN_OP_USER_ID === undefined && env.EASYTWIN_SPACE_ID === undefined) {\n if (!file.opAccountId || !file.opUserId || !file.spaceId) {\n await writeConfigFile(cwd, {\n ...file,\n opAccountId: file.opAccountId ?? TEST_OP_ACCOUNT_ID,\n opUserId: file.opUserId ?? TEST_OP_USER_ID,\n spaceId: file.spaceId ?? TEST_SPACE_ID,\n });\n }\n }\n return resolved;\n}\n\nexport async function writeConfigFile(cwd: string, config: EasyTwinConfig): Promise<string> {\n const file = configFilePath(cwd);\n const body: EasyTwinConfig = { appId: config.appId, appSecret: config.appSecret };\n if (config.env) body.env = config.env;\n if (config.baseUrl) body.baseUrl = config.baseUrl;\n if (config.ossUrl) body.ossUrl = config.ossUrl;\n const opAccountId = config.opAccountId ?? (config.env === \"test\" ? TEST_OP_ACCOUNT_ID : undefined);\n const opUserId = config.opUserId ?? (config.env === \"test\" ? TEST_OP_USER_ID : undefined);\n const spaceId = config.spaceId ?? (config.env === \"test\" ? TEST_SPACE_ID : undefined);\n if (opAccountId) body.opAccountId = opAccountId;\n if (opUserId) body.opUserId = opUserId;\n if (spaceId) body.spaceId = spaceId;\n if (config.scenes !== undefined) body.scenes = config.scenes;\n await fs.mkdir(cwd, { recursive: true });\n await fs.writeFile(file, JSON.stringify(body, null, 2) + \"\\n\", \"utf8\");\n return file;\n}\n\nexport const GITIGNORE_FILE_NAME = \".gitignore\";\nexport const GITIGNORE_ENTRY = \"easytwin.config.json\";\n\nexport interface GitignoreResult {\n created: boolean;\n added: boolean;\n}\n\n/** 把配置文件名追加进 .gitignore(无则创建),幂等:已存在条目时不重复追加。 */\nexport async function appendGitignore(cwd: string): Promise<GitignoreResult> {\n const file = path.join(cwd, GITIGNORE_FILE_NAME);\n let content = \"\";\n let created = false;\n try {\n content = await fs.readFile(file, \"utf8\");\n } catch {\n created = true;\n }\n const lines = content.split(/\\r?\\n/);\n if (lines.includes(GITIGNORE_ENTRY)) return { created, added: false };\n const prefix = content.length > 0 && !content.endsWith(\"\\n\") ? \"\\n\" : \"\";\n await fs.writeFile(file, content + prefix + GITIGNORE_ENTRY + \"\\n\", \"utf8\");\n return { created, added: true };\n}\n\nexport interface InitResult {\n configFile: string;\n gitignore: GitignoreResult;\n}\n\n/** init 的 lib 实现:生成配置文件 + 追加 gitignore(与插件配置向导共用同一实现)。 */\nexport async function initConfig(input: EasyTwinConfig, cwd: string): Promise<InitResult> {\n const validated = validateConfigShape(input);\n const configFile = await writeConfigFile(cwd, validated);\n const gitignore = await appendGitignore(cwd);\n return { configFile, gitignore };\n}\n\n/** 把场景摘要写入配置 `scenes`(全量覆盖该数组,保留其余字段)。 */\nexport async function writeConfigScenes(cwd: string, scenes: ConfigScene[]): Promise<void> {\n const file = await readConfigFile(cwd);\n await writeConfigFile(cwd, { ...file, scenes });\n}","import http from \"node:http\";\r\nimport https from \"node:https\";\r\nimport { URL } from \"node:url\";\r\nimport type { ResolvedConfig } from \"./config\";\r\n\r\n/**\r\n * 认证与路径以内部 swagger 为准(标签:SDK 应用场景 / SDK 应用代码 / SDK Runtime)。\r\n * 全仓唯一认证头注入点:`x-app-secret` = App Secret。\r\n * 过渡期另注入 OP 网关头 op-account-id / op-user-id / space-id(D13,免网关接口到位后删除)。\r\n * 场景/代码路径参数名为 applicationId;DevKit 传入配置里的 App ID。\r\n */\r\nexport const AUTH_HEADER = \"x-app-secret\";\r\n/** 过渡期 OP 网关头;免网关接口到位后删除(D13)。 */\r\nexport const OP_ACCOUNT_ID_HEADER = \"op-account-id\";\r\nexport const OP_USER_ID_HEADER = \"op-user-id\";\r\nexport const SPACE_ID_HEADER = \"space-id\";\r\n\r\nfunction enc(id: string): string {\r\n return encodeURIComponent(id);\r\n}\r\n\r\nexport const ENDPOINTS = {\r\n /** GET 已关联场景列表。 */\r\n linkedScenes: (applicationId: string) => `/api/twin/v1/sdk-application-scenes/${enc(applicationId)}/scenes`,\r\n /** GET 工作区全部代码文件。 */\r\n workspaceCode: (applicationId: string) => `/api/twin/v1/sdk-application-code/${enc(applicationId)}`,\r\n /** GET 工作区文件约束。 */\r\n workspaceConfig: (applicationId: string) =>\r\n `/api/twin/v1/sdk-application-code/${enc(applicationId)}/workspace-config`,\r\n /** POST 新建 / PATCH 批量更新 / DELETE 批量删除。 */\r\n workspaceCodeFiles: (applicationId: string) => `/api/twin/v1/sdk-application-code/${enc(applicationId)}/files`,\r\n} as const;\r\n\r\nexport class EasyTwinApiError extends Error {\r\n readonly status: number;\r\n readonly body: unknown;\r\n constructor(status: number, message: string, body?: unknown) {\r\n super(message);\r\n this.name = \"EasyTwinApiError\";\r\n this.status = status;\r\n this.body = body;\r\n }\r\n}\r\n\r\nexport interface RequestOptions {\r\n method?: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\r\n headers?: Record<string, string>;\r\n body?: string | null;\r\n signal?: AbortSignal;\r\n}\r\n\r\ninterface RawResponse {\r\n status: number;\r\n body: Buffer;\r\n}\r\n\r\nfunction messageFromBody(body: unknown): string | undefined {\r\n if (typeof body === \"object\" && body !== null) {\r\n const m = (body as Record<string, unknown>).message;\r\n if (typeof m === \"string\") return m;\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction parseResponseBody(buffer: Buffer): unknown {\r\n const text = buffer.toString(\"utf8\");\r\n if (text.length === 0) return undefined;\r\n try {\r\n return JSON.parse(text);\r\n } catch {\r\n return text;\r\n }\r\n}\r\n\r\nfunction isEnvelope(value: unknown): value is { success: unknown; data?: unknown } {\r\n return typeof value === \"object\" && value !== null && !Array.isArray(value) && \"success\" in value;\r\n}\r\n\r\n/**\r\n * EasyTwin 网关常见信封:`{ success, data, message }`。\r\n * success=false 即使 HTTP 200 也当失败;success=true 时取出 data。\r\n */\r\nfunction unwrapBody(parsed: unknown, status: number): unknown {\r\n if (!isEnvelope(parsed)) return parsed;\r\n if (parsed.success === false) {\r\n throw new EasyTwinApiError(status, messageFromBody(parsed) ?? \"请求失败\", parsed);\r\n }\r\n if (parsed.success === true && \"data\" in parsed) return parsed.data;\r\n return parsed;\r\n}\r\n\r\nexport class EasyTwinClient {\r\n readonly baseUrl: string;\r\n /** twin runtime / 场景快照资产根(baseOSSUrl)。 */\r\n readonly ossUrl: string;\r\n /** 接入凭证 App ID;同时作为场景/代码 API 的 applicationId 路径参数。 */\r\n readonly appId: string;\r\n /** 本地测试模式:true 时 scene/upload/pull 走本地 mock,不发网络请求(见 config.ts)。 */\r\n readonly mock: boolean;\r\n private readonly appSecret: string;\r\n private readonly opAccountId?: string;\r\n private readonly opUserId?: string;\r\n private readonly spaceId?: string;\r\n\r\n constructor(config: ResolvedConfig) {\r\n this.baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\r\n this.ossUrl = config.ossUrl.replace(/\\/+$/, \"\");\r\n this.mock = config.mock;\r\n this.appId = config.appId;\r\n this.appSecret = config.appSecret;\r\n this.opAccountId = config.opAccountId;\r\n this.opUserId = config.opUserId;\r\n this.spaceId = config.spaceId;\r\n }\r\n\r\n /** 全仓唯一认证头注入点。 */\r\n private authHeaders(): Record<string, string> {\r\n const headers: Record<string, string> = { [AUTH_HEADER]: this.appSecret };\r\n if (this.opAccountId) headers[OP_ACCOUNT_ID_HEADER] = this.opAccountId;\r\n if (this.opUserId) headers[OP_USER_ID_HEADER] = this.opUserId;\r\n if (this.spaceId) headers[SPACE_ID_HEADER] = this.spaceId;\r\n return headers;\r\n }\r\n\r\n /** JSON 请求(原生 fetch)。 */\r\n async request(path: string, options: RequestOptions = {}): Promise<unknown> {\r\n const url = `${this.baseUrl}${path}`;\r\n const headers: Record<string, string> = { ...this.authHeaders(), ...options.headers };\r\n if (options.body !== undefined && options.body !== null && !(\"Content-Type\" in headers)) {\r\n headers[\"Content-Type\"] = \"application/json\";\r\n }\r\n let res: Response;\r\n try {\r\n res = await fetch(url, {\r\n method: options.method ?? \"GET\",\r\n headers,\r\n body: options.body,\r\n signal: options.signal,\r\n });\r\n } catch (err) {\r\n throw new EasyTwinApiError(0, `请求失败:${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n return this.handleStatus(res.status, Buffer.from(await res.arrayBuffer()));\r\n }\r\n\r\n /**\r\n * multipart 流式上传(手写 http 请求以支持逐字节进度回调)。\r\n * 这是 fetch 上传的替代路径:原生 fetch 无法上报上传进度。\r\n */\r\n async upload(\r\n path: string,\r\n options: { boundary: string; body: Buffer; onBytes?: (bytes: number) => void }\r\n ): Promise<unknown> {\r\n const url = new URL(`${this.baseUrl}${path}`);\r\n const mod = url.protocol === \"https:\" ? https : http;\r\n const headers: Record<string, string> = {\r\n ...this.authHeaders(),\r\n \"Content-Type\": `multipart/form-data; boundary=${options.boundary}`,\r\n \"Content-Length\": String(options.body.length),\r\n };\r\n const raw = await new Promise<RawResponse>((resolve, reject) => {\r\n const req = mod.request(url, { method: \"POST\", headers }, (res) => {\r\n const chunks: Buffer[] = [];\r\n res.on(\"data\", (c: Buffer) => chunks.push(c));\r\n res.on(\"end\", () => resolve({ status: res.statusCode ?? 0, body: Buffer.concat(chunks) }));\r\n });\r\n req.on(\"error\", reject);\r\n const CHUNK = 64 * 1024;\r\n let offset = 0;\r\n const sendNext = (): void => {\r\n if (offset >= options.body.length) {\r\n req.end();\r\n return;\r\n }\r\n const chunk = options.body.subarray(offset, offset + CHUNK);\r\n offset += chunk.length;\r\n req.write(chunk, () => {\r\n options.onBytes?.(chunk.length);\r\n sendNext();\r\n });\r\n };\r\n sendNext();\r\n });\r\n return this.handleStatus(raw.status, raw.body);\r\n }\r\n\r\n private handleStatus(status: number, body: Buffer): unknown {\r\n const parsed = parseResponseBody(body);\r\n if (status >= 200 && status < 300) return unwrapBody(parsed, status);\r\n throw new EasyTwinApiError(status, messageFromBody(parsed) ?? `HTTP ${status}`, parsed);\r\n }\r\n}\r\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { writeConfigScenes, type ConfigScene } from \"./config\";\nimport { EasyTwinApiError, ENDPOINTS, type EasyTwinClient } from \"./client\";\n\n/** swagger `SdkApplicationLinkedSceneVo`。 */\nexport interface LinkedScene {\n /** 关联记录 ID。 */\n id: string;\n /** SDK 业务标识 Scene Key(list/pull 的主键)。 */\n sceneKey: string;\n name: string;\n defaultLoading: boolean;\n sourceSceneId: string;\n sourceProjectId: string;\n sourceSceneName: string;\n sourceProjectName: string;\n sourceLost: boolean;\n /** 场景快照 JSON 的 OSS 相对路径(或绝对 URL)。 */\n snapshotUrl: string;\n snapshotUpdatedAt: string;\n}\n\nexport interface SceneSummary {\n /** Scene Key,与 `easytwin scene pull <id>` 对应。 */\n id: string;\n name: string;\n linkedSceneId?: string;\n snapshotUrl?: string;\n defaultLoading?: boolean;\n}\n\nexport interface SceneDetail {\n id: string;\n name: string;\n /**\n * 场景快照 JSON 原始内容。\n * 结构以 easytwin-runtime 的 SceneJson 为准(见 skills/easytwin-scene)。\n */\n payload: unknown;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction asString(value: unknown): string {\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction asBoolean(value: unknown): boolean {\n return value === true;\n}\n\n/** 从信封/Runtime VO/数组中取出场景列表。 */\nexport function extractSceneArray(data: unknown): unknown[] {\n if (Array.isArray(data)) return data;\n const root = asRecord(data);\n if (Array.isArray(root.data)) return root.data;\n if (Array.isArray(root.list)) return root.list;\n if (Array.isArray(root.scenes)) return root.scenes;\n const nested = asRecord(root.data);\n if (Array.isArray(nested.scenes)) return nested.scenes;\n if (Array.isArray(nested.list)) return nested.list;\n throw new Error(\"scene list 响应结构无法识别\");\n}\n\n/** 把 swagger 关联场景 / Runtime scenes 规范为 LinkedScene[]。 */\nexport function normalizeLinkedScenes(data: unknown): LinkedScene[] {\n const list = extractSceneArray(data);\n return list.map((item) => {\n const it = asRecord(item);\n const sceneKey = asString(it.sceneKey);\n const sourceProjectName = asString(it.sourceProjectName);\n const sourceSceneName = asString(it.sourceSceneName);\n return {\n id: asString(it.id),\n sceneKey,\n name: sourceProjectName || sourceSceneName || sceneKey,\n defaultLoading: asBoolean(it.defaultLoading),\n sourceSceneId: asString(it.sourceSceneId),\n sourceProjectId: asString(it.sourceProjectId),\n sourceSceneName,\n sourceProjectName,\n sourceLost: asBoolean(it.sourceLost),\n snapshotUrl: asString(it.snapshotUrl),\n snapshotUpdatedAt: asString(it.snapshotUpdatedAt),\n };\n });\n}\n\nexport function normalizeSceneList(data: unknown): SceneSummary[] {\n return normalizeLinkedScenes(data).map((s) => ({\n id: s.sceneKey,\n name: s.name,\n linkedSceneId: s.id,\n snapshotUrl: s.snapshotUrl,\n defaultLoading: s.defaultLoading,\n }));\n}\n\n/** 把 list 结果收成配置里的 scenes 摘要(省略空可选字段)。 */\nexport function toConfigScenes(scenes: SceneSummary[]): ConfigScene[] {\n return scenes.map((s) => {\n const item: ConfigScene = { id: s.id, name: s.name };\n if (s.linkedSceneId) item.linkedSceneId = s.linkedSceneId;\n if (s.snapshotUrl) item.snapshotUrl = s.snapshotUrl;\n if (s.defaultLoading !== undefined) item.defaultLoading = s.defaultLoading;\n return item;\n });\n}\n\n/** 拼接场景快照地址:绝对 URL 原样使用,否则挂到 ossUrl 下。 */\nexport function resolveSnapshotUrl(ossUrl: string, snapshotUrl: string): string {\n if (/^https?:\\/\\//i.test(snapshotUrl)) return snapshotUrl;\n const base = ossUrl.replace(/\\/+$/, \"\");\n const rel = snapshotUrl.replace(/^\\/+/, \"\");\n return `${base}/${rel}`;\n}\n\nasync function fetchSnapshotJson(ossUrl: string, snapshotUrl: string): Promise<unknown> {\n if (snapshotUrl.length === 0) throw new Error(\"场景快照地址为空\");\n const url = resolveSnapshotUrl(ossUrl, snapshotUrl);\n let res: Response;\n try {\n res = await fetch(url);\n } catch (err) {\n throw new EasyTwinApiError(0, `拉取场景快照失败:${url}:${err instanceof Error ? err.message : String(err)}`);\n }\n if (!res.ok) {\n throw new EasyTwinApiError(res.status, `拉取场景快照失败:HTTP ${res.status} ${url}`);\n }\n try {\n return (await res.json()) as unknown;\n } catch {\n throw new Error(`场景快照不是合法 JSON:${url}`);\n }\n}\n\n/** devkit 包内本地测试场景文件名(4.4 本地测试模式)。 */\nexport const EXAMPLE_SCENE_FILE = \"scene.example.json\";\n/** 本地测试模式下场景列表展示的名字(示例文件本身不含场景级 name)。 */\nexport const MOCK_SCENE_NAME = \"本地示例场景\";\n\n/**\n * 示例场景文件默认路径:devkit 包内 scene.example.json(CLI/源码)。\n * 插件 bundle 到 CJS 后 import.meta.url 为空,必须经 listScenes/pullScene 的 exampleFile 显式传入(与 skills 的 sourceDir 同理)。\n */\nexport function resolveExampleScenePath(): string {\n if (typeof import.meta.url !== \"string\" || import.meta.url.length === 0) {\n throw new Error(`无法定位 ${EXAMPLE_SCENE_FILE}:插件(bundle/CJS)场景必须显式传入 exampleFile`);\n }\n return path.resolve(path.dirname(fileURLToPath(import.meta.url)), \"..\", EXAMPLE_SCENE_FILE);\n}\n\n/** 读取并解析本地示例场景(本地测试模式专用,不发网络请求)。 */\nexport async function loadExampleScene(exampleFile?: string): Promise<unknown> {\n const file = exampleFile ?? resolveExampleScenePath();\n let raw: string;\n try {\n raw = await fs.readFile(file, \"utf8\");\n } catch {\n throw new Error(`无法读取本地示例场景 ${file}(本地测试模式需要 devkit 包内的 ${EXAMPLE_SCENE_FILE})`);\n }\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n throw new Error(`本地示例场景不是合法 JSON:${file}`);\n }\n}\n\n/** 从示例场景提取场景 id:取 objs[].sceneId 首个非空值;无则回退 \"local\"。 */\nexport function deriveExampleSceneId(payload: unknown): string {\n const root = (payload ?? {}) as { objs?: Array<{ sceneId?: unknown }> } | null;\n const id = root?.objs?.map((o) => o.sceneId).find((s): s is string => typeof s === \"string\" && s.length > 0);\n return id ?? \"local\";\n}\n\n/** 本地测试模式下的场景列表(单条)。 */\nexport async function exampleSceneSummary(exampleFile?: string): Promise<SceneSummary> {\n return { id: deriveExampleSceneId(await loadExampleScene(exampleFile)), name: MOCK_SCENE_NAME };\n}\n\nexport async function listScenes(\n client: EasyTwinClient,\n options: { exampleFile?: string; cwd?: string } = {}\n): Promise<SceneSummary[]> {\n const scenes = client.mock\n ? [await exampleSceneSummary(options.exampleFile)]\n : normalizeSceneList(await client.request(ENDPOINTS.linkedScenes(client.appId), { method: \"GET\" }));\n if (options.cwd) await writeConfigScenes(options.cwd, toConfigScenes(scenes));\n return scenes;\n}\n\nexport async function pullScene(\n client: EasyTwinClient,\n id: string,\n options: { exampleFile?: string } = {}\n): Promise<SceneDetail> {\n if (client.mock) {\n const payload = await loadExampleScene(options.exampleFile);\n const sceneId = deriveExampleSceneId(payload);\n if (sceneId !== id) {\n throw new Error(`本地测试模式:示例场景 id 为 ${sceneId},收到 ${id}(本地仅提供 ${EXAMPLE_SCENE_FILE} 这一个场景)`);\n }\n return { id: sceneId, name: MOCK_SCENE_NAME, payload };\n }\n const data = await client.request(ENDPOINTS.linkedScenes(client.appId), { method: \"GET\" });\n const scenes = normalizeLinkedScenes(data);\n const hit = scenes.find((s) => s.sceneKey === id || s.id === id);\n if (!hit) {\n const available = scenes.map((s) => s.sceneKey).filter((k) => k.length > 0);\n throw new Error(\n available.length > 0 ? `未找到场景 ${id}(可用 Scene Key:${available.join(\", \")})` : `未找到场景 ${id}`\n );\n }\n const payload = await fetchSnapshotJson(client.ossUrl, hit.snapshotUrl);\n return { id: hit.sceneKey, name: hit.name, payload };\n}\n\nexport async function saveSceneJson(scene: SceneDetail, out: string): Promise<string> {\n await fs.mkdir(path.dirname(out), { recursive: true });\n await fs.writeFile(out, JSON.stringify(scene.payload ?? scene, null, 2) + \"\\n\", \"utf8\");\n return out;\n}\n/** 场景对象树节点:由场景 JSON 的 objs/hierarchy 按 parentObjId 组装(侧边栏场景结构树等复用)。 */\nexport interface SceneTreeNode {\n id: string;\n name: string;\n type?: string;\n children: SceneTreeNode[];\n}\n\n/**\n * 解析场景对象层级树:优先读 `objs`(含 type),缺失或为空时回退 `hierarchy`。\n * - `parentObjId` 为空 / 指向不存在的 id / 自引用时,该节点视为根;\n * - 节点顺序保持场景数组顺序;非法输入或无可解析结构时返回空数组。\n * scene 可为已解析对象或 JSON 字符串。\n */\nexport function parseSceneStructure(scene: unknown): SceneTreeNode[] {\n let data: unknown = scene;\n if (typeof data === \"string\") {\n try {\n data = JSON.parse(data);\n } catch {\n return [];\n }\n }\n const root = (data ?? {}) as {\n objs?: Array<Record<string, unknown>>;\n hierarchy?: Array<Record<string, unknown>>;\n };\n const objs = Array.isArray(root.objs) ? root.objs : [];\n const hierarchy = Array.isArray(root.hierarchy) ? root.hierarchy : [];\n const items = objs.length > 0 ? objs : hierarchy;\n\n const typeById = new Map<string, string>();\n for (const o of objs) {\n if (typeof o.id === \"string\" && typeof o.type === \"string\") typeById.set(o.id, o.type);\n }\n\n const nodes = new Map<string, SceneTreeNode>();\n const order: string[] = [];\n for (const item of items) {\n const id = typeof item.id === \"string\" ? item.id : \"\";\n if (id.length === 0 || nodes.has(id)) continue;\n const name = typeof item.name === \"string\" && item.name.length > 0 ? item.name : id;\n nodes.set(id, { id, name, type: typeById.get(id), children: [] });\n order.push(id);\n }\n\n const childrenOf = new Map<string, string[]>();\n for (const item of items) {\n const id = typeof item.id === \"string\" ? item.id : \"\";\n if (id.length === 0 || !nodes.has(id)) continue;\n const parentId = typeof item.parentObjId === \"string\" && item.parentObjId.length > 0 ? item.parentObjId : \"\";\n if (parentId.length === 0 || parentId === id || !nodes.has(parentId)) continue;\n const kids = childrenOf.get(parentId) ?? [];\n kids.push(id);\n childrenOf.set(parentId, kids);\n }\n\n const isChild = new Set<string>();\n for (const kids of childrenOf.values()) for (const k of kids) isChild.add(k);\n\n const build = (id: string, seen: Set<string>): SceneTreeNode => {\n const node = nodes.get(id)!;\n const children: SceneTreeNode[] = [];\n if (!seen.has(id)) {\n seen.add(id);\n for (const kid of childrenOf.get(id) ?? []) children.push(build(kid, seen));\n seen.delete(id);\n }\n return { ...node, children };\n };\n\n return order.filter((id) => !isChild.has(id)).map((id) => build(id, new Set()));\n}\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { ENDPOINTS, type EasyTwinClient } from \"./client\";\n\nexport interface UploadProgress {\n phase: \"collect\" | \"upload\";\n /** collect 阶段为已统计字节;upload 阶段为已发送字节。 */\n current: number;\n total: number;\n /** upload 阶段当前文件相对路径。 */\n file?: string;\n}\n\nexport interface UploadOptions {\n onProgress?: (progress: UploadProgress) => void;\n /** 自定义忽略规则,默认只跳过 .git。 */\n ignore?: (relPath: string) => boolean;\n}\n\nexport interface UploadResult {\n fileCount: number;\n byteCount: number;\n /** 本地测试模式(dry-run)时置 true:未真正上传。 */\n mock?: boolean;\n}\n\nconst DEFAULT_IGNORED_DIRS = new Set([\".git\"]);\n\nexport interface CollectedFile {\n relPath: string;\n absPath: string;\n size: number;\n}\n\n/** swagger `SdkApplicationWorkspaceCodeConfigVo`。 */\nexport interface WorkspaceCodeConfig {\n allowedFileExtensions: string[];\n maxCodeFiles: number;\n maxCodeDirectoryDepth: number;\n}\n\n/** swagger `SdkApplicationWorkspaceCodeFileVo`。 */\nexport interface WorkspaceCodeFile {\n id: string;\n filePath: string;\n content: string;\n}\n\n/** 递归收集目录下全部文件(默认跳过 .git),按相对路径升序排列,保证顺序稳定。 */\nexport async function collectFiles(dir: string, ignore: (relPath: string) => boolean = () => false): Promise<CollectedFile[]> {\n const files: CollectedFile[] = [];\n async function walk(current: string, rel: string): Promise<void> {\n const entries = await fs.readdir(current, { withFileTypes: true });\n for (const entry of entries) {\n const relPath = path.posix.join(rel, entry.name);\n if (ignore(relPath)) continue;\n if (entry.isDirectory()) {\n if (DEFAULT_IGNORED_DIRS.has(entry.name)) continue;\n await walk(path.join(current, entry.name), relPath);\n } else if (entry.isFile()) {\n const absPath = path.join(current, entry.name);\n const stat = await fs.stat(absPath);\n files.push({ relPath, absPath, size: stat.size });\n }\n }\n }\n await walk(dir, \"\");\n files.sort((a, b) => a.relPath.localeCompare(b.relPath));\n return files;\n}\n\nexport function buildMultipartBody(\n boundary: string,\n fields: Record<string, string>,\n file: { name: string; content: Buffer }\n): Buffer {\n const parts: Buffer[] = [];\n for (const [key, value] of Object.entries(fields)) {\n parts.push(\n Buffer.from(`--${boundary}\\r\\nContent-Disposition: form-data; name=\"${key}\"\\r\\n\\r\\n${value}\\r\\n`, \"utf8\")\n );\n }\n parts.push(\n Buffer.from(\n `--${boundary}\\r\\nContent-Disposition: form-data; name=\"file\"; filename=\"${file.name}\"\\r\\nContent-Type: application/octet-stream\\r\\n\\r\\n`,\n \"utf8\"\n )\n );\n parts.push(file.content);\n parts.push(Buffer.from(`\\r\\n--${boundary}--\\r\\n`, \"utf8\"));\n return Buffer.concat(parts);\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction asString(value: unknown): string {\n return typeof value === \"string\" ? value : \"\";\n}\n\nfunction asNumber(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : NaN;\n}\n\nexport function normalizePath(relPath: string): string {\n return relPath.replace(/\\\\/g, \"/\").replace(/^\\.\\//, \"\");\n}\n\nexport function normalizeWorkspaceConfig(data: unknown): WorkspaceCodeConfig {\n const it = asRecord(data);\n if (!Array.isArray(it.allowedFileExtensions)) throw new Error(\"workspace-config 响应结构无法识别\");\n const maxCodeFiles = asNumber(it.maxCodeFiles);\n const maxCodeDirectoryDepth = asNumber(it.maxCodeDirectoryDepth);\n if (!Number.isFinite(maxCodeFiles) || !Number.isFinite(maxCodeDirectoryDepth)) {\n throw new Error(\"workspace-config 响应结构无法识别\");\n }\n return {\n allowedFileExtensions: it.allowedFileExtensions.filter((e): e is string => typeof e === \"string\"),\n maxCodeFiles,\n maxCodeDirectoryDepth,\n };\n}\n\nexport function normalizeWorkspaceFiles(data: unknown): WorkspaceCodeFile[] {\n if (!Array.isArray(data)) throw new Error(\"workspace code 响应结构无法识别\");\n return data.map((item) => {\n const it = asRecord(item);\n return { id: asString(it.id), filePath: asString(it.filePath), content: asString(it.content) };\n });\n}\n\nfunction extensionOf(relPath: string): string {\n const base = relPath.split(\"/\").pop() ?? \"\";\n const i = base.lastIndexOf(\".\");\n if (i <= 0) return \"\";\n return base.slice(i).toLowerCase();\n}\n\nfunction allowedExtensionSet(list: string[]): Set<string> {\n return new Set(list.map((e) => (e.startsWith(\".\") ? e.toLowerCase() : `.${e.toLowerCase()}`)));\n}\n\n/** 目录深度:根文件为 0,`src/a.ts` 为 1,`src/utils/a.ts` 为 2。 */\nexport function directoryDepth(relPath: string): number {\n const parts = normalizePath(relPath).split(\"/\").filter((p) => p.length > 0);\n return Math.max(0, parts.length - 1);\n}\n\nexport function assertUploadable(files: CollectedFile[], config: WorkspaceCodeConfig): void {\n const errors: string[] = [];\n if (files.length > config.maxCodeFiles) {\n errors.push(`文件数 ${files.length} 超过上限 ${config.maxCodeFiles}`);\n }\n const tooDeep = files.filter((f) => directoryDepth(f.relPath) > config.maxCodeDirectoryDepth);\n if (tooDeep.length > 0) {\n errors.push(\n `目录深度超过上限 ${config.maxCodeDirectoryDepth}:${tooDeep.map((f) => f.relPath).join(\", \")}`\n );\n }\n if (config.allowedFileExtensions.length > 0) {\n const allowed = allowedExtensionSet(config.allowedFileExtensions);\n const bad = files.filter((f) => !allowed.has(extensionOf(f.relPath)));\n if (bad.length > 0) {\n errors.push(\n `扩展名不在允许列表(${config.allowedFileExtensions.join(\", \")}):${bad.map((f) => f.relPath).join(\", \")}`\n );\n }\n }\n if (errors.length > 0) throw new Error(`无法上传:${errors.join(\"; \")}`);\n}\n\n/** 本地测试模式(dry-run):只收集与统计,不发网络请求。 */\nasync function mockUpload(dir: string, options: UploadOptions): Promise<UploadResult> {\n const ignore = options.ignore ?? (() => false);\n const files = await collectFiles(dir, ignore);\n const total = files.reduce((sum, f) => sum + f.size, 0);\n options.onProgress?.({ phase: \"collect\", current: total, total });\n options.onProgress?.({ phase: \"upload\", current: total, total });\n return { fileCount: files.length, byteCount: total, mock: true };\n}\n\n/**\n * 全量覆盖上传目录:对照工作区代码文件(GET/POST/PATCH/DELETE)使远端与本地一致。\n * 本地测试模式(mock)时退化为 dry-run。\n */\nexport async function uploadDirectory(client: EasyTwinClient, dir: string, options: UploadOptions = {}): Promise<UploadResult> {\n if (client.mock) return mockUpload(dir, options);\n const ignore = options.ignore ?? (() => false);\n const files = await collectFiles(dir, ignore);\n const total = files.reduce((sum, f) => sum + f.size, 0);\n options.onProgress?.({ phase: \"collect\", current: total, total });\n\n const appId = client.appId;\n const wsConfig = normalizeWorkspaceConfig(await client.request(ENDPOINTS.workspaceConfig(appId), { method: \"GET\" }));\n assertUploadable(files, wsConfig);\n\n const remote = normalizeWorkspaceFiles(await client.request(ENDPOINTS.workspaceCode(appId), { method: \"GET\" }));\n const remoteByPath = new Map(remote.map((f) => [normalizePath(f.filePath), f]));\n const localPaths = new Set(files.map((f) => normalizePath(f.relPath)));\n\n const toDelete = remote.filter((f) => !localPaths.has(normalizePath(f.filePath))).map((f) => f.id);\n if (toDelete.length > 0) {\n await client.request(ENDPOINTS.workspaceCodeFiles(appId), {\n method: \"DELETE\",\n body: JSON.stringify({ ids: toDelete }),\n });\n }\n\n const creates: { file: CollectedFile; content: string }[] = [];\n const patches: { file: CollectedFile; id: string; content: string }[] = [];\n const unchanged: CollectedFile[] = [];\n for (const file of files) {\n const content = await fs.readFile(file.absPath, \"utf8\");\n const remoteFile = remoteByPath.get(normalizePath(file.relPath));\n if (!remoteFile) creates.push({ file, content });\n else if (remoteFile.content !== content) patches.push({ file, id: remoteFile.id, content });\n else unchanged.push(file);\n }\n\n let sent = 0;\n const bump = (file: CollectedFile): void => {\n sent += file.size;\n options.onProgress?.({ phase: \"upload\", current: sent, total, file: file.relPath });\n };\n\n if (patches.length > 0) {\n await client.request(ENDPOINTS.workspaceCodeFiles(appId), {\n method: \"PATCH\",\n body: JSON.stringify({ files: patches.map((p) => ({ id: p.id, content: p.content })) }),\n });\n for (const p of patches) bump(p.file);\n }\n for (const c of creates) {\n await client.request(ENDPOINTS.workspaceCodeFiles(appId), {\n method: \"POST\",\n body: JSON.stringify({ filePath: normalizePath(c.file.relPath), content: c.content }),\n });\n bump(c.file);\n }\n for (const u of unchanged) bump(u);\n if (files.length === 0) options.onProgress?.({ phase: \"upload\", current: 0, total: 0 });\n\n return { fileCount: files.length, byteCount: total };\n}\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { resolveWorkspaceAssetPath } from \"./assetsPath\";\nimport { ENDPOINTS, type EasyTwinClient } from \"./client\";\nimport {\n collectFiles,\n normalizePath,\n normalizeWorkspaceConfig,\n normalizeWorkspaceFiles,\n type WorkspaceCodeFile,\n} from \"./upload\";\n\nexport const DEFAULT_ENTRY_PATH = \"src/main.ts\";\n\n/** 与 easytwin-render 可上传子集示例对齐的默认 TwinApp 子类入口。 */\nexport const DEFAULT_MAIN_TS = `import { TwinApp, type TwinAppContext } from \"@easytwin/apps\";\n\nexport default class App extends TwinApp {\n async init(ctx: TwinAppContext) {\n // engine / container 已有;scene / camera 为 null\n void ctx;\n }\n\n async onSceneLoaded(ctx: TwinAppContext) {\n // 场景字段有值;在此加物体 / 绑事件,并用 ctx.sceneCleanup 对称拆除\n void ctx;\n }\n\n onUpdate(ctx: TwinAppContext, delta: number, elapsed: number) {\n void ctx;\n void delta;\n void elapsed;\n }\n\n onDispose(ctx: TwinAppContext) {\n void ctx;\n }\n}\n`;\n\nconst PULL_IGNORED_DIRS = new Set([\n \".git\",\n \"node_modules\",\n \"dist\",\n \".easytwin\",\n \".cursor\",\n \".claude\",\n \".qoder\",\n \".vscode\",\n]);\nconst PULL_IGNORED_FILES = new Set([\"easytwin.config.json\"]);\nconst DEFAULT_PULL_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".json\", \".css\", \".html\", \".md\"];\n\nexport type WorkspaceChangeKind = \"identical\" | \"remote-only\" | \"local-only\" | \"modified\" | \"seed\";\n\nexport interface WorkspaceFileChange {\n path: string;\n kind: WorkspaceChangeKind;\n localContent?: string;\n remoteContent?: string;\n}\n\nexport interface WorkspacePullPlan {\n remoteEmpty: boolean;\n seededDefaults: boolean;\n mock?: boolean;\n skippedRemotePaths: string[];\n changes: WorkspaceFileChange[];\n}\n\nexport interface WorkspacePullOptions {\n /** 用远端内容覆盖内容冲突的本地文件;仅本地文件仍不删除。 */\n force?: boolean;\n /** 只算计划,不写盘。 */\n dryRun?: boolean;\n ignore?: (relPath: string) => boolean;\n}\n\nexport interface WorkspacePullResult {\n plan: WorkspacePullPlan;\n written: string[];\n skippedConflicts: string[];\n dryRun?: boolean;\n mock?: boolean;\n}\n\nexport function defaultPullIgnore(relPath: string): boolean {\n const parts = normalizePath(relPath).split(\"/\").filter((p) => p.length > 0);\n if (parts.some((p) => PULL_IGNORED_DIRS.has(p))) return true;\n const base = parts[parts.length - 1];\n return base !== undefined && PULL_IGNORED_FILES.has(base);\n}\n\n/** 拒绝逃逸、空路径与凭据文件,避免远端路径写到工作区外。 */\nexport function isSafeRelPath(relPath: string): boolean {\n const n = normalizePath(relPath);\n if (!n) return false;\n if (n.toLowerCase() === \"easytwin.config.json\") return false;\n if (path.isAbsolute(n) || path.win32.isAbsolute(n.replace(/\\//g, \"\\\\\"))) return false;\n const parts = n.split(\"/\");\n if (parts.some((p) => p === \"..\" || p === \".\" || p === \"\")) return false;\n return true;\n}\n\nfunction extensionOf(relPath: string): string {\n const base = relPath.split(\"/\").pop() ?? \"\";\n const i = base.lastIndexOf(\".\");\n if (i <= 0) return \"\";\n return base.slice(i).toLowerCase();\n}\n\nfunction allowedExtensionSet(list: string[]): Set<string> {\n return new Set(list.map((e) => (e.startsWith(\".\") ? e.toLowerCase() : `.${e.toLowerCase()}`)));\n}\n\nfunction normalizeEol(text: string): string {\n return text.replace(/\\r\\n/g, \"\\n\");\n}\n\nfunction combineIgnore(extra?: (relPath: string) => boolean): (relPath: string) => boolean {\n return (relPath) => defaultPullIgnore(relPath) || (extra?.(relPath) ?? false);\n}\n\nasync function readLocalText(absPath: string): Promise<string | undefined> {\n try {\n return await fs.readFile(absPath, \"utf8\");\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") return undefined;\n throw err;\n }\n}\n\nasync function loadAllowedExtensions(client: EasyTwinClient): Promise<string[]> {\n if (client.mock) return DEFAULT_PULL_EXTENSIONS;\n try {\n const cfg = normalizeWorkspaceConfig(\n await client.request(ENDPOINTS.workspaceConfig(client.appId), { method: \"GET\" })\n );\n return cfg.allowedFileExtensions.length > 0 ? cfg.allowedFileExtensions : DEFAULT_PULL_EXTENSIONS;\n } catch {\n return DEFAULT_PULL_EXTENSIONS;\n }\n}\n\nasync function fetchRemoteFiles(client: EasyTwinClient): Promise<WorkspaceCodeFile[]> {\n if (client.mock) return [];\n return normalizeWorkspaceFiles(await client.request(ENDPOINTS.workspaceCode(client.appId), { method: \"GET\" }));\n}\n\n/**\n * 对照远端工作区代码与本地目录,算出 diff 计划。\n * mock 或远端无有效文件时,本地缺省入口视为 seed。\n */\nexport async function planWorkspacePull(\n client: EasyTwinClient,\n dir: string,\n options: Pick<WorkspacePullOptions, \"ignore\"> = {}\n): Promise<WorkspacePullPlan> {\n const ignore = combineIgnore(options.ignore);\n const allowed = allowedExtensionSet(await loadAllowedExtensions(client));\n const remoteRaw = await fetchRemoteFiles(client);\n const skippedRemotePaths: string[] = [];\n const remoteByPath = new Map<string, string>();\n for (const file of remoteRaw) {\n const rel = normalizePath(file.filePath);\n if (!isSafeRelPath(rel) || ignore(rel)) {\n skippedRemotePaths.push(rel || file.filePath);\n continue;\n }\n remoteByPath.set(rel, file.content);\n }\n\n let localFiles: { relPath: string; absPath: string }[] = [];\n try {\n localFiles = await collectFiles(dir, ignore);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code !== \"ENOENT\") throw err;\n }\n\n const localByPath = new Map<string, string>();\n for (const file of localFiles) {\n const rel = normalizePath(file.relPath);\n if (!allowed.has(extensionOf(rel))) continue;\n const content = await readLocalText(file.absPath);\n if (content !== undefined) localByPath.set(rel, content);\n }\n\n const changes: WorkspaceFileChange[] = [];\n const seen = new Set<string>();\n\n for (const [rel, remoteContent] of remoteByPath) {\n seen.add(rel);\n const localContent = localByPath.get(rel);\n if (localContent === undefined) {\n changes.push({ path: rel, kind: \"remote-only\", remoteContent });\n } else if (normalizeEol(localContent) === normalizeEol(remoteContent)) {\n changes.push({ path: rel, kind: \"identical\", localContent, remoteContent });\n } else {\n changes.push({ path: rel, kind: \"modified\", localContent, remoteContent });\n }\n }\n\n for (const [rel, localContent] of localByPath) {\n if (seen.has(rel)) continue;\n changes.push({ path: rel, kind: \"local-only\", localContent });\n }\n\n const remoteEmpty = remoteByPath.size === 0;\n let seededDefaults = false;\n if (remoteEmpty) {\n const localMain = localByPath.get(DEFAULT_ENTRY_PATH);\n if (localMain === undefined) {\n changes.push({ path: DEFAULT_ENTRY_PATH, kind: \"seed\", remoteContent: DEFAULT_MAIN_TS });\n seededDefaults = true;\n }\n }\n\n changes.sort((a, b) => a.path.localeCompare(b.path));\n return {\n remoteEmpty,\n seededDefaults,\n mock: client.mock || undefined,\n skippedRemotePaths,\n changes,\n };\n}\n\nexport interface WorkspacePullApplyResult {\n written: string[];\n skippedConflicts: string[];\n}\n\n/** 按计划写盘:seed 与 remote-only 始终写入;modified 仅 force 时覆盖;不删 local-only。 */\nexport async function applyWorkspacePull(\n dir: string,\n plan: WorkspacePullPlan,\n options: { force?: boolean } = {}\n): Promise<WorkspacePullApplyResult> {\n const written: string[] = [];\n const skippedConflicts: string[] = [];\n for (const change of plan.changes) {\n if (change.kind === \"identical\" || change.kind === \"local-only\") continue;\n if (change.kind === \"modified\" && !options.force) {\n skippedConflicts.push(change.path);\n continue;\n }\n const content = change.remoteContent ?? \"\";\n const abs = resolveWorkspaceAssetPath(dir, change.path);\n await fs.mkdir(path.dirname(abs), { recursive: true });\n await fs.writeFile(abs, content, \"utf8\");\n written.push(change.path);\n }\n return { written, skippedConflicts };\n}\n\nexport async function pullWorkspace(\n client: EasyTwinClient,\n dir: string,\n options: WorkspacePullOptions = {}\n): Promise<WorkspacePullResult> {\n const plan = await planWorkspacePull(client, dir, { ignore: options.ignore });\n if (options.dryRun) {\n const skippedConflicts = plan.changes.filter((c) => c.kind === \"modified\" && !options.force).map((c) => c.path);\n return { plan, written: [], skippedConflicts, dryRun: true, mock: plan.mock };\n }\n const applied = await applyWorkspacePull(dir, plan, { force: options.force });\n return { plan, ...applied, mock: plan.mock };\n}\n\nconst KIND_LABEL: Record<WorkspaceChangeKind, string> = {\n identical: \"same \",\n \"remote-only\": \"create\",\n \"local-only\": \"keep \",\n modified: \"modify\",\n seed: \"seed \",\n};\n\nexport function formatWorkspacePullPlan(plan: WorkspacePullPlan): string {\n const lines: string[] = [];\n if (plan.mock) lines.push(\"[本地测试模式] 按远端为空处理\");\n const remoteCount = plan.changes.filter((c) => c.kind !== \"local-only\" && c.kind !== \"seed\").length;\n if (plan.remoteEmpty) {\n lines.push(\n plan.seededDefaults\n ? `远端 0 个文件,将写入默认 ${DEFAULT_ENTRY_PATH}`\n : \"远端 0 个文件,本地已有入口,未改动默认模板\"\n );\n } else {\n lines.push(`远端 ${remoteCount} 个文件`);\n }\n for (const change of plan.changes) {\n let extra = \"\";\n if (change.kind === \"modified\") extra = \" (冲突,默认不覆盖)\";\n if (change.kind === \"local-only\") extra = \" (仅本地)\";\n if (change.kind === \"seed\") extra = \" (默认 TwinApp)\";\n lines.push(` ${KIND_LABEL[change.kind]} ${change.path}${extra}`);\n }\n if (plan.skippedRemotePaths.length > 0) {\n lines.push(`跳过非法/凭据路径: ${plan.skippedRemotePaths.join(\", \")}`);\n }\n return lines.join(\"\\n\");\n}\n\nexport function formatWorkspacePullResult(result: WorkspacePullResult): string {\n const lines = [formatWorkspacePullPlan(result.plan)];\n if (result.dryRun) {\n lines.push(\"dry-run:未写盘\");\n if (result.skippedConflicts.length > 0) {\n lines.push(`${result.skippedConflicts.length} 个冲突未覆盖(加 --force)`);\n }\n return lines.join(\"\\n\");\n }\n if (result.written.length > 0) {\n lines.push(`已写入 ${result.written.length} 个文件: ${result.written.join(\", \")}`);\n } else {\n lines.push(\"未写入文件\");\n }\n if (result.skippedConflicts.length > 0) {\n lines.push(`${result.skippedConflicts.length} 个冲突未覆盖(加 --force): ${result.skippedConflicts.join(\", \")}`);\n }\n return lines.join(\"\\n\");\n}\n\nexport function workspacePullHasConflicts(plan: WorkspacePullPlan): boolean {\n return plan.changes.some((c) => c.kind === \"modified\");\n}\n\nexport function workspacePullPendingWrites(plan: WorkspacePullPlan, force = false): string[] {\n return plan.changes\n .filter((c) => c.kind === \"seed\" || c.kind === \"remote-only\" || (force && c.kind === \"modified\"))\n .map((c) => c.path);\n}\n","import path from \"node:path\";\n\n/**\n * 把 ctx.assets 的相对路径落到工作区磁盘。规范化后必须仍在 cwd 内。\n */\nexport function resolveWorkspaceAssetPath(cwd: string, relPath: string): string {\n const root = path.resolve(cwd);\n const input = relPath.trim();\n if (!input) throw new Error(\"assets 路径为空\");\n if (path.isAbsolute(input)) throw new Error(`assets 只接受工作区相对路径,拒绝绝对路径: ${relPath}`);\n const resolved = path.resolve(root, input);\n const rel = path.relative(root, resolved);\n if (rel.startsWith(\"..\") || path.isAbsolute(rel)) {\n throw new Error(`assets 路径逃逸工作区: ${relPath}`);\n }\n return resolved;\n}\n","import { existsSync, promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport type SyncTarget = \"cursor\" | \"claude\" | \"codex\" | \"qoder\";\nexport type SyncTargetArg = SyncTarget | \"all\";\n\n/** 六件套清单(5.1),顺序即输出顺序。 */\nexport const SKILL_NAMES = [\n \"easytwin-render\",\n \"easytwin-core\",\n \"easytwin-develop\",\n \"easytwin-bootstrap\",\n \"easytwin-scene\",\n \"easytwin-upload\",\n] as const;\n\nexport type SyncAction = \"created\" | \"updated\" | \"unchanged\";\n\nexport interface SyncEntrySummary {\n name: string;\n action: SyncAction;\n}\n\nexport interface SyncSummary {\n target: SyncTarget;\n entries: SyncEntrySummary[];\n codex?: SyncEntrySummary;\n}\n\nexport interface SyncOptions {\n cwd: string;\n targets?: SyncTargetArg | SyncTarget[];\n version?: string;\n /** skills 源目录;缺省按 devkit 包内 skills/ 解析(CLI)。插件 bundle 场景显式传入插件内目录。 */\n sourceDir?: string;\n /** runtime index.d.ts 源文件;缺省按包内 src/lib 或 dist/runtime-types 解析。插件必须显式传入。 */\n typesSourceFile?: string;\n}\n\nexport const CODEX_MARKER_BEGIN = \"<!-- EASYTWIN-SKILLS:BEGIN -->\";\nexport const CODEX_MARKER_END = \"<!-- EASYTWIN-SKILLS:END -->\";\nexport const META_FILE_NAME = \".easytwin-meta.json\";\n\n/** 用户项目内 runtime 类型落地目录(posix)。 */\nexport const EASYTWIN_TYPES_DIR = \".easytwin/types\";\n\nexport const MINIMAL_TSCONFIG = `${JSON.stringify(\n {\n compilerOptions: {\n target: \"ES2022\",\n module: \"ESNext\",\n moduleResolution: \"bundler\",\n strict: true,\n skipLibCheck: true,\n noEmit: true,\n paths: {\n \"@easytwin/runtime\": [\".easytwin/types\"],\n \"@easytwin/apps\": [\".easytwin/types/apps\"]\n },\n },\n include: [\"src/**/*.ts\"],\n },\n null,\n 2\n)}\\n`;\n\nexport const TSCONFIG_PATHS_HINT = `已有 tsconfig.json,未改动。请在 compilerOptions 中加入:\n \"skipLibCheck\": true,\n \"paths\": {\n \"@easytwin/runtime\": [\".easytwin/types\"],\n \"@easytwin/apps\": [\".easytwin/types/apps\"]\n }`;\n\nexport const APPS_TYPES_FILE = \"apps.d.ts\";\n\nexport const APPS_DTS = `import type { RuntimeEngine, RuntimeScene, SceneManager } from \"@easytwin/runtime\";\n\nexport type TwinAppContext = {\n app: {\n id: string;\n mode: \"preview\" | \"publish\";\n };\n engine: RuntimeEngine;\n container: HTMLElement;\n runtimeScene: RuntimeScene | null;\n scene: RuntimeScene[\"sceneObject\"] | null;\n camera: RuntimeScene[\"camera\"][\"main\"] | null;\n sceneManager: {\n currentSceneId: string;\n runtime: SceneManager | null;\n loadScene(sceneId: string): Promise<void>;\n };\n logger: {\n log(...args: unknown[]): void;\n info(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n error(...args: unknown[]): void;\n };\n assets: {\n text(path: string): Promise<string>;\n json<T = unknown>(path: string): Promise<T>;\n };\n cleanup(fn: () => void | Promise<void>): void;\n sceneCleanup(fn: () => void | Promise<void>): void;\n};\n\nexport declare abstract class TwinApp {\n init?(ctx: TwinAppContext): void | Promise<void>;\n onUpdate?(ctx: TwinAppContext, delta: number, elapsed: number): void;\n onBeforeSceneUnload?(ctx: TwinAppContext): void | Promise<void>;\n onSceneLoaded?(ctx: TwinAppContext): void | Promise<void>;\n onDispose?(ctx: TwinAppContext): void | Promise<void>;\n onError?(ctx: TwinAppContext, error: unknown): boolean | void;\n}\n\nexport declare function defineApp<T>(app: T): T;\n`;\n\nexport function buildRuntimeTypesContent(sourceDts: string): string {\n return `${sourceDts.replace(/\\s+$/, \"\")}\\n`;\n}\n\nexport function normalizeTargets(target: SyncTargetArg | SyncTarget[] = \"all\"): SyncTarget[] {\n if (target === \"all\") return [\"cursor\", \"claude\", \"codex\", \"qoder\"];\n if (Array.isArray(target)) return [...new Set(target)];\n return [target];\n}\n\n/** skills 源目录默认解析:CLI 下为 devkit 包内 skills/。插件 bundle 到 CJS 后 import.meta.url 为空,\n * 必须通过 SyncOptions.sourceDir / detectSkillsStatus 的 sourceDir 显式传入(见 esbuild.config.mjs 注释)。 */\nexport function resolveSkillsSourceDir(): string {\n if (typeof import.meta.url !== \"string\" || import.meta.url.length === 0) {\n throw new Error(\"无法定位 skills 源目录:插件(bundle/CJS)场景必须显式传入 sourceDir\");\n }\n const here = path.dirname(fileURLToPath(import.meta.url));\n return path.resolve(here, \"..\", \"skills\");\n}\n\n/** runtime 类型声明源:开发态 src/lib/index.d.ts,发布态 dist/runtime-types/index.d.ts。 */\nexport function resolveRuntimeTypesSourceFile(): string {\n if (typeof import.meta.url !== \"string\" || import.meta.url.length === 0) {\n throw new Error(\"无法定位 runtime 类型:插件(bundle/CJS)场景必须显式传入 typesSourceFile\");\n }\n const here = path.dirname(fileURLToPath(import.meta.url));\n const fromDist = path.join(here, \"runtime-types\", \"index.d.ts\");\n const fromSrc = path.resolve(here, \"lib\", \"index.d.ts\");\n if (existsSync(fromDist)) return fromDist;\n if (existsSync(fromSrc)) return fromSrc;\n throw new Error(`无法定位 runtime 类型声明,已尝试:${fromDist}, ${fromSrc}`);\n}\n\nasync function readJson<T>(file: string): Promise<T> {\n return JSON.parse(await fs.readFile(file, \"utf8\")) as T;\n}\n\nexport async function readDevkitVersion(skillsDir = resolveSkillsSourceDir()): Promise<string> {\n const marker = path.join(skillsDir, \".easytwin-source.json\");\n try {\n const meta = await readJson<{ version: string }>(marker);\n if (typeof meta.version === \"string\") return meta.version;\n } catch {\n // 无构建期标记,退回读包内 package.json\n }\n try {\n const pkg = await readJson<{ version: string }>(path.resolve(skillsDir, \"..\", \"package.json\"));\n return pkg.version;\n } catch {\n return \"0.0.0\";\n }\n}\n\nasync function copyDir(src: string, dest: string): Promise<void> {\n await fs.mkdir(dest, { recursive: true });\n const entries = await fs.readdir(src, { withFileTypes: true });\n for (const entry of entries) {\n const s = path.join(src, entry.name);\n const d = path.join(dest, entry.name);\n if (entry.isDirectory()) await copyDir(s, d);\n else if (entry.isFile()) await fs.copyFile(s, d);\n }\n}\n\n/** 比较源目录的每个文件与目标是否逐字节一致(忽略目标里额外的文件,如版本标记)。 */\nasync function dirMatches(src: string, dest: string): Promise<boolean> {\n let sourceEntries: string[];\n try {\n sourceEntries = await fs.readdir(src);\n } catch {\n return false;\n }\n for (const name of sourceEntries) {\n const s = path.join(src, name);\n const d = path.join(dest, name);\n const sStat = await fs.stat(s);\n if (sStat.isDirectory()) {\n if (!(await dirMatches(s, d))) return false;\n } else {\n let dStat;\n try {\n dStat = await fs.stat(d);\n } catch {\n return false;\n }\n if (!sStat.isFile() || !dStat.isFile() || sStat.size !== dStat.size) return false;\n if (!(await fs.readFile(s)).equals(await fs.readFile(d))) return false;\n }\n }\n return true;\n}\n\nfunction actionFor(exists: boolean, matches: boolean): SyncAction {\n if (!exists) return \"created\";\n return matches ? \"unchanged\" : \"updated\";\n}\n\nasync function writeMeta(destDir: string, version: string): Promise<void> {\n const meta = { name: \"@easytwin/devkit\", version };\n await fs.writeFile(path.join(destDir, META_FILE_NAME), JSON.stringify(meta, null, 2) + \"\\n\", \"utf8\");\n}\n\n/** cursor / claude / qoder:复制技能目录到用户项目,按内容覆盖,写入版本标记。 */\nasync function syncToDir(target: SyncTarget, sourceRoot: string, targetRoot: string, version: string): Promise<SyncSummary> {\n const entries: SyncEntrySummary[] = [];\n for (const name of SKILL_NAMES) {\n const src = path.join(sourceRoot, name);\n const dest = path.join(targetRoot, name);\n const exists = await fs\n .stat(dest)\n .then(() => true)\n .catch(() => false);\n const matches = await dirMatches(src, dest);\n const action = actionFor(exists, matches);\n if (action !== \"unchanged\") {\n await fs.rm(dest, { recursive: true, force: true });\n await copyDir(src, dest);\n }\n entries.push({ name, action });\n }\n await writeMeta(targetRoot, version);\n return { target, entries };\n}\n\n/** codex:在用户项目 AGENTS.md 注入带标记的引用段(整段替换,幂等)。 */\nfunction buildCodexSegment(version: string): string {\n return [\n CODEX_MARKER_BEGIN,\n \"<!-- 本段由 `easytwin skills sync` 管理,可整段替换;手动修改会被下次同步覆盖。 -->\",\n `EasyTwin 开发技能(由 @easytwin/devkit v${version} 同步):`,\n \"\",\n \"- `easytwin-develop`:工作流总纲,开始 EasyTwin 开发前必读。\",\n \"- `easytwin-bootstrap`:初始化应用级凭证(easytwin.config.json)。\",\n \"- `easytwin-scene`:列出场景、拉取场景 JSON。\",\n \"- `easytwin-render`:用 twin runtime 开发渲染功能(主力)。\",\n \"- `easytwin-core`:引擎内核 API(RuntimeEngine/基类/Time/相机/物理)。\",\n \"- `easytwin-upload`:拉取/上传工作区代码(远端为空写默认入口;上传全量覆盖不可逆)。\",\n \"\",\n \"详细用法见各技能;重新同步运行 `easytwin skills sync --target codex`。\",\n CODEX_MARKER_END,\n ].join(\"\\n\");\n}\n\nasync function syncToCodex(sourceRoot: string, cwd: string, version: string): Promise<SyncSummary> {\n const agentsFile = path.join(cwd, \"AGENTS.md\");\n const segment = buildCodexSegment(version);\n let content = \"\";\n let exists = true;\n try {\n content = await fs.readFile(agentsFile, \"utf8\");\n } catch {\n exists = false;\n }\n const start = content.indexOf(CODEX_MARKER_BEGIN);\n const end = content.indexOf(CODEX_MARKER_END);\n let action: SyncAction;\n let next: string;\n if (start === -1 || end === -1 || end < start) {\n action = exists ? \"updated\" : \"created\";\n next = content.length > 0 && !content.endsWith(\"\\n\") ? content + \"\\n\\n\" : content + (content.length > 0 ? \"\\n\" : \"\");\n next += segment + \"\\n\";\n } else {\n const current = content.slice(start, end + CODEX_MARKER_END.length);\n action = current === segment ? \"unchanged\" : \"updated\";\n next = content.slice(0, start) + segment + content.slice(end + CODEX_MARKER_END.length);\n }\n if (action !== \"unchanged\") {\n await fs.mkdir(cwd, { recursive: true });\n await fs.writeFile(agentsFile, next, \"utf8\");\n }\n return { target: \"codex\", entries: [], codex: { name: \"AGENTS.md\", action } };\n}\n\nexport interface TypesSyncSummary {\n action: SyncAction;\n tsconfig: \"created\" | \"unchanged\" | \"manual-paths\";\n pathsHint?: string;\n}\n\nexport interface SyncSkillsResult {\n summaries: SyncSummary[];\n types: TypesSyncSummary;\n}\n\nasync function syncRuntimeTypes(cwd: string, typesSourceFile: string): Promise<TypesSyncSummary> {\n const destDir = path.join(cwd, \".easytwin\", \"types\");\n const destFile = path.join(destDir, \"index.d.ts\");\n const appsFile = path.join(destDir, APPS_TYPES_FILE);\n const content = buildRuntimeTypesContent(await fs.readFile(typesSourceFile, \"utf8\"));\n let runtimeCurrent = \"\";\n let appsCurrent = \"\";\n let runtimeExists = true;\n let appsExists = true;\n try {\n runtimeCurrent = await fs.readFile(destFile, \"utf8\");\n } catch {\n runtimeExists = false;\n }\n try {\n appsCurrent = await fs.readFile(appsFile, \"utf8\");\n } catch {\n appsExists = false;\n }\n const runtimeAction = actionFor(runtimeExists, runtimeCurrent === content);\n const appsAction = actionFor(appsExists, appsCurrent === APPS_DTS);\n const action: SyncAction =\n runtimeAction === \"unchanged\" && appsAction === \"unchanged\"\n ? \"unchanged\"\n : !runtimeExists && !appsExists\n ? \"created\"\n : \"updated\";\n if (runtimeAction !== \"unchanged\" || appsAction !== \"unchanged\") {\n await fs.mkdir(destDir, { recursive: true });\n if (runtimeAction !== \"unchanged\") await fs.writeFile(destFile, content, \"utf8\");\n if (appsAction !== \"unchanged\") await fs.writeFile(appsFile, APPS_DTS, \"utf8\");\n }\n\n const tsconfigPath = path.join(cwd, \"tsconfig.json\");\n let tsconfig: TypesSyncSummary[\"tsconfig\"];\n let pathsHint: string | undefined;\n try {\n const existing = await fs.readFile(tsconfigPath, \"utf8\");\n if (existing === MINIMAL_TSCONFIG) tsconfig = \"unchanged\";\n else {\n tsconfig = \"manual-paths\";\n pathsHint = TSCONFIG_PATHS_HINT;\n }\n } catch {\n await fs.writeFile(tsconfigPath, MINIMAL_TSCONFIG, \"utf8\");\n tsconfig = \"created\";\n }\n return { action, tsconfig, pathsHint };\n}\n\nexport async function syncSkills(options: SyncOptions): Promise<SyncSkillsResult> {\n const targets = normalizeTargets(options.targets ?? \"all\");\n const sourceRoot = options.sourceDir ?? resolveSkillsSourceDir();\n const version = options.version ?? (await readDevkitVersion(sourceRoot));\n const summaries: SyncSummary[] = [];\n for (const target of targets) {\n if (target === \"cursor\") summaries.push(await syncToDir(\"cursor\", sourceRoot, path.join(options.cwd, \".cursor\", \"skills\"), version));\n else if (target === \"claude\") summaries.push(await syncToDir(\"claude\", sourceRoot, path.join(options.cwd, \".claude\", \"skills\"), version));\n else if (target === \"qoder\") summaries.push(await syncToDir(\"qoder\", sourceRoot, path.join(options.cwd, \".qoder\", \"skills\"), version));\n else summaries.push(await syncToCodex(sourceRoot, options.cwd, version));\n }\n const types = await syncRuntimeTypes(options.cwd, options.typesSourceFile ?? resolveRuntimeTypesSourceFile());\n return { summaries, types };\n}\n\nexport interface SkillsTargetStatus {\n target: SyncTarget;\n synced: boolean;\n reason?: string;\n}\n\nexport interface SkillsStatus {\n cwd: string;\n targets: SkillsTargetStatus[];\n typesSynced: boolean;\n}\n\n/** 供插件\"缺失/过期时提示一次\"使用:检测各目标当前同步状态。 */\nexport async function detectSkillsStatus(cwd: string, sourceDir?: string): Promise<SkillsStatus> {\n const sourceRoot = sourceDir ?? resolveSkillsSourceDir();\n const version = await readDevkitVersion(sourceRoot);\n const targets: SkillsTargetStatus[] = [];\n\n const dirTargets = [\"cursor\", \"claude\", \"qoder\"] as const;\n const DIR_ROOTS: Record<(typeof dirTargets)[number], string> = {\n cursor: \".cursor/skills\",\n claude: \".claude/skills\",\n qoder: \".qoder/skills\",\n };\n\n for (const target of dirTargets) {\n const root = path.join(cwd, DIR_ROOTS[target]);\n const missing = [];\n for (const name of SKILL_NAMES) {\n if (!(await fs.stat(path.join(root, name)).then(() => true).catch(() => false))) missing.push(name);\n }\n let stale = false;\n try {\n const meta = await readJson<{ version: string }>(path.join(root, META_FILE_NAME));\n stale = meta.version !== version;\n } catch {\n stale = missing.length === 0; // 目录存在但无版本标记\n }\n targets.push({\n target,\n synced: missing.length === 0 && !stale,\n reason: missing.length > 0 ? `缺少 ${missing.join(\", \")}` : stale ? \"版本过期\" : undefined,\n });\n }\n\n let agentsContent = \"\";\n try {\n agentsContent = await fs.readFile(path.join(cwd, \"AGENTS.md\"), \"utf8\");\n } catch {\n // AGENTS.md 不存在视为未同步\n }\n const hasCodex =\n agentsContent.includes(CODEX_MARKER_BEGIN) && agentsContent.includes(CODEX_MARKER_END) && agentsContent.includes(`v${version}`);\n targets.push({ target: \"codex\", synced: hasCodex, reason: hasCodex ? undefined : \"AGENTS.md 缺少同步标记段\" });\n\n let typesSynced = false;\n try {\n const dts = await fs.readFile(path.join(cwd, \".easytwin\", \"types\", \"index.d.ts\"), \"utf8\");\n const appsDts = await fs.readFile(path.join(cwd, \".easytwin\", \"types\", APPS_TYPES_FILE), \"utf8\");\n typesSynced = dts.includes(\"registerEngineTickListener\") && appsDts.includes(\"export declare abstract class TwinApp\");\n } catch {\n typesSynced = false;\n }\n\n return { cwd, targets, typesSynced };\n}\n","import * as esbuild from \"esbuild-wasm\";\nimport { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { portableRuntimeWarning } from \"./apps\";\n\n/** 用户代码固定入口(相对工作区根)。 */\nexport const USER_ENTRY = \"src/main.ts\";\n/** CLI 缺省输出路径(相对工作区根)。 */\nexport const DEFAULT_BUNDLE_OUT = \"dist/main.js\";\n/** 白名单允许的裸模块。 */\nexport const RUNTIME_MODULE = \"@easytwin/runtime\";\nexport const APPS_MODULE = \"@easytwin/apps\";\nconst ALLOWED_BARE_MODULES = new Set([RUNTIME_MODULE, APPS_MODULE]);\n\nexport class BundleError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"BundleError\";\n }\n}\n\nexport interface BundleUserCodeOptions {\n cwd: string;\n /** 缺省不落盘,只返回产物字符串(插件内存编译);CLI 传入绝对/相对路径。 */\n outFile?: string;\n}\n\nexport interface BundleResult {\n code: string;\n warnings: string[];\n}\n\nfunction isRelativeOrAbsolute(spec: string): boolean {\n return spec.startsWith(\"./\") || spec.startsWith(\"../\") || spec.startsWith(\"/\") || path.isAbsolute(spec);\n}\n\nfunction whitelistPlugin(): esbuild.Plugin {\n return {\n name: \"easytwin-whitelist\",\n setup(build) {\n build.onResolve({ filter: /.*/ }, (args) => {\n if (args.kind === \"entry-point\") return undefined;\n if (isRelativeOrAbsolute(args.path)) return undefined;\n if (ALLOWED_BARE_MODULES.has(args.path)) return { path: args.path, external: true };\n return {\n errors: [\n {\n text: `检测到外部依赖 ${args.path},用户代码只能依赖 @easytwin/runtime 与 @easytwin/apps。不要 npm install,类型由 easytwin skills sync 分发,运行走预览页 Run 或 easytwin bundle。`,\n },\n ],\n };\n });\n },\n };\n}\n\nfunction formatEsbuildMessages(messages: readonly esbuild.Message[]): string {\n return messages\n .map((m) => {\n const loc = m.location ? `${m.location.file}:${m.location.line}:${m.location.column}: ` : \"\";\n return `${loc}${m.text}`;\n })\n .join(\"\\n\");\n}\n\nfunction collectBundledRuntimeExports(code: string): string[] {\n const names: string[] = [];\n if (/import\\s+\\*\\s+as\\s+[\\w$]+\\s+from\\s*[\"']@easytwin\\/runtime[\"']/.test(code)) names.push(\"*\");\n const named = /import\\s*\\{([^}]+)\\}\\s*from\\s*[\"']@easytwin\\/runtime[\"']/g;\n for (const match of code.matchAll(named)) {\n const body = match[1] ?? \"\";\n for (const part of body.split(\",\")) {\n const token = part.replace(/\\btype\\b/g, \"\").trim();\n if (!token) continue;\n const id = token.split(/\\s+as\\s+/)[0]?.trim();\n if (id) names.push(id);\n }\n }\n return names;\n}\n\n/** 打包工作区 src/main.ts。产物标准 ESM + inline sourcemap;仅允许 @easytwin/runtime 与 @easytwin/apps。 */\nexport async function bundleUserCode(options: BundleUserCodeOptions): Promise<BundleResult> {\n const cwd = path.resolve(options.cwd);\n const entry = path.join(cwd, USER_ENTRY);\n try {\n await fs.access(entry);\n } catch {\n throw new BundleError(\n `未找到入口文件 ${entry}。请在工作区创建 src/main.ts,并 \\`export default\\` TwinApp 子类或 defineApp({...})。`\n );\n }\n\n let result: esbuild.BuildResult;\n try {\n result = await esbuild.build({\n absWorkingDir: cwd,\n entryPoints: [entry],\n bundle: true,\n write: false,\n format: \"esm\",\n platform: \"browser\",\n target: \"es2022\",\n sourcemap: \"inline\",\n logLevel: \"silent\",\n plugins: [whitelistPlugin()],\n });\n } catch (err) {\n const errors = (err as { errors?: esbuild.Message[] }).errors;\n if (Array.isArray(errors) && errors.length > 0) {\n throw new BundleError(formatEsbuildMessages(errors));\n }\n throw err instanceof Error ? new BundleError(err.message) : err;\n }\n\n if (result.errors.length > 0) {\n throw new BundleError(formatEsbuildMessages(result.errors));\n }\n const file = result.outputFiles?.[0];\n if (!file) throw new BundleError(\"打包未产出文件\");\n const code = file.text;\n const warnings = result.warnings.map((w) => formatEsbuildMessages([w]));\n const portable = portableRuntimeWarning(collectBundledRuntimeExports(code));\n if (portable) warnings.push(portable);\n\n if (options.outFile) {\n const outFile = path.isAbsolute(options.outFile) ? options.outFile : path.join(cwd, options.outFile);\n await fs.mkdir(path.dirname(outFile), { recursive: true });\n await fs.writeFile(outFile, code, \"utf8\");\n }\n\n return { code, warnings };\n}\n\n/** 若工作区尚未同步 runtime 类型,返回提示文案;已同步则返回 undefined。 */\nexport async function typesMissingHint(cwd: string): Promise<string | undefined> {\n try {\n await fs.access(path.join(cwd, \".easytwin\", \"types\", \"index.d.ts\"));\n return undefined;\n } catch {\n return \"未找到 .easytwin/types,运行 `easytwin skills sync` 以分发 @easytwin/runtime 类型声明。\";\n }\n}\n\nconst SOURCEMAP_RE = /sourceMappingURL=data:application\\/json(?:;charset=[^;]+)?;base64,([A-Za-z0-9+/]+=*)/;\n\ninterface SourceMapJson {\n sources?: string[];\n mappings?: string;\n}\n\ninterface OriginalPos {\n source: string;\n line: number;\n column: number;\n}\n\ninterface MappingSeg {\n generatedColumn: number;\n source: string;\n originalLine: number;\n originalColumn: number;\n}\n\nconst VLQ_CHARS = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\nfunction decodeVLQValues(str: string): number[] {\n const values: number[] = [];\n let i = 0;\n while (i < str.length) {\n let result = 0;\n let shift = 0;\n let continuation = true;\n while (continuation) {\n if (i >= str.length) return values;\n const digit = VLQ_CHARS.indexOf(str[i++] ?? \"\");\n if (digit < 0) return values;\n continuation = (digit & 32) !== 0;\n result += (digit & 31) << shift;\n shift += 5;\n }\n values.push(result & 1 ? -(result >> 1) : result >> 1);\n }\n return values;\n}\n\nfunction decodeMappings(map: SourceMapJson): MappingSeg[][] {\n const sources = map.sources ?? [];\n const lines = (map.mappings ?? \"\").split(\";\");\n let sourceIndex = 0;\n let originalLine = 0;\n let originalColumn = 0;\n const decoded: MappingSeg[][] = [];\n for (const line of lines) {\n let generatedColumn = 0;\n const segs: MappingSeg[] = [];\n if (line) {\n for (const raw of line.split(\",\")) {\n if (!raw) continue;\n const nums = decodeVLQValues(raw);\n if (nums[0] === undefined) continue;\n generatedColumn += nums[0];\n if (nums.length >= 4) {\n sourceIndex += nums[1] ?? 0;\n originalLine += nums[2] ?? 0;\n originalColumn += nums[3] ?? 0;\n segs.push({\n generatedColumn,\n source: sources[sourceIndex] ?? USER_ENTRY,\n originalLine,\n originalColumn,\n });\n }\n }\n }\n decoded.push(segs);\n }\n return decoded;\n}\n\n/** generated line/col 均为 1-based(与 Error.stack 一致)。无精确段时回退到上一行最后一个映射。 */\nfunction originalPositionFor(map: SourceMapJson, line: number, column: number): OriginalPos | undefined {\n const decoded = decodeMappings(map);\n for (let i = line - 1; i >= 0; i--) {\n const segs = decoded[i];\n if (!segs || segs.length === 0) continue;\n const col = i === line - 1 ? column - 1 : Number.POSITIVE_INFINITY;\n let best = segs[0];\n for (const seg of segs) {\n if (seg.generatedColumn <= col) best = seg;\n else break;\n }\n if (!best) continue;\n return { source: best.source, line: best.originalLine + 1, column: best.originalColumn };\n }\n return undefined;\n}\n\nexport function extractInlineSourceMap(code: string): SourceMapJson | undefined {\n const m = code.match(SOURCEMAP_RE);\n if (!m?.[1]) return undefined;\n try {\n return JSON.parse(Buffer.from(m[1], \"base64\").toString(\"utf8\")) as SourceMapJson;\n } catch {\n return undefined;\n }\n}\n\n/**\n * 把 bundled JS 的 stack(blob: 行号)映射回 TS 源码行号。\n * 映射失败时原样返回。\n */\nexport function remapErrorStack(stack: string, bundledCode: string): string {\n const map = extractInlineSourceMap(bundledCode);\n if (!map?.mappings) return stack;\n return stack.replace(/(blob:[^\\s)]+?):(\\d+):(\\d+)/g, (full, _url: string, line: string, col: string) => {\n const orig = originalPositionFor(map, Number(line), Number(col));\n if (!orig) return full;\n return `${orig.source}:${orig.line}:${orig.column}`;\n });\n}\n","/** 在线 TwinApp 编译 stub 露出的 `@easytwin/runtime` 导出名。本地整包 external,超出此集合只 warning。 */\nexport const PORTABLE_RUNTIME_EXPORTS = [\n \"THREE\",\n \"RuntimeEngine\",\n \"SceneManager\",\n \"LoadSceneMode\",\n \"convertObjToComponentJson\",\n] as const;\n\nexport type PortableRuntimeExport = (typeof PORTABLE_RUNTIME_EXPORTS)[number];\n\nexport type TwinAppEngine = {\n container: HTMLElement;\n time: { deltaTime: number; elapsedTime: number };\n mainScene?: TwinAppRuntimeScene | null;\n getManager(ctor: unknown): TwinAppSceneManager | null;\n destroy(): void;\n};\n\nexport type TwinAppRuntimeScene = {\n sceneObject?: { add(object: unknown): void; remove(object: unknown): void } | null;\n camera?: { main?: unknown } | null;\n};\n\nexport type TwinAppSceneManager = {\n loadScene(...args: unknown[]): Promise<unknown>;\n};\n\nexport type TwinAppContext = {\n app: {\n id: string;\n mode: \"preview\" | \"publish\";\n };\n engine: TwinAppEngine;\n container: HTMLElement;\n runtimeScene: TwinAppRuntimeScene | null;\n scene: TwinAppRuntimeScene[\"sceneObject\"] | null;\n camera: unknown | null;\n sceneManager: {\n currentSceneId: string;\n runtime: TwinAppSceneManager | null;\n loadScene(sceneId: string): Promise<void>;\n };\n logger: {\n log(...args: unknown[]): void;\n info(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n error(...args: unknown[]): void;\n };\n assets: {\n text(path: string): Promise<string>;\n json<T = unknown>(path: string): Promise<T>;\n };\n cleanup(fn: () => void | Promise<void>): void;\n sceneCleanup(fn: () => void | Promise<void>): void;\n};\n\nexport abstract class TwinApp {\n init?(ctx: TwinAppContext): void | Promise<void>;\n onUpdate?(ctx: TwinAppContext, delta: number, elapsed: number): void;\n onBeforeSceneUnload?(ctx: TwinAppContext): void | Promise<void>;\n onSceneLoaded?(ctx: TwinAppContext): void | Promise<void>;\n onDispose?(ctx: TwinAppContext): void | Promise<void>;\n onError?(ctx: TwinAppContext, error: unknown): boolean | void;\n}\n\nexport function defineApp<T>(app: T): T {\n return app;\n}\n\nconst LIFECYCLE_NAMES = [\n \"init\",\n \"onUpdate\",\n \"onBeforeSceneUnload\",\n \"onSceneLoaded\",\n \"onDispose\",\n \"onError\",\n] as const;\n\nfunction isLifecycleApp(value: unknown): value is TwinApp {\n if (typeof value !== \"object\" || value === null) return false;\n return LIFECYCLE_NAMES.some((name) => typeof Reflect.get(value, name) === \"function\");\n}\n\n/** 把用户模块 default 导出收成 TwinApp 实例。函数式 `main` 不认。 */\nexport function createAppInstance(appExport: unknown): TwinApp {\n if (\n typeof appExport === \"function\" &&\n (appExport.prototype instanceof TwinApp || isLifecycleApp(appExport.prototype))\n ) {\n return new (appExport as new () => TwinApp)();\n }\n if (isLifecycleApp(appExport)) return appExport;\n throw new Error(\"入口默认导出必须是 TwinApp 子类或 defineApp({...}) 生命周期对象\");\n}\n\nexport function portableRuntimeWarning(names: Iterable<string>): string | undefined {\n const extra = [...new Set(names)].filter(\n (n) => n !== \"*\" && !(PORTABLE_RUNTIME_EXPORTS as readonly string[]).includes(n)\n );\n const ns = [...names].includes(\"*\");\n if (!ns && extra.length === 0) return undefined;\n const detail = ns\n ? \"namespace import *\"\n : extra.sort().join(\", \");\n return `检测到 @easytwin/runtime 导出 ${detail} 不在在线编译白名单(${PORTABLE_RUNTIME_EXPORTS.join(\", \")})内。本地预览可用,上传到在线 TwinApp 可能编不过。`;\n}\n","import { createAppInstance, TwinApp, type TwinAppContext, type TwinAppEngine } from \"./apps\";\n\nexport const LOCAL_LOAD_SCENE_ERROR = \"本地预览单场景,不能调用 sceneManager.loadScene\";\nexport const MISSING_TICK_ERROR =\n \"当前 runtime 不支持引擎时钟(缺少 registerEngineTickListener)。无法运行 onUpdate。\";\n\nexport type TwinAppTickListener = (engine: TwinAppEngine) => void;\n\nexport type TwinAppRuntimeModule = {\n RuntimeEngine: {\n create(config: Record<string, unknown>): Promise<TwinAppEngine>;\n };\n SceneManager: unknown;\n LoadSceneMode: { Single: unknown };\n RuntimeSceneMode: { Publish: unknown };\n registerEngineTickListener?: (engine: TwinAppEngine, listener: TwinAppTickListener) => void;\n unregisterEngineTickListener?: (engine: TwinAppEngine, listener: TwinAppTickListener) => void;\n};\n\nexport type TwinAppPreviewHostOptions = {\n runtime: TwinAppRuntimeModule;\n containerId: string;\n ossUrl: string;\n appId: string;\n sceneId: string;\n sceneJson: unknown;\n customComponentDeps: Record<string, unknown>;\n loadScene(engine: TwinAppEngine, sceneJson: unknown): Promise<void>;\n readAsset(path: string): Promise<string>;\n importUserModule?(code: string): Promise<{ default: unknown }>;\n log?: (line: string) => void;\n};\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n return typeof value === \"object\" && value !== null && \"then\" in value;\n}\n\nexport class TwinAppPreviewHost {\n private app: TwinApp | null = null;\n private engine: TwinAppEngine | null = null;\n private disposed = false;\n /** 用户应用已经成功 onSceneLoaded。 */\n private scenePresented = false;\n private tickAttached = false;\n private sceneLoadTask: Promise<void> | null = null;\n private ctx: TwinAppContext | null = null;\n private cleanups: Array<() => void | Promise<void>> = [];\n private sceneCleanups: Array<() => void | Promise<void>> = [];\n private warnedAsyncUpdate = false;\n private userBlobUrl: string | null = null;\n private currentSceneId: string;\n private readonly onEngineTick: TwinAppTickListener;\n\n constructor(private readonly options: TwinAppPreviewHostOptions) {\n this.currentSceneId = options.sceneId;\n this.onEngineTick = (engine) => this.handleTick(engine);\n }\n\n getEngine(): TwinAppEngine | null {\n return this.engine;\n }\n\n async boot(): Promise<void> {\n const { runtime, containerId, ossUrl, customComponentDeps } = this.options;\n this.engine = await runtime.RuntimeEngine.create({\n containerId,\n baseOSSUrl: ossUrl,\n customComponentDeps,\n sceneResources: [],\n componentRels: [],\n enableResourcePersistence: false,\n });\n await this.loadCurrentScene();\n }\n\n async run(code: string): Promise<void> {\n if (this.disposed) throw new Error(\"预览宿主已销毁\");\n if (!this.engine) throw new Error(\"场景尚未加载完成,无法 Run\");\n this.assertTickApi();\n\n try {\n await this.teardownApp({ keepEngine: true });\n const mod = await this.importUser(code);\n this.app = createAppInstance(mod.default);\n await this.app.init?.(this.getContext());\n await this.loadCurrentScene();\n this.scenePresented = true;\n await this.app.onSceneLoaded?.(this.getContext());\n this.attachTick();\n } catch (error) {\n await this.teardownApp({ keepEngine: true, ignoreHookErrors: true });\n throw error;\n }\n }\n\n async dispose(): Promise<void> {\n if (this.disposed) return;\n this.disposed = true;\n await this.teardownApp({ keepEngine: false, ignoreHookErrors: true });\n }\n\n private assertTickApi(): void {\n const { runtime } = this.options;\n if (\n typeof runtime.registerEngineTickListener !== \"function\" ||\n typeof runtime.unregisterEngineTickListener !== \"function\"\n ) {\n throw new Error(MISSING_TICK_ERROR);\n }\n }\n\n private async importUser(code: string): Promise<{ default: unknown }> {\n if (this.options.importUserModule) return this.options.importUserModule(code);\n if (this.userBlobUrl) {\n try {\n URL.revokeObjectURL(this.userBlobUrl);\n } catch {\n /* ignore */\n }\n this.userBlobUrl = null;\n }\n const blob = new Blob([code], { type: \"text/javascript\" });\n this.userBlobUrl = URL.createObjectURL(blob);\n return import(/* @vite-ignore */ this.userBlobUrl);\n }\n\n private async loadCurrentScene(): Promise<void> {\n if (!this.engine) throw new Error(\"Engine is not created\");\n if (this.sceneLoadTask) await this.sceneLoadTask;\n this.sceneLoadTask = this.options.loadScene(this.engine, this.options.sceneJson).finally(() => {\n this.sceneLoadTask = null;\n });\n await this.sceneLoadTask;\n }\n\n private handleTick(engine: TwinAppEngine): void {\n if (this.disposed || this.sceneLoadTask || !this.scenePresented) return;\n try {\n const result = this.app?.onUpdate?.(\n this.getContext(),\n engine.time.deltaTime,\n engine.time.elapsedTime\n ) as unknown;\n if (isPromiseLike(result)) {\n void Promise.resolve(result).catch((error) => {\n console.error(\"async onUpdate rejected:\", error);\n });\n if (!this.warnedAsyncUpdate) {\n this.warnedAsyncUpdate = true;\n console.warn(\"TwinApp.onUpdate 应同步执行;本次已忽略其 Promise 返回值\");\n }\n }\n } catch (error) {\n this.handleUpdateError(error);\n }\n }\n\n private handleUpdateError(error: unknown): void {\n let shouldContinue = false;\n try {\n shouldContinue = this.app?.onError?.(this.getContext(), error) === true;\n } catch (onError) {\n void this.failRun(onError);\n return;\n }\n if (shouldContinue) {\n console.error(\"TwinApp.onUpdate threw:\", error);\n this.options.log?.(`onUpdate 抛错已 continue: ${error instanceof Error ? error.message : String(error)}`);\n return;\n }\n void this.failRun(error);\n }\n\n private async failRun(error: unknown): Promise<void> {\n this.options.log?.(`Run 失败 ${error instanceof Error ? error.stack ?? error.message : String(error)}`);\n await this.teardownApp({ keepEngine: true, ignoreHookErrors: true });\n }\n\n private attachTick(): void {\n if (!this.engine || this.tickAttached) return;\n this.options.runtime.registerEngineTickListener?.(this.engine, this.onEngineTick);\n this.tickAttached = true;\n }\n\n private detachTick(): void {\n if (!this.engine || !this.tickAttached) return;\n this.options.runtime.unregisterEngineTickListener?.(this.engine, this.onEngineTick);\n this.tickAttached = false;\n }\n\n private async teardownApp(options: { keepEngine: boolean; ignoreHookErrors?: boolean }): Promise<void> {\n this.detachTick();\n await this.unloadUserScene({ ignoreErrors: options.ignoreHookErrors });\n if (this.app && this.engine) {\n try {\n await this.app.onDispose?.(this.getContext());\n } catch (error) {\n if (!options.ignoreHookErrors) throw error;\n console.warn(\"TwinApp.onDispose failed:\", error);\n }\n }\n await this.runHooks(this.cleanups);\n this.cleanups = [];\n this.app = null;\n this.ctx = null;\n this.scenePresented = false;\n if (!options.keepEngine) {\n try {\n this.engine?.destroy();\n } catch {\n /* webview 销毁阶段容错 */\n }\n this.engine = null;\n }\n if (this.userBlobUrl) {\n try {\n URL.revokeObjectURL(this.userBlobUrl);\n } catch {\n /* ignore */\n }\n this.userBlobUrl = null;\n }\n }\n\n private async unloadUserScene(options?: { ignoreErrors?: boolean }): Promise<void> {\n if (!this.scenePresented) return;\n this.scenePresented = false;\n try {\n if (this.engine) await this.app?.onBeforeSceneUnload?.(this.getContext());\n } catch (error) {\n if (!options?.ignoreErrors) throw error;\n console.warn(\"TwinApp.onBeforeSceneUnload failed:\", error);\n } finally {\n await this.runHooks(this.sceneCleanups);\n this.sceneCleanups = [];\n }\n }\n\n private async runHooks(hooks: Array<() => void | Promise<void>>): Promise<void> {\n for (const fn of [...hooks].reverse()) {\n try {\n await fn();\n } catch (error) {\n console.warn(\"TwinApp cleanup failed:\", error);\n }\n }\n }\n\n private getContext(): TwinAppContext {\n if (!this.engine) throw new Error(\"Engine is not created\");\n const runtimeScene = this.scenePresented ? (this.engine.mainScene ?? null) : null;\n const scene = runtimeScene?.sceneObject ?? null;\n const camera = runtimeScene?.camera?.main ?? null;\n const sceneManagerRuntime = this.engine.getManager(this.options.runtime.SceneManager);\n\n if (!this.ctx) {\n this.ctx = {\n app: { id: this.options.appId, mode: \"preview\" },\n engine: this.engine,\n container: this.engine.container,\n runtimeScene,\n scene,\n camera,\n sceneManager: {\n currentSceneId: this.currentSceneId,\n runtime: sceneManagerRuntime,\n loadScene: () => Promise.reject(new Error(LOCAL_LOAD_SCENE_ERROR)),\n },\n logger: {\n log: (...args: unknown[]) => console.log(...args),\n info: (...args: unknown[]) => console.info(...args),\n warn: (...args: unknown[]) => console.warn(...args),\n error: (...args: unknown[]) => console.error(...args),\n },\n assets: {\n text: (p: string) => this.options.readAsset(p),\n json: async <T>(p: string) => JSON.parse(await this.options.readAsset(p)) as T,\n },\n cleanup: (fn) => {\n this.cleanups.push(fn);\n },\n sceneCleanup: (fn) => {\n this.sceneCleanups.push(fn);\n },\n };\n return this.ctx;\n }\n\n this.ctx.engine = this.engine;\n this.ctx.container = this.engine.container;\n this.ctx.runtimeScene = runtimeScene;\n this.ctx.scene = scene;\n this.ctx.camera = camera;\n this.ctx.sceneManager.currentSceneId = this.currentSceneId;\n this.ctx.sceneManager.runtime = sceneManagerRuntime;\n return this.ctx;\n }\n}\n"],"mappings":"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","names":["URL","path","fs","path","path","fs","payload","build","fs","path","fs","path","asRecord","asString","fs","path","path","path","extensionOf","allowedExtensionSet","fs","fs","path","fileURLToPath","fs","path","path","build","fs"]}