@easytwin/devkit 0.1.0 → 0.1.2

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.d.ts CHANGED
@@ -1,22 +1,75 @@
1
1
  /** 配置文件名(项目根)。 */
2
2
  declare const CONFIG_FILE_NAME = "easytwin.config.json";
3
3
  /**
4
- * 官方缺省域名。
5
- * TODO(外部输入): 域名值待定。该常量是全仓唯一收口点,只允许写在这里。
4
+ * 官方缺省域名(正式环境)。该常量是全仓唯一收口点,只允许写在这里。
6
5
  */
7
- declare const DEFAULT_BASE_URL = "https://api.easytwin.example.com";
6
+ declare const DEFAULT_BASE_URL = "http://saas-twin.k8s.dtstack.cn/";
7
+ /** 官方测试环境域名。 */
8
+ declare const TEST_BASE_URL = "http://172.16.125.3:10100/";
9
+ /**
10
+ * 当前测试 OP 网关缺省头(与编辑器 curl 一致)。配置/环境变量可覆盖。
11
+ * 免网关接口到位后删除(D13)。
12
+ */
13
+ declare const TEST_OP_ACCOUNT_ID = "25";
14
+ declare const TEST_OP_USER_ID = "25";
15
+ declare const TEST_SPACE_ID = "54";
16
+ /**
17
+ * 官方 OSS(twin runtime baseOSSUrl)。系统资产由此拼出:
18
+ * `{ossUrl}/easytwin/system/libs/webp-wasm.wasm`、
19
+ * `{ossUrl}/easytwin/system/libs/draco/`、
20
+ * `{ossUrl}/easytwin/system/components/custom/{type}/{version}/script.js`。
21
+ * 不得用 API baseUrl 代替:场景/上传走 API,系统库与组件脚本走 OSS。
22
+ */
23
+ declare const DEFAULT_OSS_URL = "https://dt-easyv-test.oss-cn-hangzhou.aliyuncs.com/";
24
+ /** 服务环境,决定缺省 baseUrl。 */
25
+ type EasyTwinEnv = "prod" | "test";
26
+ /** 本地测试模式哨兵凭据:appId 与 appSecret 均为该值时,场景/上传走本地 mock,不发网络请求(见 AGENTS.md 4.4)。 */
27
+ declare const MOCK_APP_ID = "test";
28
+ declare const MOCK_APP_SECRET = "test";
29
+ /** appId/appSecret 是否命中本地测试模式哨兵值。 */
30
+ declare function isMockCredentials(appId: string, appSecret: string): boolean;
8
31
  /** 磁盘上的配置结构(4.3 配置契约)。 */
9
32
  interface EasyTwinConfig {
10
33
  appId: string;
11
34
  appSecret: string;
35
+ /** 服务环境,缺省 prod。 */
36
+ env?: EasyTwinEnv;
12
37
  baseUrl?: string;
38
+ /** twin runtime 资产根(baseOSSUrl);缺省官方 OSS,可覆盖为 CDN/自建存储。 */
39
+ ossUrl?: string;
40
+ /** 过渡期 OP 网关头;免网关接口到位后删除(D13)。 */
41
+ opAccountId?: string;
42
+ opUserId?: string;
43
+ spaceId?: string;
44
+ /**
45
+ * 关联场景摘要,由 scene list / 场景树刷新写入(D17)。
46
+ * 不含场景 JSON 本体;下次 list 全量覆盖。
47
+ */
48
+ scenes?: ConfigScene[];
49
+ }
50
+ /** 写入 easytwin.config.json 的关联场景摘要(对应 listScenes 的可序列化子集)。 */
51
+ interface ConfigScene {
52
+ /** Scene Key,与 `easytwin scene pull <id>` 对应。 */
53
+ id: string;
54
+ name: string;
55
+ linkedSceneId?: string;
56
+ snapshotUrl?: string;
57
+ defaultLoading?: boolean;
13
58
  }
14
59
  /** 解析 + 环境变量覆盖后的最终配置。 */
15
60
  interface ResolvedConfig {
16
61
  appId: string;
17
62
  appSecret: string;
18
63
  baseUrl: string;
64
+ /** twin runtime baseOSSUrl(系统库 draco/basis/webp、custom script 与相对路径资产);缺省官方 OSS。 */
65
+ ossUrl: string;
66
+ /** 本地测试模式:appId/appSecret 均为 "test" 时启用,scene/upload/pull 走本地 mock 不发请求。 */
67
+ mock: boolean;
19
68
  source: "file" | "env";
69
+ /** 过渡期 OP 网关头;env=test 时缺省 25/25/54。免网关接口到位后删除(D13)。 */
70
+ opAccountId?: string;
71
+ opUserId?: string;
72
+ spaceId?: string;
20
73
  }
21
74
  declare class ConfigError extends Error {
22
75
  constructor(message: string);
@@ -43,19 +96,29 @@ interface InitResult {
43
96
  }
44
97
  /** init 的 lib 实现:生成配置文件 + 追加 gitignore(与插件配置向导共用同一实现)。 */
45
98
  declare function initConfig(input: EasyTwinConfig, cwd: string): Promise<InitResult>;
99
+ /** 把场景摘要写入配置 `scenes`(全量覆盖该数组,保留其余字段)。 */
100
+ declare function writeConfigScenes(cwd: string, scenes: ConfigScene[]): Promise<void>;
46
101
 
47
102
  /**
48
- * TODO(swagger): 认证头名称、endpoint 路径、请求/响应结构一律以内部 swagger 为准。
49
- * 以下常量为占位约定;swagger 到位后在 client.ts / scene.ts / upload.ts 集中修订,不扩散到其它文件。
103
+ * 认证与路径以内部 swagger 为准(标签:SDK 应用场景 / SDK 应用代码 / SDK Runtime)。
104
+ * 全仓唯一认证头注入点:`x-app-secret` = App Secret。
105
+ * 过渡期另注入 OP 网关头 op-account-id / op-user-id / space-id(D13,免网关接口到位后删除)。
106
+ * 场景/代码路径参数名为 applicationId;DevKit 传入配置里的 App ID。
50
107
  */
51
- declare const AUTH_HEADER = "Authorization";
52
- declare const BEARER_PREFIX = "Bearer";
53
- /** TODO(swagger): 应用标识头名待定(上传目标空间由 App ID 决定)。 */
54
- declare const APP_ID_HEADER = "X-Easytwin-App-Id";
108
+ declare const AUTH_HEADER = "x-app-secret";
109
+ /** 过渡期 OP 网关头;免网关接口到位后删除(D13)。 */
110
+ declare const OP_ACCOUNT_ID_HEADER = "op-account-id";
111
+ declare const OP_USER_ID_HEADER = "op-user-id";
112
+ declare const SPACE_ID_HEADER = "space-id";
55
113
  declare const ENDPOINTS: {
56
- readonly scenes: "/api/scenes";
57
- readonly scene: (id: string) => string;
58
- readonly upload: "/api/upload";
114
+ /** GET 已关联场景列表。 */
115
+ readonly linkedScenes: (applicationId: string) => string;
116
+ /** GET 工作区全部代码文件。 */
117
+ readonly workspaceCode: (applicationId: string) => string;
118
+ /** GET 工作区文件约束。 */
119
+ readonly workspaceConfig: (applicationId: string) => string;
120
+ /** POST 新建 / PATCH 批量更新 / DELETE 批量删除。 */
121
+ readonly workspaceCodeFiles: (applicationId: string) => string;
59
122
  };
60
123
  declare class EasyTwinApiError extends Error {
61
124
  readonly status: number;
@@ -63,15 +126,23 @@ declare class EasyTwinApiError extends Error {
63
126
  constructor(status: number, message: string, body?: unknown);
64
127
  }
65
128
  interface RequestOptions {
66
- method?: "GET" | "POST" | "PUT" | "DELETE";
129
+ method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
67
130
  headers?: Record<string, string>;
68
131
  body?: string | null;
69
132
  signal?: AbortSignal;
70
133
  }
71
134
  declare class EasyTwinClient {
72
135
  readonly baseUrl: string;
73
- private readonly appId;
136
+ /** twin runtime / 场景快照资产根(baseOSSUrl)。 */
137
+ readonly ossUrl: string;
138
+ /** 接入凭证 App ID;同时作为场景/代码 API 的 applicationId 路径参数。 */
139
+ readonly appId: string;
140
+ /** 本地测试模式:true 时 scene/upload/pull 走本地 mock,不发网络请求(见 config.ts)。 */
141
+ readonly mock: boolean;
74
142
  private readonly appSecret;
143
+ private readonly opAccountId?;
144
+ private readonly opUserId?;
145
+ private readonly spaceId?;
75
146
  constructor(config: ResolvedConfig);
76
147
  /** 全仓唯一认证头注入点。 */
77
148
  private authHeaders;
@@ -89,21 +160,86 @@ declare class EasyTwinClient {
89
160
  private handleStatus;
90
161
  }
91
162
 
163
+ /** swagger `SdkApplicationLinkedSceneVo`。 */
164
+ interface LinkedScene {
165
+ /** 关联记录 ID。 */
166
+ id: string;
167
+ /** SDK 业务标识 Scene Key(list/pull 的主键)。 */
168
+ sceneKey: string;
169
+ name: string;
170
+ defaultLoading: boolean;
171
+ sourceSceneId: string;
172
+ sourceProjectId: string;
173
+ sourceSceneName: string;
174
+ sourceProjectName: string;
175
+ sourceLost: boolean;
176
+ /** 场景快照 JSON 的 OSS 相对路径(或绝对 URL)。 */
177
+ snapshotUrl: string;
178
+ snapshotUpdatedAt: string;
179
+ }
92
180
  interface SceneSummary {
181
+ /** Scene Key,与 `easytwin scene pull <id>` 对应。 */
93
182
  id: string;
94
183
  name: string;
184
+ linkedSceneId?: string;
185
+ snapshotUrl?: string;
186
+ defaultLoading?: boolean;
95
187
  }
96
188
  interface SceneDetail {
97
189
  id: string;
98
190
  name: string;
99
- /** 服务端返回的场景 JSON 原始内容。 */
191
+ /**
192
+ * 场景快照 JSON 原始内容。
193
+ * 结构以 easytwin-runtime 的 SceneJson 为准(见 skills/easytwin-scene)。
194
+ */
100
195
  payload: unknown;
101
196
  }
197
+ /** 从信封/Runtime VO/数组中取出场景列表。 */
198
+ declare function extractSceneArray(data: unknown): unknown[];
199
+ /** 把 swagger 关联场景 / Runtime scenes 规范为 LinkedScene[]。 */
200
+ declare function normalizeLinkedScenes(data: unknown): LinkedScene[];
102
201
  declare function normalizeSceneList(data: unknown): SceneSummary[];
103
- declare function normalizeSceneDetail(data: unknown): SceneDetail;
104
- declare function listScenes(client: EasyTwinClient): Promise<SceneSummary[]>;
105
- declare function pullScene(client: EasyTwinClient, id: string): Promise<SceneDetail>;
202
+ /** list 结果收成配置里的 scenes 摘要(省略空可选字段) */
203
+ declare function toConfigScenes(scenes: SceneSummary[]): ConfigScene[];
204
+ /** 拼接场景快照地址:绝对 URL 原样使用,否则挂到 ossUrl 下。 */
205
+ declare function resolveSnapshotUrl(ossUrl: string, snapshotUrl: string): string;
206
+ /** devkit 包内本地测试场景文件名(4.4 本地测试模式)。 */
207
+ declare const EXAMPLE_SCENE_FILE = "scene.example.json";
208
+ /** 本地测试模式下场景列表展示的名字(示例文件本身不含场景级 name)。 */
209
+ declare const MOCK_SCENE_NAME = "\u672C\u5730\u793A\u4F8B\u573A\u666F";
210
+ /**
211
+ * 示例场景文件默认路径:devkit 包内 scene.example.json(CLI/源码)。
212
+ * 插件 bundle 到 CJS 后 import.meta.url 为空,必须经 listScenes/pullScene 的 exampleFile 显式传入(与 skills 的 sourceDir 同理)。
213
+ */
214
+ declare function resolveExampleScenePath(): string;
215
+ /** 读取并解析本地示例场景(本地测试模式专用,不发网络请求)。 */
216
+ declare function loadExampleScene(exampleFile?: string): Promise<unknown>;
217
+ /** 从示例场景提取场景 id:取 objs[].sceneId 首个非空值;无则回退 "local"。 */
218
+ declare function deriveExampleSceneId(payload: unknown): string;
219
+ /** 本地测试模式下的场景列表(单条)。 */
220
+ declare function exampleSceneSummary(exampleFile?: string): Promise<SceneSummary>;
221
+ declare function listScenes(client: EasyTwinClient, options?: {
222
+ exampleFile?: string;
223
+ cwd?: string;
224
+ }): Promise<SceneSummary[]>;
225
+ declare function pullScene(client: EasyTwinClient, id: string, options?: {
226
+ exampleFile?: string;
227
+ }): Promise<SceneDetail>;
106
228
  declare function saveSceneJson(scene: SceneDetail, out: string): Promise<string>;
229
+ /** 场景对象树节点:由场景 JSON 的 objs/hierarchy 按 parentObjId 组装(侧边栏场景结构树等复用)。 */
230
+ interface SceneTreeNode {
231
+ id: string;
232
+ name: string;
233
+ type?: string;
234
+ children: SceneTreeNode[];
235
+ }
236
+ /**
237
+ * 解析场景对象层级树:优先读 `objs`(含 type),缺失或为空时回退 `hierarchy`。
238
+ * - `parentObjId` 为空 / 指向不存在的 id / 自引用时,该节点视为根;
239
+ * - 节点顺序保持场景数组顺序;非法输入或无可解析结构时返回空数组。
240
+ * scene 可为已解析对象或 JSON 字符串。
241
+ */
242
+ declare function parseSceneStructure(scene: unknown): SceneTreeNode[];
107
243
 
108
244
  interface UploadProgress {
109
245
  phase: "collect" | "upload";
@@ -121,22 +257,98 @@ interface UploadOptions {
121
257
  interface UploadResult {
122
258
  fileCount: number;
123
259
  byteCount: number;
260
+ /** 本地测试模式(dry-run)时置 true:未真正上传。 */
261
+ mock?: boolean;
124
262
  }
125
263
  interface CollectedFile {
126
264
  relPath: string;
127
265
  absPath: string;
128
266
  size: number;
129
267
  }
268
+ /** swagger `SdkApplicationWorkspaceCodeConfigVo`。 */
269
+ interface WorkspaceCodeConfig {
270
+ allowedFileExtensions: string[];
271
+ maxCodeFiles: number;
272
+ maxCodeDirectoryDepth: number;
273
+ }
274
+ /** swagger `SdkApplicationWorkspaceCodeFileVo`。 */
275
+ interface WorkspaceCodeFile {
276
+ id: string;
277
+ filePath: string;
278
+ content: string;
279
+ }
130
280
  /** 递归收集目录下全部文件(默认跳过 .git),按相对路径升序排列,保证顺序稳定。 */
131
281
  declare function collectFiles(dir: string, ignore?: (relPath: string) => boolean): Promise<CollectedFile[]>;
132
282
  declare function buildMultipartBody(boundary: string, fields: Record<string, string>, file: {
133
283
  name: string;
134
284
  content: Buffer;
135
285
  }): Buffer;
136
- /** 全量覆盖上传目录:逐文件 multipart 上传,带进度回调(供插件进度条) */
286
+ declare function normalizePath(relPath: string): string;
287
+ declare function normalizeWorkspaceConfig(data: unknown): WorkspaceCodeConfig;
288
+ declare function normalizeWorkspaceFiles(data: unknown): WorkspaceCodeFile[];
289
+ /** 目录深度:根文件为 0,`src/a.ts` 为 1,`src/utils/a.ts` 为 2。 */
290
+ declare function directoryDepth(relPath: string): number;
291
+ declare function assertUploadable(files: CollectedFile[], config: WorkspaceCodeConfig): void;
292
+ /**
293
+ * 全量覆盖上传目录:对照工作区代码文件(GET/POST/PATCH/DELETE)使远端与本地一致。
294
+ * 本地测试模式(mock)时退化为 dry-run。
295
+ */
137
296
  declare function uploadDirectory(client: EasyTwinClient, dir: string, options?: UploadOptions): Promise<UploadResult>;
138
297
 
139
- type SyncTarget = "cursor" | "claude" | "codex";
298
+ declare const DEFAULT_ENTRY_PATH = "src/main.ts";
299
+ /** 与 easytwin-render 可上传子集示例对齐的默认 TwinApp 子类入口。 */
300
+ declare 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 \u5DF2\u6709;scene / camera \u4E3A null\n void ctx;\n }\n\n async onSceneLoaded(ctx: TwinAppContext) {\n // \u573A\u666F\u5B57\u6BB5\u6709\u503C;\u5728\u6B64\u52A0\u7269\u4F53 / \u7ED1\u4E8B\u4EF6,\u5E76\u7528 ctx.sceneCleanup \u5BF9\u79F0\u62C6\u9664\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";
301
+ type WorkspaceChangeKind = "identical" | "remote-only" | "local-only" | "modified" | "seed";
302
+ interface WorkspaceFileChange {
303
+ path: string;
304
+ kind: WorkspaceChangeKind;
305
+ localContent?: string;
306
+ remoteContent?: string;
307
+ }
308
+ interface WorkspacePullPlan {
309
+ remoteEmpty: boolean;
310
+ seededDefaults: boolean;
311
+ mock?: boolean;
312
+ skippedRemotePaths: string[];
313
+ changes: WorkspaceFileChange[];
314
+ }
315
+ interface WorkspacePullOptions {
316
+ /** 用远端内容覆盖内容冲突的本地文件;仅本地文件仍不删除。 */
317
+ force?: boolean;
318
+ /** 只算计划,不写盘。 */
319
+ dryRun?: boolean;
320
+ ignore?: (relPath: string) => boolean;
321
+ }
322
+ interface WorkspacePullResult {
323
+ plan: WorkspacePullPlan;
324
+ written: string[];
325
+ skippedConflicts: string[];
326
+ dryRun?: boolean;
327
+ mock?: boolean;
328
+ }
329
+ declare function defaultPullIgnore(relPath: string): boolean;
330
+ /** 拒绝逃逸、空路径与凭据文件,避免远端路径写到工作区外。 */
331
+ declare function isSafeRelPath(relPath: string): boolean;
332
+ /**
333
+ * 对照远端工作区代码与本地目录,算出 diff 计划。
334
+ * mock 或远端无有效文件时,本地缺省入口视为 seed。
335
+ */
336
+ declare function planWorkspacePull(client: EasyTwinClient, dir: string, options?: Pick<WorkspacePullOptions, "ignore">): Promise<WorkspacePullPlan>;
337
+ interface WorkspacePullApplyResult {
338
+ written: string[];
339
+ skippedConflicts: string[];
340
+ }
341
+ /** 按计划写盘:seed 与 remote-only 始终写入;modified 仅 force 时覆盖;不删 local-only。 */
342
+ declare function applyWorkspacePull(dir: string, plan: WorkspacePullPlan, options?: {
343
+ force?: boolean;
344
+ }): Promise<WorkspacePullApplyResult>;
345
+ declare function pullWorkspace(client: EasyTwinClient, dir: string, options?: WorkspacePullOptions): Promise<WorkspacePullResult>;
346
+ declare function formatWorkspacePullPlan(plan: WorkspacePullPlan): string;
347
+ declare function formatWorkspacePullResult(result: WorkspacePullResult): string;
348
+ declare function workspacePullHasConflicts(plan: WorkspacePullPlan): boolean;
349
+ declare function workspacePullPendingWrites(plan: WorkspacePullPlan, force?: boolean): string[];
350
+
351
+ type SyncTarget = "cursor" | "claude" | "codex" | "qoder";
140
352
  type SyncTargetArg = SyncTarget | "all";
141
353
  /** 六件套清单(5.1),顺序即输出顺序。 */
142
354
  declare const SKILL_NAMES: readonly ["easytwin-render", "easytwin-core", "easytwin-develop", "easytwin-bootstrap", "easytwin-scene", "easytwin-upload"];
@@ -156,16 +368,36 @@ interface SyncOptions {
156
368
  version?: string;
157
369
  /** skills 源目录;缺省按 devkit 包内 skills/ 解析(CLI)。插件 bundle 场景显式传入插件内目录。 */
158
370
  sourceDir?: string;
371
+ /** runtime index.d.ts 源文件;缺省按包内 src/lib 或 dist/runtime-types 解析。插件必须显式传入。 */
372
+ typesSourceFile?: string;
159
373
  }
160
374
  declare const CODEX_MARKER_BEGIN = "<!-- EASYTWIN-SKILLS:BEGIN -->";
161
375
  declare const CODEX_MARKER_END = "<!-- EASYTWIN-SKILLS:END -->";
162
376
  declare const META_FILE_NAME = ".easytwin-meta.json";
377
+ /** 用户项目内 runtime 类型落地目录(posix)。 */
378
+ declare const EASYTWIN_TYPES_DIR = ".easytwin/types";
379
+ declare const MINIMAL_TSCONFIG: string;
380
+ declare const TSCONFIG_PATHS_HINT = "\u5DF2\u6709 tsconfig.json,\u672A\u6539\u52A8\u3002\u8BF7\u5728 compilerOptions \u4E2D\u52A0\u5165:\n \"skipLibCheck\": true,\n \"paths\": {\n \"@easytwin/runtime\": [\".easytwin/types\"],\n \"@easytwin/apps\": [\".easytwin/types/apps\"]\n }";
381
+ declare const APPS_TYPES_FILE = "apps.d.ts";
382
+ declare 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";
383
+ declare function buildRuntimeTypesContent(sourceDts: string): string;
163
384
  declare function normalizeTargets(target?: SyncTargetArg | SyncTarget[]): SyncTarget[];
164
385
  /** skills 源目录默认解析:CLI 下为 devkit 包内 skills/。插件 bundle 到 CJS 后 import.meta.url 为空,
165
386
  * 必须通过 SyncOptions.sourceDir / detectSkillsStatus 的 sourceDir 显式传入(见 esbuild.config.mjs 注释)。 */
166
387
  declare function resolveSkillsSourceDir(): string;
388
+ /** runtime 类型声明源:开发态 src/lib/index.d.ts,发布态 dist/runtime-types/index.d.ts。 */
389
+ declare function resolveRuntimeTypesSourceFile(): string;
167
390
  declare function readDevkitVersion(skillsDir?: string): Promise<string>;
168
- declare function syncSkills(options: SyncOptions): Promise<SyncSummary[]>;
391
+ interface TypesSyncSummary {
392
+ action: SyncAction;
393
+ tsconfig: "created" | "unchanged" | "manual-paths";
394
+ pathsHint?: string;
395
+ }
396
+ interface SyncSkillsResult {
397
+ summaries: SyncSummary[];
398
+ types: TypesSyncSummary;
399
+ }
400
+ declare function syncSkills(options: SyncOptions): Promise<SyncSkillsResult>;
169
401
  interface SkillsTargetStatus {
170
402
  target: SyncTarget;
171
403
  synced: boolean;
@@ -174,8 +406,181 @@ interface SkillsTargetStatus {
174
406
  interface SkillsStatus {
175
407
  cwd: string;
176
408
  targets: SkillsTargetStatus[];
409
+ typesSynced: boolean;
177
410
  }
178
411
  /** 供插件"缺失/过期时提示一次"使用:检测各目标当前同步状态。 */
179
412
  declare function detectSkillsStatus(cwd: string, sourceDir?: string): Promise<SkillsStatus>;
180
413
 
181
- export { APP_ID_HEADER, AUTH_HEADER, BEARER_PREFIX, CODEX_MARKER_BEGIN, CODEX_MARKER_END, CONFIG_FILE_NAME, type CollectedFile, ConfigError, DEFAULT_BASE_URL, ENDPOINTS, EasyTwinApiError, EasyTwinClient, type EasyTwinConfig, GITIGNORE_ENTRY, GITIGNORE_FILE_NAME, type GitignoreResult, type InitResult, META_FILE_NAME, type RequestOptions, type ResolvedConfig, SKILL_NAMES, type SceneDetail, type SceneSummary, type SkillsStatus, type SkillsTargetStatus, type SyncAction, type SyncEntrySummary, type SyncOptions, type SyncSummary, type SyncTarget, type SyncTargetArg, type UploadOptions, type UploadProgress, type UploadResult, appendGitignore, buildMultipartBody, collectFiles, configFilePath, detectSkillsStatus, initConfig, listScenes, loadConfig, normalizeSceneDetail, normalizeSceneList, normalizeTargets, parseConfig, pullScene, readConfigFile, readDevkitVersion, resolveConfig, resolveSkillsSourceDir, saveSceneJson, syncSkills, uploadDirectory, validateConfigShape, writeConfigFile };
414
+ /** 用户代码固定入口(相对工作区根)。 */
415
+ declare const USER_ENTRY = "src/main.ts";
416
+ /** CLI 缺省输出路径(相对工作区根)。 */
417
+ declare const DEFAULT_BUNDLE_OUT = "dist/main.js";
418
+ /** 白名单允许的裸模块。 */
419
+ declare const RUNTIME_MODULE = "@easytwin/runtime";
420
+ declare const APPS_MODULE = "@easytwin/apps";
421
+ declare class BundleError extends Error {
422
+ constructor(message: string);
423
+ }
424
+ interface BundleUserCodeOptions {
425
+ cwd: string;
426
+ /** 缺省不落盘,只返回产物字符串(插件内存编译);CLI 传入绝对/相对路径。 */
427
+ outFile?: string;
428
+ }
429
+ interface BundleResult {
430
+ code: string;
431
+ warnings: string[];
432
+ }
433
+ /** 打包工作区 src/main.ts。产物标准 ESM + inline sourcemap;仅允许 @easytwin/runtime 与 @easytwin/apps。 */
434
+ declare function bundleUserCode(options: BundleUserCodeOptions): Promise<BundleResult>;
435
+ /** 若工作区尚未同步 runtime 类型,返回提示文案;已同步则返回 undefined。 */
436
+ declare function typesMissingHint(cwd: string): Promise<string | undefined>;
437
+ interface SourceMapJson {
438
+ sources?: string[];
439
+ mappings?: string;
440
+ }
441
+ declare function extractInlineSourceMap(code: string): SourceMapJson | undefined;
442
+ /**
443
+ * 把 bundled JS 的 stack(blob: 行号)映射回 TS 源码行号。
444
+ * 映射失败时原样返回。
445
+ */
446
+ declare function remapErrorStack(stack: string, bundledCode: string): string;
447
+
448
+ /** 在线 TwinApp 编译 stub 露出的 `@easytwin/runtime` 导出名。本地整包 external,超出此集合只 warning。 */
449
+ declare const PORTABLE_RUNTIME_EXPORTS: readonly ["THREE", "RuntimeEngine", "SceneManager", "LoadSceneMode", "convertObjToComponentJson"];
450
+ type PortableRuntimeExport = (typeof PORTABLE_RUNTIME_EXPORTS)[number];
451
+ type TwinAppEngine = {
452
+ container: HTMLElement;
453
+ time: {
454
+ deltaTime: number;
455
+ elapsedTime: number;
456
+ };
457
+ mainScene?: TwinAppRuntimeScene | null;
458
+ getManager(ctor: unknown): TwinAppSceneManager | null;
459
+ destroy(): void;
460
+ };
461
+ type TwinAppRuntimeScene = {
462
+ sceneObject?: {
463
+ add(object: unknown): void;
464
+ remove(object: unknown): void;
465
+ } | null;
466
+ camera?: {
467
+ main?: unknown;
468
+ } | null;
469
+ };
470
+ type TwinAppSceneManager = {
471
+ loadScene(...args: unknown[]): Promise<unknown>;
472
+ };
473
+ type TwinAppContext = {
474
+ app: {
475
+ id: string;
476
+ mode: "preview" | "publish";
477
+ };
478
+ engine: TwinAppEngine;
479
+ container: HTMLElement;
480
+ runtimeScene: TwinAppRuntimeScene | null;
481
+ scene: TwinAppRuntimeScene["sceneObject"] | null;
482
+ camera: unknown | null;
483
+ sceneManager: {
484
+ currentSceneId: string;
485
+ runtime: TwinAppSceneManager | null;
486
+ loadScene(sceneId: string): Promise<void>;
487
+ };
488
+ logger: {
489
+ log(...args: unknown[]): void;
490
+ info(...args: unknown[]): void;
491
+ warn(...args: unknown[]): void;
492
+ error(...args: unknown[]): void;
493
+ };
494
+ assets: {
495
+ text(path: string): Promise<string>;
496
+ json<T = unknown>(path: string): Promise<T>;
497
+ };
498
+ cleanup(fn: () => void | Promise<void>): void;
499
+ sceneCleanup(fn: () => void | Promise<void>): void;
500
+ };
501
+ declare abstract class TwinApp {
502
+ init?(ctx: TwinAppContext): void | Promise<void>;
503
+ onUpdate?(ctx: TwinAppContext, delta: number, elapsed: number): void;
504
+ onBeforeSceneUnload?(ctx: TwinAppContext): void | Promise<void>;
505
+ onSceneLoaded?(ctx: TwinAppContext): void | Promise<void>;
506
+ onDispose?(ctx: TwinAppContext): void | Promise<void>;
507
+ onError?(ctx: TwinAppContext, error: unknown): boolean | void;
508
+ }
509
+ declare function defineApp<T>(app: T): T;
510
+ /** 把用户模块 default 导出收成 TwinApp 实例。函数式 `main` 不认。 */
511
+ declare function createAppInstance(appExport: unknown): TwinApp;
512
+ declare function portableRuntimeWarning(names: Iterable<string>): string | undefined;
513
+
514
+ /**
515
+ * 把 ctx.assets 的相对路径落到工作区磁盘。规范化后必须仍在 cwd 内。
516
+ */
517
+ declare function resolveWorkspaceAssetPath(cwd: string, relPath: string): string;
518
+
519
+ declare const LOCAL_LOAD_SCENE_ERROR = "\u672C\u5730\u9884\u89C8\u5355\u573A\u666F,\u4E0D\u80FD\u8C03\u7528 sceneManager.loadScene";
520
+ declare const MISSING_TICK_ERROR = "\u5F53\u524D runtime \u4E0D\u652F\u6301\u5F15\u64CE\u65F6\u949F(\u7F3A\u5C11 registerEngineTickListener)\u3002\u65E0\u6CD5\u8FD0\u884C onUpdate\u3002";
521
+ type TwinAppTickListener = (engine: TwinAppEngine) => void;
522
+ type TwinAppRuntimeModule = {
523
+ RuntimeEngine: {
524
+ create(config: Record<string, unknown>): Promise<TwinAppEngine>;
525
+ };
526
+ SceneManager: unknown;
527
+ LoadSceneMode: {
528
+ Single: unknown;
529
+ };
530
+ RuntimeSceneMode: {
531
+ Publish: unknown;
532
+ };
533
+ registerEngineTickListener?: (engine: TwinAppEngine, listener: TwinAppTickListener) => void;
534
+ unregisterEngineTickListener?: (engine: TwinAppEngine, listener: TwinAppTickListener) => void;
535
+ };
536
+ type TwinAppPreviewHostOptions = {
537
+ runtime: TwinAppRuntimeModule;
538
+ containerId: string;
539
+ ossUrl: string;
540
+ appId: string;
541
+ sceneId: string;
542
+ sceneJson: unknown;
543
+ customComponentDeps: Record<string, unknown>;
544
+ loadScene(engine: TwinAppEngine, sceneJson: unknown): Promise<void>;
545
+ readAsset(path: string): Promise<string>;
546
+ importUserModule?(code: string): Promise<{
547
+ default: unknown;
548
+ }>;
549
+ log?: (line: string) => void;
550
+ };
551
+ declare class TwinAppPreviewHost {
552
+ private readonly options;
553
+ private app;
554
+ private engine;
555
+ private disposed;
556
+ /** 用户应用已经成功 onSceneLoaded。 */
557
+ private scenePresented;
558
+ private tickAttached;
559
+ private sceneLoadTask;
560
+ private ctx;
561
+ private cleanups;
562
+ private sceneCleanups;
563
+ private warnedAsyncUpdate;
564
+ private userBlobUrl;
565
+ private currentSceneId;
566
+ private readonly onEngineTick;
567
+ constructor(options: TwinAppPreviewHostOptions);
568
+ getEngine(): TwinAppEngine | null;
569
+ boot(): Promise<void>;
570
+ run(code: string): Promise<void>;
571
+ dispose(): Promise<void>;
572
+ private assertTickApi;
573
+ private importUser;
574
+ private loadCurrentScene;
575
+ private handleTick;
576
+ private handleUpdateError;
577
+ private failRun;
578
+ private attachTick;
579
+ private detachTick;
580
+ private teardownApp;
581
+ private unloadUserScene;
582
+ private runHooks;
583
+ private getContext;
584
+ }
585
+
586
+ export { APPS_DTS, APPS_MODULE, APPS_TYPES_FILE, AUTH_HEADER, BundleError, type BundleResult, type BundleUserCodeOptions, CODEX_MARKER_BEGIN, CODEX_MARKER_END, CONFIG_FILE_NAME, type CollectedFile, ConfigError, type ConfigScene, DEFAULT_BASE_URL, DEFAULT_BUNDLE_OUT, DEFAULT_ENTRY_PATH, DEFAULT_MAIN_TS, DEFAULT_OSS_URL, EASYTWIN_TYPES_DIR, ENDPOINTS, EXAMPLE_SCENE_FILE, EasyTwinApiError, EasyTwinClient, type EasyTwinConfig, type EasyTwinEnv, GITIGNORE_ENTRY, GITIGNORE_FILE_NAME, type GitignoreResult, type InitResult, LOCAL_LOAD_SCENE_ERROR, type LinkedScene, META_FILE_NAME, MINIMAL_TSCONFIG, MISSING_TICK_ERROR, MOCK_APP_ID, MOCK_APP_SECRET, MOCK_SCENE_NAME, OP_ACCOUNT_ID_HEADER, OP_USER_ID_HEADER, PORTABLE_RUNTIME_EXPORTS, type PortableRuntimeExport, RUNTIME_MODULE, type RequestOptions, type ResolvedConfig, SKILL_NAMES, SPACE_ID_HEADER, type SceneDetail, type SceneSummary, type SceneTreeNode, type SkillsStatus, type SkillsTargetStatus, type SyncAction, type SyncEntrySummary, type SyncOptions, type SyncSkillsResult, type SyncSummary, type SyncTarget, type SyncTargetArg, TEST_BASE_URL, TEST_OP_ACCOUNT_ID, TEST_OP_USER_ID, TEST_SPACE_ID, TSCONFIG_PATHS_HINT, TwinApp, type TwinAppContext, type TwinAppEngine, TwinAppPreviewHost, type TwinAppPreviewHostOptions, type TwinAppRuntimeModule, type TwinAppRuntimeScene, type TwinAppSceneManager, type TwinAppTickListener, type TypesSyncSummary, USER_ENTRY, type UploadOptions, type UploadProgress, type UploadResult, type WorkspaceChangeKind, type WorkspaceCodeConfig, type WorkspaceCodeFile, type WorkspaceFileChange, type WorkspacePullApplyResult, type WorkspacePullOptions, type WorkspacePullPlan, type WorkspacePullResult, appendGitignore, applyWorkspacePull, assertUploadable, buildMultipartBody, buildRuntimeTypesContent, bundleUserCode, collectFiles, configFilePath, createAppInstance, defaultPullIgnore, defineApp, deriveExampleSceneId, detectSkillsStatus, directoryDepth, exampleSceneSummary, extractInlineSourceMap, extractSceneArray, formatWorkspacePullPlan, formatWorkspacePullResult, initConfig, isMockCredentials, isSafeRelPath, listScenes, loadConfig, loadExampleScene, normalizeLinkedScenes, normalizePath, normalizeSceneList, normalizeTargets, normalizeWorkspaceConfig, normalizeWorkspaceFiles, parseConfig, parseSceneStructure, planWorkspacePull, portableRuntimeWarning, pullScene, pullWorkspace, readConfigFile, readDevkitVersion, remapErrorStack, resolveConfig, resolveExampleScenePath, resolveRuntimeTypesSourceFile, resolveSkillsSourceDir, resolveSnapshotUrl, resolveWorkspaceAssetPath, saveSceneJson, syncSkills, toConfigScenes, typesMissingHint, uploadDirectory, validateConfigShape, workspacePullHasConflicts, workspacePullPendingWrites, writeConfigFile, writeConfigScenes };