@allbluecn/kernel 0.10.0 → 0.10.1

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/bin.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { $ as dumpModules, et as generateAssemblyCode, it as resolvePluginOrder, nt as parseProfileImports, tt as generateAssemblyFiles } from "./src-CKvw-8uC.js";
2
+ import { $ as dumpModules, at as resolvePluginOrder, et as generateAssemblyCode, rt as parseProfileImports, tt as generateAssemblyFiles } from "./src-Bo9e8qon.js";
3
3
  import { parseArgs } from "node:util";
4
4
  import { pathToFileURL } from "node:url";
5
5
  import { dirname, relative, resolve } from "node:path";
@@ -86,10 +86,68 @@ async function main() {
86
86
  return;
87
87
  }
88
88
  }
89
+ const IDENTIFIER_RE = /^[A-Za-z_$][\w$]*$/;
90
+ /**
91
+ * 从 profile 源码中提取 plugins 数组元素的 default import 标识符。
92
+ *
93
+ * 用括号配平扫描替代正则(旧正则 `[^\]]*` 无法处理元素内嵌套数组/对象、
94
+ * 注释、含 `]` 的字面量),支持任意嵌套与跨行写法;字符串与注释内容跳过。
95
+ * 非纯标识符元素(spread、变量引用、成员访问)无法对应 default import,
96
+ * 收集时跳过并告警——错误在装配早期显式暴露,而非延后到
97
+ * resolveImportSpecifiers 以「找不到标识符」的失真信息报错。
98
+ */
89
99
  function extractPluginLocalNames(source) {
90
- const match = source.match(/plugins:\s*\[([^\]]*)\]/s);
91
- if (!match) return [];
92
- return match[1].split(",").map((s) => s.trim()).filter(Boolean);
100
+ const start = source.search(/plugins\s*:\s*\[/);
101
+ if (start === -1) {
102
+ console.warn("未能从 profile 源码解析 plugins 数组(约定写法:plugins: [pluginA, pluginB]),按空数组处理");
103
+ return [];
104
+ }
105
+ const arrayStart = source.indexOf("[", start);
106
+ let depth = 0;
107
+ let inString = null;
108
+ const names = [];
109
+ let current = "";
110
+ for (let i = arrayStart; i < source.length; i++) {
111
+ const ch = source[i];
112
+ if (inString) {
113
+ if (ch === "\\") i++;
114
+ else if (ch === inString) inString = null;
115
+ continue;
116
+ }
117
+ if (ch === "\"" || ch === "'" || ch === "`") {
118
+ inString = ch;
119
+ continue;
120
+ }
121
+ if (ch === "/" && source[i + 1] === "/") {
122
+ while (i < source.length && source[i] !== "\n") i++;
123
+ continue;
124
+ }
125
+ if (ch === "/" && source[i + 1] === "*") {
126
+ i = source.indexOf("*/", i + 2);
127
+ if (i === -1) break;
128
+ i++;
129
+ continue;
130
+ }
131
+ if (ch === "[" || ch === "{" || ch === "(") depth++;
132
+ if (ch === "]" || ch === "}" || ch === ")") {
133
+ depth--;
134
+ if (depth === 0) break;
135
+ }
136
+ if (ch === "," && depth === 1) {
137
+ addName(names, current);
138
+ current = "";
139
+ continue;
140
+ }
141
+ current += depth >= 1 ? ch : "";
142
+ }
143
+ addName(names, current);
144
+ return names;
145
+ }
146
+ function addName(names, raw) {
147
+ const entry = raw.trim();
148
+ if (!entry) return;
149
+ if (IDENTIFIER_RE.test(entry)) names.push(entry);
150
+ else console.warn(`plugins 数组元素 ${JSON.stringify(entry)} 不是标识符(不支持 spread / 变量引用 / 表达式),已跳过`);
93
151
  }
94
152
  async function writeAssemblyFiles(appDir, assembly) {
95
153
  const { writeFile, readFile, unlink, mkdir } = await import("node:fs/promises");
@@ -102,7 +160,13 @@ async function writeAssemblyFiles(appDir, assembly) {
102
160
  await writeFile(join(pluginsDir, "ui.gen.ts"), assembly.uiGen + "\n");
103
161
  const manifestPath = join(pluginsDir, ".gen-manifest.json");
104
162
  const oldManifest = await readFile(manifestPath, "utf8").catch(() => null);
105
- const oldFiles = oldManifest ? JSON.parse(oldManifest).routeFiles : [];
163
+ let oldFiles = [];
164
+ if (oldManifest) try {
165
+ const parsed = JSON.parse(oldManifest);
166
+ oldFiles = Array.isArray(parsed.routeFiles) ? parsed.routeFiles.filter((f) => typeof f === "string") : [];
167
+ } catch {
168
+ console.warn(`旧 gen-manifest 损坏(${manifestPath}),已忽略并重新生成`);
169
+ }
106
170
  const newFiles = [...assembly.routeFiles.keys()];
107
171
  for (const f of oldFiles) if (!newFiles.includes(f)) await unlink(join(appDir, f)).catch(() => {});
108
172
  for (const [file, content] of assembly.routeFiles.entries()) {
@@ -7,10 +7,22 @@ const ALGO = "aes-256-gcm";
7
7
  const IV_BYTES = 12;
8
8
  const VERSION = "v1";
9
9
  let cachedKey = null;
10
+ let randomFallbackWarned = false;
11
+ function resolveSecret() {
12
+ const secret = process.env.AUTH_SECRET;
13
+ if (secret) return secret;
14
+ if (process.env.DEPLOY_TARGET === "desktop") {
15
+ if (!randomFallbackWarned) {
16
+ randomFallbackWarned = true;
17
+ console.warn("[kernel/crypto] AUTH_SECRET 未设置:已派生进程级随机密钥(仅限桌面端;重启后历史密文将无法解密)");
18
+ }
19
+ return randomBytes(32).toString("base64url");
20
+ }
21
+ throw new Error("[kernel/crypto] 缺少 AUTH_SECRET 环境变量:拒绝使用可预测密钥加密敏感数据。生产/开发部署必须显式配置 AUTH_SECRET;仅桌面端可设 DEPLOY_TARGET=desktop 启用进程级随机密钥。");
22
+ }
10
23
  function deriveKey() {
11
24
  if (cachedKey) return cachedKey;
12
- const secret = process.env.AUTH_SECRET ?? "dev-only-secret";
13
- cachedKey = pbkdf2Sync(secret, KDF_SALT, KDF_ITERATIONS, KEY_BYTES, "sha256");
25
+ cachedKey = pbkdf2Sync(resolveSecret(), KDF_SALT, KDF_ITERATIONS, KEY_BYTES, "sha256");
14
26
  return cachedKey;
15
27
  }
16
28
  /** 格式:v1.<iv-b64url>.<cipher-b64url>.<tag-b64url> */
@@ -23,10 +35,11 @@ function encryptSecret(plain) {
23
35
  }
24
36
  function decryptSecret(payload) {
25
37
  if (!payload) return null;
38
+ const key = deriveKey();
26
39
  try {
27
40
  const [v, ivS, dataS, tagS] = payload.split(".");
28
41
  if (v !== VERSION || !ivS || !dataS || !tagS) return null;
29
- const decipher = createDecipheriv(ALGO, deriveKey(), Buffer.from(ivS, "base64url"));
42
+ const decipher = createDecipheriv(ALGO, key, Buffer.from(ivS, "base64url"));
30
43
  decipher.setAuthTag(Buffer.from(tagS, "base64url"));
31
44
  return Buffer.concat([decipher.update(Buffer.from(dataS, "base64url")), decipher.final()]).toString("utf8");
32
45
  } catch {
package/dist/index.d.ts CHANGED
@@ -398,7 +398,7 @@ interface AnalyticsService {
398
398
  }
399
399
  //#endregion
400
400
  //#region src/pro-contract/global-search.d.ts
401
- interface SearchResult$1 {
401
+ interface SearchResult {
402
402
  id: string;
403
403
  type: 'document' | 'project' | 'story' | 'comment' | 'user' | 'tag';
404
404
  title: string;
@@ -411,13 +411,13 @@ interface SearchResult$1 {
411
411
  interface SearchParams {
412
412
  query: string;
413
413
  workspaceId?: string | null;
414
- types?: Array<SearchResult$1['type']>;
414
+ types?: Array<SearchResult['type']>;
415
415
  limit?: number;
416
416
  offset?: number;
417
417
  }
418
418
  interface GlobalSearchService {
419
419
  search(params: SearchParams): Promise<{
420
- results: SearchResult$1[];
420
+ results: SearchResult[];
421
421
  total: number;
422
422
  }>;
423
423
  index(documentId: string, content: string, metadata: Record<string, unknown>): Promise<void>;
@@ -463,7 +463,12 @@ interface ComplianceService {
463
463
  //#endregion
464
464
  //#region src/pro-contract/module.d.ts
465
465
  type ProEdition = 'oss' | 'pro';
466
- type ProFeature = 'billing' | 'hostedAi' | 'sso' | 'audit' | 'permissions' | 'license' | 'versionHistory' | 'automation' | 'templates' | 'analytics' | 'globalSearch' | 'compliance';
466
+ /**
467
+ * Pro 功能键单一来源(generate-assembly 的 implementedModules 生成亦消费此常量)。
468
+ * 新增 feature 只改这里;ProFeature 联合类型由本数组派生,杜绝双维护漂移。
469
+ */
470
+ declare const PRO_FEATURES: readonly ['billing', 'hostedAi', 'sso', 'audit', 'permissions', 'license', 'versionHistory', 'automation', 'templates', 'analytics', 'globalSearch', 'compliance'];
471
+ type ProFeature = (typeof PRO_FEATURES)[number];
467
472
  interface ProModule {
468
473
  readonly isAvailable: boolean;
469
474
  readonly edition: ProEdition;
@@ -582,6 +587,13 @@ declare function generateAssemblyFiles(input: AssembleInput): AssemblyFiles;
582
587
  declare function dumpModules(profileId: string, resolved: ResolveResult): string;
583
588
  //#endregion
584
589
  //#region src/server-seam.d.ts
590
+ /**
591
+ * Seam 注入模式:宿主(start.ts)与 database 包各自注册实现,契约包只声明接口。
592
+ *
593
+ * ServerSeam —— 宿主注入(鉴权 / 会话 / 平台判定);
594
+ * PrismaSeam —— database 包注入(prisma 接入点,解决 shared → database → shared 循环依赖)。
595
+ * 两者同构的「模块级单例 + 注册 + 未注册抛错」逻辑由 createSeam 泛型工厂统一提供。
596
+ */
585
597
  interface HostSession {
586
598
  user?: {
587
599
  id?: string;
@@ -590,14 +602,20 @@ interface HostSession {
590
602
  } | null;
591
603
  [key: string]: unknown;
592
604
  }
605
+ /** 鉴权成功后的会话形状:注册实现(web/admin requireAuth)保证 user.id 必在,消费方免 `session.user!.id!` 断言 */
606
+ type AuthedHostSession = HostSession & {
607
+ user: {
608
+ id: string;
609
+ role?: string | null;
610
+ [key: string]: unknown;
611
+ };
612
+ };
593
613
  interface ServerSeam {
594
- requireAuth: (request?: Request) => Promise<HostSession>;
614
+ requireAuth: (request?: Request) => Promise<AuthedHostSession>;
595
615
  requireUserInDb: (userId: string) => Promise<void>;
596
616
  getCurrentSession: (request?: Request) => Promise<HostSession | null>;
597
617
  isDesktop: () => boolean;
598
618
  }
599
- declare function registerServerSeam(impl: ServerSeam): void;
600
- declare function getServerSeam(): ServerSeam;
601
619
  /**
602
620
  * PrismaSeam — 注入式 prisma 接入点
603
621
  *
@@ -610,8 +628,14 @@ interface PrismaSeam {
610
628
  create: (data: unknown) => Promise<unknown>;
611
629
  findMany: (where: unknown) => Promise<unknown[]>;
612
630
  };
631
+ /**
632
+ * ⚠ 硬约束:`sql` 必须是常量字符串(模板内不允许出现任何来源的用户输入拼接),
633
+ * 用户输入只允许通过 `...params` 占位参数传入。违反即为 SQL 注入。
634
+ */
613
635
  $queryRawUnsafe: <T = Record<string, unknown>>(sql: string, ...params: unknown[]) => Promise<T[]>;
614
636
  }
637
+ declare function registerServerSeam(impl: ServerSeam): void;
638
+ declare function getServerSeam(): ServerSeam;
615
639
  declare function registerPrismaSeam(seam: PrismaSeam): void;
616
640
  //#endregion
617
641
  //#region src/contract/constants/perf.d.ts
@@ -623,7 +647,7 @@ declare const DND_STICKY_THRESHOLD = 500;
623
647
  type AdapterKind = 'openai' | 'anthropic' | 'gemini' | 'groq' | 'grok' | 'openrouter' | 'ollama' | 'openai-compatible' | 'mistral' | 'bedrock' | 'byteplus' | 'fal' |
624
648
  /** harness 型 provider(需沙箱上下文,不走 createProviderAdapter 普通路径) */
625
649
  'harness-claude-code' | 'harness-codex' | 'harness-acp' | 'harness-opencode';
626
- type ProviderCategory = 'recommended' | 'popular' | 'local' | 'harness' | 'hosted';
650
+ type ProviderCategory = 'recommended' | 'popular' | 'local' | 'harness';
627
651
  type ModelCapability = 'text' | 'vision' | 'tools' | 'reasoning' | 'audio';
628
652
  interface AiModelMeta {
629
653
  /** 模型 ID(传给 adapter 的 model 字符串) */
@@ -681,7 +705,13 @@ interface AiProviderRow extends AiProviderMeta {
681
705
  /** 模型来源模式:平台托管 / 本地 Agent / 使用自己的 Key */
682
706
  type AiSourceMode = 'hosted' | 'local-agent' | 'byok';
683
707
  declare const AI_SOURCE_MODES: readonly ['hosted', 'local-agent', 'byok'];
684
- /** 卡片角标的预设颜色(按文案匹配),admin 也可自由输入文案 */
708
+ /**
709
+ * 卡片角标的预设颜色(按文案匹配),admin 也可自由输入文案。
710
+ *
711
+ * ⚠ 这里的类名字符串位于 npm 包 dist 内,app 侧 Tailwind v4 不会自动扫描
712
+ * node_modules——消费方 globals.css 必须显式 `@source` 指向本包 dist,
713
+ * 否则角标样式在生产构建被 tree-shake 静默丢失(不报错)。
714
+ */
685
715
  declare const PROVIDER_BADGE_STYLES: Record<string, string>;
686
716
  //#endregion
687
717
  //#region src/contract/modules/ai-providers/constants.d.ts
@@ -690,6 +720,11 @@ declare const ADAPTER_KINDS: Array<{
690
720
  label: string;
691
721
  description: string;
692
722
  }>;
723
+ /**
724
+ * 服务商分类筛选项。有意不含 'harness'(沙箱 harness 型服务商需专用上下文,
725
+ * 不进常规筛选)与 'hosted'(已从 ProviderCategory 移除,托管语义归
726
+ * AiSourceMode);若未来放开筛选,在此补全映射。
727
+ */
693
728
  declare const PROVIDER_CATEGORIES: Array<{
694
729
  value: ProviderCategory;
695
730
  label: string;
@@ -716,19 +751,36 @@ declare const MODEL_TABS: Array<{
716
751
  declare const LOBE_ICON_MAP: Record<string, string>;
717
752
  //#endregion
718
753
  //#region src/contract/modules/ai-providers/seed-data.d.ts
719
- /** 10 个最受欢迎 AI 服务商的种子数据,admin 可在其基础上增删改 */
754
+ /** 18 个 AI 服务商的种子数据(14 个常规 + 4 个 harness 沙箱型),admin 可在其基础上增删改 */
720
755
  declare const SEED_AI_PROVIDERS: AiProviderMeta[];
721
756
  //#endregion
722
- //#region src/contract/modules/ai-prompts/types.d.ts
723
- interface SystemPromptSectionDTO {
757
+ //#region src/contract/modules/ai-prompts/builtin.d.ts
758
+ interface PromptSection {
724
759
  id: string;
725
760
  order: number;
726
761
  template: string;
727
762
  }
728
- interface PromptVariableDefDTO {
763
+ interface PromptVariableDef {
729
764
  name: string;
730
765
  description: string;
731
766
  }
767
+ interface PromptDefinition {
768
+ key: string;
769
+ name: string;
770
+ description?: string;
771
+ sections: PromptSection[];
772
+ variables: PromptVariableDef[];
773
+ isProtected: boolean;
774
+ }
775
+ declare const TIPTAP_ACTION_INSTRUCTIONS: Record<string, string>;
776
+ declare const PROMPT_DEFINITIONS: PromptDefinition[];
777
+ declare function listPromptDefinitions(): PromptDefinition[];
778
+ declare function getPromptDefinition(key: string): PromptDefinition | undefined;
779
+ declare function promptDefinitionKeys(): string[];
780
+ //#endregion
781
+ //#region src/contract/modules/ai-prompts/types.d.ts
782
+ type SystemPromptSectionDTO = PromptSection;
783
+ type PromptVariableDefDTO = PromptVariableDef;
732
784
  interface SystemPromptTemplateDTO {
733
785
  id: string;
734
786
  key: string;
@@ -757,30 +809,6 @@ declare class UnknownPromptVariableError extends Error {
757
809
  }
758
810
  declare function interpolateTemplate(template: string, vars: Record<string, string>): string;
759
811
  //#endregion
760
- //#region src/contract/modules/ai-prompts/builtin.d.ts
761
- interface PromptSection {
762
- id: string;
763
- order: number;
764
- template: string;
765
- }
766
- interface PromptVariableDef {
767
- name: string;
768
- description: string;
769
- }
770
- interface PromptDefinition {
771
- key: string;
772
- name: string;
773
- description?: string;
774
- sections: PromptSection[];
775
- variables: PromptVariableDef[];
776
- isProtected: boolean;
777
- }
778
- declare const TIPTAP_ACTION_INSTRUCTIONS: Record<string, string>;
779
- declare const PROMPT_DEFINITIONS: PromptDefinition[];
780
- declare function listPromptDefinitions(): PromptDefinition[];
781
- declare function getPromptDefinition(key: string): PromptDefinition | undefined;
782
- declare function promptDefinitionKeys(): string[];
783
- //#endregion
784
812
  //#region src/contract/modules/dependencies/index.d.ts
785
813
  /** 依赖分类 */
786
814
  type DependencyCategory = 'framework' | 'ui' | 'editor' | 'ai' | 'state' | 'auth' | 'tool' | 'other';
@@ -876,7 +904,13 @@ declare const DEFAULT_WATCHED_DEPENDENCIES: DependencySeed[];
876
904
  declare function resolveIpLocation(ip: string | null | undefined): Promise<string>;
877
905
  /**
878
906
  * 从 Request 中提取客户端真实 IP
879
- * 优先级:X-Forwarded-For > X-Real-IP > CF-Connecting-IP
907
+ *
908
+ * 优先级:CF-Connecting-IP(Cloudflare 平台注入的权威头,客户端不可伪造)
909
+ * > X-Real-IP > X-Forwarded-For 末段。
910
+ *
911
+ * ⚠ 前提声明:XFF 首值可由客户端任意伪造,因此取**末段**(最靠近本服务的
912
+ * 可信代理所追加的一跳)。部署平台若自身不覆写 XFF(Vercel 会覆写),
913
+ * 末段仍可能被上游代理链污染;Cloudflare 场景以 CF-Connecting-IP 为准。
880
914
  */
881
915
  declare function getClientIp(request: Request): string | null;
882
916
  //#endregion
@@ -895,10 +929,37 @@ interface ParsedUA {
895
929
  }
896
930
  declare function parseUserAgent(ua: string | null | undefined): ParsedUA;
897
931
  /**
898
- * 将 ParsedUA 拼接为可读字符串,如 "Chrome 120 / Windows 10/11 / 桌面"
932
+ * 将 ParsedUA 拼接为可读字符串,如 "Chrome 120 / Windows 10/11 / Desktop"
933
+ * (输出为英文原文;中文文案由展示层经 paraglide 映射)
899
934
  */
900
935
  declare function formatParsedUA(parsed: ParsedUA): string;
901
936
  //#endregion
937
+ //#region src/contract/interfaces/references.d.ts
938
+ interface RefDisplay {
939
+ title: string;
940
+ status?: string;
941
+ priority?: string;
942
+ url?: string;
943
+ }
944
+ interface Reference {
945
+ id: string;
946
+ sourceModule: string;
947
+ sourceEntityId: string;
948
+ targetModule: string;
949
+ targetEntityId: string;
950
+ }
951
+ interface ResolvedRef extends Reference {
952
+ display: RefDisplay;
953
+ }
954
+ interface SearchResult$1 {
955
+ id: string;
956
+ module: string;
957
+ type: string;
958
+ title: string;
959
+ status?: string;
960
+ url?: string;
961
+ }
962
+ //#endregion
902
963
  //#region src/contract/interfaces/module.d.ts
903
964
  interface EntityDef {
904
965
  type: string;
@@ -927,12 +988,7 @@ interface AICommandDef {
927
988
  entityTypes: string[];
928
989
  handler: AICommandHandler;
929
990
  }
930
- type ReferenceDisplayFn = (type: string, data: Record<string, unknown>) => {
931
- title: string;
932
- status?: string;
933
- priority?: string;
934
- url?: string;
935
- };
991
+ type ReferenceDisplayFn = (type: string, data: Record<string, unknown>) => RefDisplay;
936
992
  interface AllBlueModule {
937
993
  id: string;
938
994
  name: string;
@@ -943,32 +999,6 @@ interface AllBlueModule {
943
999
  referenceDisplay: ReferenceDisplayFn;
944
1000
  }
945
1001
  //#endregion
946
- //#region src/contract/interfaces/references.d.ts
947
- interface RefDisplay {
948
- title: string;
949
- status?: string;
950
- priority?: string;
951
- url?: string;
952
- }
953
- interface Reference {
954
- id: string;
955
- sourceModule: string;
956
- sourceEntityId: string;
957
- targetModule: string;
958
- targetEntityId: string;
959
- }
960
- interface ResolvedRef extends Reference {
961
- display: RefDisplay;
962
- }
963
- interface SearchResult {
964
- id: string;
965
- module: string;
966
- type: string;
967
- title: string;
968
- status?: string;
969
- url?: string;
970
- }
971
- //#endregion
972
1002
  //#region src/contract/interfaces/ai.d.ts
973
1003
  interface CLIAgentInfo {
974
1004
  id: string;
@@ -991,7 +1021,8 @@ interface AiAdapter {
991
1021
  entityIds: string[];
992
1022
  userInput?: string;
993
1023
  }): AsyncGenerator<string>;
994
- getActiveAgent(): string;
1024
+ /** 当前 agent id;未选择时为 null(与 infrastructure/ai/adapter.ts 实现一致) */
1025
+ getActiveAgent(): string | null;
995
1026
  switchAgent(agentId: string): void;
996
1027
  }
997
1028
  //#endregion
@@ -1219,6 +1250,7 @@ declare function isResourceDefined(key: string): key is ResourceKey;
1219
1250
  interface DeveloperLogEntry {
1220
1251
  id: string;
1221
1252
  date: string;
1253
+ /** DB 列投影(developerLog.year,供 orderBy/分组直用),恒等于 date 的年份——改列需同步迁移 */
1222
1254
  year: string;
1223
1255
  title: string;
1224
1256
  desc: string;
@@ -1285,12 +1317,26 @@ declare function normalizeCategoryFrequencies(raw: unknown): CategoryFrequencies
1285
1317
  * 部分缺失(只有部分 key)或缺失值非布尔(类型错误)时,该 key 用默认值。
1286
1318
  */
1287
1319
  declare function normalizeEmailCategories(raw: unknown): CategoryEmailFlags;
1320
+ /**
1321
+ * 判定 now(HH:MM)是否落在勿扰窗口内(支持跨零点)。
1322
+ *
1323
+ * 畸形时间输入(空串 / 非数字,如 DB 脏数据)旧实现产出 NaN、比较恒 false、
1324
+ * DND 静默失效——现显式校验,畸形时告警一次并按「不在勿扰窗口」处理。
1325
+ */
1288
1326
  declare function isInDndWindow(prefs: Pick<NotificationPreferences, 'dndEnabled' | 'dndStart' | 'dndEnd'>, now: string): boolean;
1289
1327
  //#endregion
1290
1328
  //#region src/contract/modules/registry.d.ts
1291
1329
  declare class ModuleRegistry {
1292
1330
  private modules;
1293
- register(mod: AllBlueModule): void;
1331
+ /**
1332
+ * 注册模块。同 id 重复注册的语义:
1333
+ * - 显式 `{ overwrite: true }`:警告并覆盖(有意的替换场景);
1334
+ * - 生产环境:视为装配期配置错误直接抛出,避免「两个模块意外同 id」被静默掩盖;
1335
+ * - dev/test/HMR:警告并覆盖(模块双执行 / 热更新场景保持宽松)。
1336
+ */
1337
+ register(mod: AllBlueModule, options?: {
1338
+ overwrite?: boolean;
1339
+ }): void;
1294
1340
  getModule(id: string): AllBlueModule | undefined;
1295
1341
  getAll(): AllBlueModule[];
1296
1342
  getAICommands(): AICommandDef[];
@@ -1400,8 +1446,8 @@ interface DesignVersionWithSemver extends DesignVersionBase {
1400
1446
  minor: number;
1401
1447
  patch: number;
1402
1448
  }
1403
- declare const ICON_MAP: Record<string, React.ComponentType<{
1449
+ declare const ICON_MAP: Record<string, ComponentType<{
1404
1450
  className?: string;
1405
1451
  }>>;
1406
1452
  //#endregion
1407
- export { ADAPTER_KINDS, ADAPTER_KIND_VALUES, type AICommandContext, type AICommandDef, type AICommandHandler, type AICommandResult, AI_SOURCE_MODES, type ActivationResult, AdapterKind, type AiAdapter, AiModelMeta, AiProviderMeta, AiProviderRow, type AiQuota, AiSourceMode, type AllBlueModule, type AnalyticsQuery, type AnalyticsResult, type AnalyticsService, type AssembleInput, type AssemblyFiles, type AuditLogEntry, type AuditQuery, type AuditService, type AutomationRule, type AutomationService, type AvatarConfig, type AvatarPart, type BillingService, BillingUnavailableError, type CLIAgentInfo, type CanvasElement, CategoryEmailFlags, CategoryFrequencies, type CheckoutParams, type ComplianceJobSummary, type ComplianceService, type ComponentCategory, type ComponentSource, type CustomDashboard, DEFAULT_CATEGORIES, DEFAULT_EMAIL_CATEGORIES, DEFAULT_WATCHED_DEPENDENCIES, DEPENDENCY_CATEGORIES, DEPENDENCY_PRIORITIES, DEVICE_SIZES, DND_STICKY_THRESHOLD, DependencyCategory, DependencyPriority, DependencySeed, DependencyUsage, type Design, type DesignDetail, type DesignVersionWithPages, type DesignVersionWithSemver, type DeveloperLogEntry, type DeviceType, type DocumentTemplate, type DocumentVersion, type EditableFieldType, type EditablePropField, type EntityDef, type EntityUpdateEvent, FEATURE_KEYS, type FeatureContribution, type FeatureKey, type FeatureMeta, FeatureRegistry, type GlobalSearchService, type HostSession, type HostedAiChatParams, type HostedAiChatResult, HostedAiError, type HostedAiModel, type HostedAiService, ICON_MAP, type InvoiceInfo, LOAD_MORE_STEP, LOBE_ICON_MAP, type LicenseInfo, type LicenseIssueParams, type LicenseIssueResult, type LicenseService, type LicenseStatus, MODEL_CAPABILITY_OPTIONS, MODEL_TABS, type Middleware, ModelCapability, ModelTab, NOTIFICATION_CATEGORIES, NOTIFICATION_FREQUENCIES, NotificationCategory, NotificationFrequency, NotificationItem, NotificationListResult, NotificationPreferences, NotificationSsePayload, NotificationSseValue, OSS_BASE_FEATURES, type OutlineNode, PROMPT_DEFINITIONS, PROVIDER_BADGE_STYLES, PROVIDER_CATEGORIES, PROVIDER_CATEGORY_VALUES, type ParsedUA, type PermissionLevel, type PermissionsService, type PlanFeatures, PlanFeaturesSchema, type PlanInfo, type PluginContributions, type PluginDefinition, type PluginRouteContext, type PortalSessionParams, type PrismaContribution, type PrismaSeam, type ProEdition, type ProFeature, type ProModule, type ProServiceMap, type ProfileDefinition, PromptDefinition, PromptSection, PromptVariableDef, PromptVariableDefDTO, type PrototypeComponentConfig, ProviderCategory, type QueryFactoryMap, RESOURCE_KEYS, type RealtimeTransport, type RefDisplay, type Reference, type ReferenceDisplayFn, type ResizeDirection, type ResizeMode, type ResolveResult, type ResolvedRef, type ResourceKey, type ResourceMeta, ResourceRegistry, type ResourceSnapshot, type ResourceSnapshots, type RoleDefinition, type RouteContribution, SEED_AI_PROVIDERS, type SearchParams, type SearchResult, type SeatCheckResult, SeatsExceededError, type ServerSeam, type SettingsTabContribution, type ShapeType, type SsoProvider, type SsoService, type SubscriptionInfo, SyncDependencyResult, SystemPromptSectionDTO, SystemPromptTemplateDTO, SystemPromptVersionDTO, TIPTAP_ACTION_INSTRUCTIONS, type TemplatesService, ThirdPartyDependencyRow, type UiSlotContributions, UnknownPromptVariableError, UnreadSnapshotPayload, UpdateDependencyInput, VIRTUALIZE_THRESHOLD, type VersionHistoryService, VersionStatus, WebhookSignatureError, definePlugin, defineProfile, dumpModules, formatParsedUA, generateAssemblyCode, generateAssemblyFiles, getClientIp, getPromptDefinition, getServerSeam, interpolateTemplate, isInDndWindow, isOssFeature, isResourceDefined, listPromptDefinitions, moduleRegistry, normalizeCategoryFrequencies, normalizeEmailCategories, parseProfileImports, parseUserAgent, promptDefinitionKeys, registerPrismaSeam, registerServerSeam, resolveImportSpecifiers, resolveIpLocation, resolvePluginOrder };
1453
+ export { ADAPTER_KINDS, ADAPTER_KIND_VALUES, type AICommandContext, type AICommandDef, type AICommandHandler, type AICommandResult, AI_SOURCE_MODES, type ActivationResult, AdapterKind, type AiAdapter, AiModelMeta, AiProviderMeta, AiProviderRow, type AiQuota, AiSourceMode, type AllBlueModule, type AnalyticsQuery, type AnalyticsResult, type AnalyticsService, type AssembleInput, type AssemblyFiles, type AuditLogEntry, type AuditQuery, type AuditService, type AutomationRule, type AutomationService, type AvatarConfig, type AvatarPart, type BillingService, BillingUnavailableError, type CLIAgentInfo, type CanvasElement, CategoryEmailFlags, CategoryFrequencies, type CheckoutParams, type ComplianceJobSummary, type ComplianceService, type ComponentCategory, type ComponentSource, type CustomDashboard, DEFAULT_CATEGORIES, DEFAULT_EMAIL_CATEGORIES, DEFAULT_WATCHED_DEPENDENCIES, DEPENDENCY_CATEGORIES, DEPENDENCY_PRIORITIES, DEVICE_SIZES, DND_STICKY_THRESHOLD, DependencyCategory, DependencyPriority, DependencySeed, DependencyUsage, type Design, type DesignDetail, type DesignVersionWithPages, type DesignVersionWithSemver, type DeveloperLogEntry, type DeviceType, type DocumentTemplate, type DocumentVersion, type EditableFieldType, type EditablePropField, type EntityDef, type EntityUpdateEvent, FEATURE_KEYS, type FeatureContribution, type FeatureKey, type FeatureMeta, FeatureRegistry, type SearchResult as GlobalSearchResult, type GlobalSearchService, type HostSession, type HostedAiChatParams, type HostedAiChatResult, HostedAiError, type HostedAiModel, type HostedAiService, ICON_MAP, type InvoiceInfo, LOAD_MORE_STEP, LOBE_ICON_MAP, type LicenseInfo, type LicenseIssueParams, type LicenseIssueResult, type LicenseService, type LicenseStatus, MODEL_CAPABILITY_OPTIONS, MODEL_TABS, type Middleware, ModelCapability, ModelTab, NOTIFICATION_CATEGORIES, NOTIFICATION_FREQUENCIES, NotificationCategory, NotificationFrequency, NotificationItem, NotificationListResult, NotificationPreferences, NotificationSsePayload, NotificationSseValue, OSS_BASE_FEATURES, type OutlineNode, PROMPT_DEFINITIONS, PROVIDER_BADGE_STYLES, PROVIDER_CATEGORIES, PROVIDER_CATEGORY_VALUES, PRO_FEATURES, type ParsedUA, type PermissionLevel, type PermissionsService, type PlanFeatures, PlanFeaturesSchema, type PlanInfo, type PluginContributions, type PluginDefinition, type PluginRouteContext, type PortalSessionParams, type PrismaContribution, type PrismaSeam, type ProEdition, type ProFeature, type ProModule, type ProServiceMap, type ProfileDefinition, PromptDefinition, PromptSection, PromptVariableDef, PromptVariableDefDTO, type PrototypeComponentConfig, ProviderCategory, type QueryFactoryMap, RESOURCE_KEYS, type RealtimeTransport, type RefDisplay, type Reference, type ReferenceDisplayFn, type ResizeDirection, type ResizeMode, type ResolveResult, type ResolvedRef, type ResourceKey, type ResourceMeta, ResourceRegistry, type ResourceSnapshot, type ResourceSnapshots, type RoleDefinition, type RouteContribution, SEED_AI_PROVIDERS, type SearchParams, type SearchResult$1 as SearchResult, type SeatCheckResult, type SeatUpdateParams, SeatsExceededError, type ServerSeam, type SettingsTabContribution, type ShapeType, type SsoProvider, type SsoService, type SubscriptionInfo, SyncDependencyResult, SystemPromptSectionDTO, SystemPromptTemplateDTO, SystemPromptVersionDTO, TIPTAP_ACTION_INSTRUCTIONS, type TemplatesService, ThirdPartyDependencyRow, type UiSlotContributions, UnknownPromptVariableError, UnreadSnapshotPayload, UpdateDependencyInput, VIRTUALIZE_THRESHOLD, type VersionHistoryService, VersionStatus, WebhookSignatureError, definePlugin, defineProfile, dumpModules, formatParsedUA, generateAssemblyCode, generateAssemblyFiles, getClientIp, getPromptDefinition, getServerSeam, interpolateTemplate, isInDndWindow, isOssFeature, isResourceDefined, listPromptDefinitions, moduleRegistry, normalizeCategoryFrequencies, normalizeEmailCategories, parseProfileImports, parseUserAgent, promptDefinitionKeys, registerPrismaSeam, registerServerSeam, resolveImportSpecifiers, resolveIpLocation, resolvePluginOrder };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { $ as dumpModules, A as promptDefinitionKeys, B as PROVIDER_CATEGORY_VALUES, C as DEFAULT_WATCHED_DEPENDENCIES, D as TIPTAP_ACTION_INSTRUCTIONS, E as PROMPT_DEFINITIONS, F as ADAPTER_KIND_VALUES, G as VIRTUALIZE_THRESHOLD, H as PROVIDER_BADGE_STYLES, I as LOBE_ICON_MAP, J as registerServerSeam, K as getServerSeam, L as MODEL_CAPABILITY_OPTIONS, M as interpolateTemplate, N as SEED_AI_PROVIDERS, O as getPromptDefinition, P as ADAPTER_KINDS, Q as WebhookSignatureError, R as MODEL_TABS, S as resolveIpLocation, T as DEPENDENCY_PRIORITIES, U as DND_STICKY_THRESHOLD, V as AI_SOURCE_MODES, W as LOAD_MORE_STEP, X as BillingUnavailableError, Y as HostedAiError, Z as SeatsExceededError, _ as OSS_BASE_FEATURES, a as DEFAULT_EMAIL_CATEGORIES, at as defineProfile, b as parseUserAgent, c as normalizeEmailCategories, d as RESOURCE_KEYS, et as generateAssemblyCode, f as ResourceRegistry, g as FeatureRegistry, h as FEATURE_KEYS, i as DEFAULT_CATEGORIES, it as resolvePluginOrder, j as UnknownPromptVariableError, k as listPromptDefinitions, l as NOTIFICATION_CATEGORIES, m as PlanFeaturesSchema, n as DEVICE_SIZES, nt as parseProfileImports, o as isInDndWindow, ot as definePlugin, p as isResourceDefined, q as registerPrismaSeam, r as moduleRegistry, rt as resolveImportSpecifiers, s as normalizeCategoryFrequencies, t as ICON_MAP, tt as generateAssemblyFiles, u as NOTIFICATION_FREQUENCIES, v as isOssFeature, w as DEPENDENCY_CATEGORIES, x as getClientIp, y as formatParsedUA, z as PROVIDER_CATEGORIES } from "./src-CKvw-8uC.js";
2
- export { ADAPTER_KINDS, ADAPTER_KIND_VALUES, AI_SOURCE_MODES, BillingUnavailableError, DEFAULT_CATEGORIES, DEFAULT_EMAIL_CATEGORIES, DEFAULT_WATCHED_DEPENDENCIES, DEPENDENCY_CATEGORIES, DEPENDENCY_PRIORITIES, DEVICE_SIZES, DND_STICKY_THRESHOLD, FEATURE_KEYS, FeatureRegistry, HostedAiError, ICON_MAP, LOAD_MORE_STEP, LOBE_ICON_MAP, MODEL_CAPABILITY_OPTIONS, MODEL_TABS, NOTIFICATION_CATEGORIES, NOTIFICATION_FREQUENCIES, OSS_BASE_FEATURES, PROMPT_DEFINITIONS, PROVIDER_BADGE_STYLES, PROVIDER_CATEGORIES, PROVIDER_CATEGORY_VALUES, PlanFeaturesSchema, RESOURCE_KEYS, ResourceRegistry, SEED_AI_PROVIDERS, SeatsExceededError, TIPTAP_ACTION_INSTRUCTIONS, UnknownPromptVariableError, VIRTUALIZE_THRESHOLD, WebhookSignatureError, definePlugin, defineProfile, dumpModules, formatParsedUA, generateAssemblyCode, generateAssemblyFiles, getClientIp, getPromptDefinition, getServerSeam, interpolateTemplate, isInDndWindow, isOssFeature, isResourceDefined, listPromptDefinitions, moduleRegistry, normalizeCategoryFrequencies, normalizeEmailCategories, parseProfileImports, parseUserAgent, promptDefinitionKeys, registerPrismaSeam, registerServerSeam, resolveImportSpecifiers, resolveIpLocation, resolvePluginOrder };
1
+ import { $ as dumpModules, A as promptDefinitionKeys, B as PROVIDER_CATEGORY_VALUES, C as DEFAULT_WATCHED_DEPENDENCIES, D as TIPTAP_ACTION_INSTRUCTIONS, E as PROMPT_DEFINITIONS, F as ADAPTER_KIND_VALUES, G as VIRTUALIZE_THRESHOLD, H as PROVIDER_BADGE_STYLES, I as LOBE_ICON_MAP, J as registerServerSeam, K as getServerSeam, L as MODEL_CAPABILITY_OPTIONS, M as interpolateTemplate, N as SEED_AI_PROVIDERS, O as getPromptDefinition, P as ADAPTER_KINDS, Q as WebhookSignatureError, R as MODEL_TABS, S as resolveIpLocation, T as DEPENDENCY_PRIORITIES, U as DND_STICKY_THRESHOLD, V as AI_SOURCE_MODES, W as LOAD_MORE_STEP, X as BillingUnavailableError, Y as HostedAiError, Z as SeatsExceededError, _ as OSS_BASE_FEATURES, a as DEFAULT_EMAIL_CATEGORIES, at as resolvePluginOrder, b as parseUserAgent, c as normalizeEmailCategories, d as RESOURCE_KEYS, et as generateAssemblyCode, f as ResourceRegistry, g as FeatureRegistry, h as FEATURE_KEYS, i as DEFAULT_CATEGORIES, it as resolveImportSpecifiers, j as UnknownPromptVariableError, k as listPromptDefinitions, l as NOTIFICATION_CATEGORIES, m as PlanFeaturesSchema, n as DEVICE_SIZES, nt as PRO_FEATURES, o as isInDndWindow, ot as defineProfile, p as isResourceDefined, q as registerPrismaSeam, r as moduleRegistry, rt as parseProfileImports, s as normalizeCategoryFrequencies, st as definePlugin, t as ICON_MAP, tt as generateAssemblyFiles, u as NOTIFICATION_FREQUENCIES, v as isOssFeature, w as DEPENDENCY_CATEGORIES, x as getClientIp, y as formatParsedUA, z as PROVIDER_CATEGORIES } from "./src-Bo9e8qon.js";
2
+ export { ADAPTER_KINDS, ADAPTER_KIND_VALUES, AI_SOURCE_MODES, BillingUnavailableError, DEFAULT_CATEGORIES, DEFAULT_EMAIL_CATEGORIES, DEFAULT_WATCHED_DEPENDENCIES, DEPENDENCY_CATEGORIES, DEPENDENCY_PRIORITIES, DEVICE_SIZES, DND_STICKY_THRESHOLD, FEATURE_KEYS, FeatureRegistry, HostedAiError, ICON_MAP, LOAD_MORE_STEP, LOBE_ICON_MAP, MODEL_CAPABILITY_OPTIONS, MODEL_TABS, NOTIFICATION_CATEGORIES, NOTIFICATION_FREQUENCIES, OSS_BASE_FEATURES, PROMPT_DEFINITIONS, PROVIDER_BADGE_STYLES, PROVIDER_CATEGORIES, PROVIDER_CATEGORY_VALUES, PRO_FEATURES, PlanFeaturesSchema, RESOURCE_KEYS, ResourceRegistry, SEED_AI_PROVIDERS, SeatsExceededError, TIPTAP_ACTION_INSTRUCTIONS, UnknownPromptVariableError, VIRTUALIZE_THRESHOLD, WebhookSignatureError, definePlugin, defineProfile, dumpModules, formatParsedUA, generateAssemblyCode, generateAssemblyFiles, getClientIp, getPromptDefinition, getServerSeam, interpolateTemplate, isInDndWindow, isOssFeature, isResourceDefined, listPromptDefinitions, moduleRegistry, normalizeCategoryFrequencies, normalizeEmailCategories, parseProfileImports, parseUserAgent, promptDefinitionKeys, registerPrismaSeam, registerServerSeam, resolveImportSpecifiers, resolveIpLocation, resolvePluginOrder };
@@ -2,9 +2,10 @@ import { z } from "zod";
2
2
  import { BadgeDollarSign, BarChart3, Bell, Brain, Building2, Calendar, CircleStar, Database, Earth, FileText, Fish, Folder, GraduationCap, HandFist, Heart, HeartHandshake, Link, LoaderPinwheel, MessageSquare, Music4, Package, PartyPopper, PencilRuler, Settings, ShoppingCart, Shrimp, Sparkles, SquareChartGantt, ToolCase, Users, VenetianMask } from "lucide-react";
3
3
  //#region src/define-plugin.ts
4
4
  const PLUGIN_ID_RE = /^@[a-z0-9-]+\/[a-z0-9-]+$/;
5
+ const SEMVER_RE = /^\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$/;
5
6
  function definePlugin(def) {
6
7
  if (!PLUGIN_ID_RE.test(def.id)) throw new Error(`插件 id 必须形如 '@scope/name'(小写),收到: ${def.id}`);
7
- if (!/^\d+\.\d+\.\d+/.test(def.version)) throw new Error(`插件 version 必须是语义化版本,收到: ${def.version}`);
8
+ if (!SEMVER_RE.test(def.version)) throw new Error(`插件 version 必须是语义化版本,收到: ${def.version}`);
8
9
  return deepFreeze(def);
9
10
  }
10
11
  function deepFreeze(value) {
@@ -71,8 +72,7 @@ function findCyclePath(cyclicIds, byId) {
71
72
  const visited = /* @__PURE__ */ new Set([start]);
72
73
  let current = start;
73
74
  while (true) {
74
- const deps = byId.get(current)?.dependencies ?? [];
75
- const next = deps.find((d) => cyclicIds.includes(d)) ?? deps[0];
75
+ const next = (byId.get(current)?.dependencies ?? []).find((d) => cyclicIds.includes(d));
76
76
  if (!next) break;
77
77
  if (next === start || visited.has(next)) {
78
78
  path.push(next);
@@ -82,7 +82,7 @@ function findCyclePath(cyclicIds, byId) {
82
82
  path.push(next);
83
83
  current = next;
84
84
  }
85
- return path;
85
+ return path.length > 1 ? path : cyclicIds;
86
86
  }
87
87
  //#endregion
88
88
  //#region src/assemble-input.ts
@@ -99,31 +99,18 @@ function resolveImportSpecifiers(input) {
99
99
  const localName = input.pluginLocalNames[index];
100
100
  if (!localName) throw new Error(`插件 ${plugin.id} 在 profile 源码中找不到对应标识符`);
101
101
  const specifier = input.imports.get(localName);
102
- if (!specifier) throw new Error(`标识符 ${localName} 没有 default import(约定:profile 中插件必须以 default import 引入)`);
102
+ if (!specifier) throw new Error(`标识符 ${localName} 没有 default import(约定:profile 中插件必须以单标识符 default import 单行引入,如 \`import tags from '@scope/tags'\`;不支持 \`import X, { y }\` / \`import * as X\` / \`import { default as X }\` / 跨行 import)`);
103
103
  byId.set(plugin.id, specifier);
104
104
  });
105
105
  return byId;
106
106
  }
107
107
  //#endregion
108
- //#region src/generate-assembly.ts
109
- function generateAssemblyCode(input) {
110
- const { profileId, profileModulePath, resolved } = input;
111
- const ids = resolved.ids.map((id) => `'${id}'`).join(", ");
112
- return [
113
- `// AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT`,
114
- `// profile: ${profileId} (validated: ${resolved.order.length} plugins)`,
115
- `// 拓扑序(被依赖者在前):${resolved.ids.join(" -> ")}`,
116
- `import type { ProfileDefinition } from '@allbluecn/kernel'`,
117
- ``,
118
- `export { default as profile } from '${profileModulePath}'`,
119
- ``,
120
- `export const pluginIds: string[] = [${ids}]`,
121
- ``,
122
- `declare const _profile: ProfileDefinition`
123
- ].join("\n");
124
- }
125
- const HEADER = "// AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT";
126
- const ALL_FEATURES = [
108
+ //#region src/pro-contract/module.ts
109
+ /**
110
+ * Pro 功能键单一来源(generate-assembly 的 implementedModules 生成亦消费此常量)。
111
+ * 新增 feature 只改这里;ProFeature 联合类型由本数组派生,杜绝双维护漂移。
112
+ */
113
+ const PRO_FEATURES = [
127
114
  "billing",
128
115
  "hostedAi",
129
116
  "sso",
@@ -137,11 +124,40 @@ const ALL_FEATURES = [
137
124
  "globalSearch",
138
125
  "compliance"
139
126
  ];
127
+ //#endregion
128
+ //#region src/generate-assembly.ts
129
+ /**
130
+ * 生成单引号字符串字面量:转义反斜杠与单引号,
131
+ * 防止 profileId / 插件 id / 模块路径 / route path 中的特殊字符污染生成代码。
132
+ */
133
+ const q = (s) => `'${s.replace(/[\\']/g, "\\$&")}'`;
134
+ /**
135
+ * route 贡献路径白名单:以 / 开头,仅允许小写字母、数字、-、_、/。
136
+ * 排除 `..`、绝对路径片段、反常字符,防止生成文件被映射到 src/routes 之外。
137
+ */
138
+ const ROUTE_PATH_RE = /^\/[a-z0-9\-_/]*$/;
139
+ function assertRoutePath(path) {
140
+ if (!ROUTE_PATH_RE.test(path)) throw new Error(`[kernel] 非法 route path: ${JSON.stringify(path)}(须以 / 开头,仅允许小写字母/数字/-/_,不得含 .. 等穿越片段)`);
141
+ }
142
+ function generateAssemblyCode(input) {
143
+ const { profileId, profileModulePath, resolved } = input;
144
+ const ids = resolved.ids.map((id) => q(id)).join(", ");
145
+ return [
146
+ `// AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT`,
147
+ `// profile: ${profileId} (validated: ${resolved.order.length} plugins)`,
148
+ `// 拓扑序(被依赖者在前):${resolved.ids.join(" -> ")}`,
149
+ ``,
150
+ `export { default as profile } from ${q(profileModulePath)}`,
151
+ ``,
152
+ `export const pluginIds: string[] = [${ids}]`
153
+ ].join("\n");
154
+ }
155
+ const HEADER = "// AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT";
140
156
  function generateAssemblyFiles(input) {
141
157
  const specifiers = resolveImportSpecifiers(input);
142
158
  const { resolved } = input;
143
159
  const importLines = resolved.order.map((p, i) => {
144
- return `import ${input.pluginLocalNames[i]} from '${specifiers.get(p.id)}'`;
160
+ return `import ${input.pluginLocalNames[i]} from ${q(specifiers.get(p.id) ?? "")}`;
145
161
  });
146
162
  const pluginList = input.pluginLocalNames.slice(0, resolved.order.length).join(", ");
147
163
  const middlewareParts = resolved.order.map((p, i) => {
@@ -155,25 +171,25 @@ function generateAssemblyFiles(input) {
155
171
  `import { defineProfile, type ProfileDefinition } from '@allbluecn/kernel'`,
156
172
  ``,
157
173
  `export const profile: ProfileDefinition = defineProfile({`,
158
- ` id: '${input.profileId}',`,
174
+ ` id: ${q(input.profileId)},`,
159
175
  ` plugins: [${pluginList}],`,
160
176
  `})`,
161
177
  ``,
162
- `export const pluginIds: string[] = [${resolved.ids.map((i) => `'${i}'`).join(", ")}]`,
178
+ `export const pluginIds: string[] = [${resolved.ids.map((i) => q(i)).join(", ")}]`,
163
179
  ``,
164
180
  `export const pluginMiddleware: unknown[] = [`,
165
181
  middlewareParts,
166
182
  `]`
167
183
  ].join("\n");
168
- const implLines = ALL_FEATURES.map((f) => {
184
+ const implLines = PRO_FEATURES.map((f) => {
169
185
  return ` ${f}: ${resolved.order.some((p) => p.contributes.services?.[f] !== void 0)},`;
170
186
  });
171
187
  const modulesGen = [
172
188
  HEADER,
173
189
  `import type { ProFeature } from '@allbluecn/kernel'`,
174
190
  ``,
175
- `export const profileId = '${input.profileId}' as const`,
176
- `export const activePluginIds = [${resolved.ids.map((i) => `'${i}'`).join(", ")}] as const`,
191
+ `export const profileId = ${q(input.profileId)} as const`,
192
+ `export const activePluginIds = [${resolved.ids.map((i) => q(i)).join(", ")}] as const`,
177
193
  `export type ActivePluginId = (typeof activePluginIds)[number]`,
178
194
  ``,
179
195
  `export const implementedModules: Record<ProFeature, boolean> = {`,
@@ -190,16 +206,17 @@ function generateAssemblyFiles(input) {
190
206
  const spec = specifiers.get(p.id);
191
207
  const slots = p.contributes.uiSlots;
192
208
  if (!slots) continue;
209
+ const uiSpec = q(`${spec}/ui`);
193
210
  for (const [key] of Object.entries(slots.navItems ?? {})) {
194
- uiImports.push(`import { ${key} } from '${spec}/ui'`);
211
+ uiImports.push(`import { ${key} } from ${uiSpec}`);
195
212
  navItems.push(key);
196
213
  }
197
214
  if (slots.settingsTabs?.length) {
198
- uiImports.push(`import { ${local}SettingsTabs } from '${spec}/ui'`);
215
+ uiImports.push(`import { ${local}SettingsTabs } from ${uiSpec}`);
199
216
  settingsTabs.push(`...${local}SettingsTabs`);
200
217
  }
201
218
  for (const [key] of Object.entries(slots.dashboardWidgets ?? {})) {
202
- uiImports.push(`import { ${key} } from '${spec}/ui'`);
219
+ uiImports.push(`import { ${key} } from ${uiSpec}`);
203
220
  widgets.push(key);
204
221
  }
205
222
  }
@@ -218,6 +235,7 @@ function generateAssemblyFiles(input) {
218
235
  const p = resolved.order[i];
219
236
  const spec = specifiers.get(p.id);
220
237
  p.contributes.routes?.forEach((r, j) => {
238
+ assertRoutePath(r.path);
221
239
  const file = routeContributionToFile(r.path);
222
240
  const varName = `${input.pluginLocalNames[i]}_route_${j}`;
223
241
  const routePath = r.path.endsWith("/") ? r.path.slice(0, -1) : r.path;
@@ -225,9 +243,9 @@ function generateAssemblyFiles(input) {
225
243
  HEADER,
226
244
  `import { createFileRoute } from '@tanstack/react-router'`,
227
245
  ...r.beforeLoad || r.loader ? [`import type { PluginRouteContext } from '@allbluecn/kernel'`] : [],
228
- `import { ${varName} } from '${spec}/routes'`,
246
+ `import { ${varName} } from ${q(`${spec}/routes`)}`,
229
247
  ``,
230
- `export const Route = createFileRoute('${routePath}')({`,
248
+ `export const Route = createFileRoute(${q(routePath)})({`,
231
249
  ...r.beforeLoad ? [` beforeLoad: ((ctx: PluginRouteContext) => ${varName}.beforeLoad(ctx)) as any,`] : [],
232
250
  ...r.loader ? [` loader: ((ctx: PluginRouteContext) => ${varName}.loader(ctx)) as any,`] : [],
233
251
  ...r.validateSearch ? [` validateSearch: ${varName}.validateSearch as any,`] : [],
@@ -295,27 +313,43 @@ var SeatsExceededError = class SeatsExceededError extends Error {
295
313
  };
296
314
  //#endregion
297
315
  //#region src/pro-contract/hosted-ai.ts
298
- var HostedAiError = class extends Error {
316
+ var HostedAiError = class HostedAiError extends Error {
299
317
  code;
300
318
  details;
301
319
  constructor(code, message, details) {
302
- super(message);
320
+ super(message, details?.cause !== void 0 ? { cause: details.cause } : void 0);
303
321
  this.code = code;
304
322
  this.details = details;
305
323
  this.name = "HostedAiError";
324
+ Object.setPrototypeOf(this, HostedAiError.prototype);
306
325
  }
307
326
  };
308
327
  //#endregion
309
328
  //#region src/server-seam.ts
310
- let seam = null;
329
+ /** 「模块级单例 + 注册 + 未注册抛错」泛型工厂:新增 seam 时复用,避免复制三件套。 */
330
+ function createSeam(notRegisteredMessage) {
331
+ let impl = null;
332
+ return {
333
+ register: (value) => {
334
+ impl = value;
335
+ },
336
+ get: () => {
337
+ if (!impl) throw new Error(notRegisteredMessage);
338
+ return impl;
339
+ }
340
+ };
341
+ }
342
+ const serverSeam = createSeam("ServerSeam 未注册:宿主需在 start.ts 中调用 registerServerSeam()");
311
343
  function registerServerSeam(impl) {
312
- seam = impl;
344
+ serverSeam.register(impl);
313
345
  }
314
346
  function getServerSeam() {
315
- if (!seam) throw new Error("ServerSeam 未注册:宿主需在 start.ts 中调用 registerServerSeam()");
316
- return seam;
347
+ return serverSeam.get();
348
+ }
349
+ const prismaSeam = createSeam("[@allbluecn/kernel] PrismaSeam not registered. Call registerPrismaSeam(prisma) before using reference engine.");
350
+ function registerPrismaSeam(seam) {
351
+ prismaSeam.register(seam);
317
352
  }
318
- function registerPrismaSeam(seam) {}
319
353
  //#endregion
320
354
  //#region src/contract/constants/perf.ts
321
355
  const VIRTUALIZE_THRESHOLD = 250;
@@ -328,7 +362,13 @@ const AI_SOURCE_MODES = [
328
362
  "local-agent",
329
363
  "byok"
330
364
  ];
331
- /** 卡片角标的预设颜色(按文案匹配),admin 也可自由输入文案 */
365
+ /**
366
+ * 卡片角标的预设颜色(按文案匹配),admin 也可自由输入文案。
367
+ *
368
+ * ⚠ 这里的类名字符串位于 npm 包 dist 内,app 侧 Tailwind v4 不会自动扫描
369
+ * node_modules——消费方 globals.css 必须显式 `@source` 指向本包 dist,
370
+ * 否则角标样式在生产构建被 tree-shake 静默丢失(不报错)。
371
+ */
332
372
  const PROVIDER_BADGE_STYLES = {
333
373
  推荐: "bg-primary/10 text-primary border-primary/30",
334
374
  热门: "bg-orange-500/10 text-orange-600 dark:text-orange-400 border-orange-500/30",
@@ -400,6 +440,11 @@ const ADAPTER_KINDS = [
400
440
  description: "fal.ai 聚合平台,image / video / audio / speech"
401
441
  }
402
442
  ];
443
+ /**
444
+ * 服务商分类筛选项。有意不含 'harness'(沙箱 harness 型服务商需专用上下文,
445
+ * 不进常规筛选)与 'hosted'(已从 ProviderCategory 移除,托管语义归
446
+ * AiSourceMode);若未来放开筛选,在此补全映射。
447
+ */
403
448
  const PROVIDER_CATEGORIES = [
404
449
  {
405
450
  value: "recommended",
@@ -453,7 +498,7 @@ const MODEL_TABS = [
453
498
  },
454
499
  {
455
500
  value: "tools",
456
- label: "对话"
501
+ label: "工具"
457
502
  },
458
503
  {
459
504
  value: "vision",
@@ -489,7 +534,7 @@ const LOBE_ICON_MAP = {
489
534
  };
490
535
  //#endregion
491
536
  //#region src/contract/modules/ai-providers/seed-data.ts
492
- /** 10 个最受欢迎 AI 服务商的种子数据,admin 可在其基础上增删改 */
537
+ /** 18 个 AI 服务商的种子数据(14 个常规 + 4 个 harness 沙箱型),admin 可在其基础上增删改 */
493
538
  const SEED_AI_PROVIDERS = [
494
539
  {
495
540
  providerId: "openai",
@@ -1545,7 +1590,7 @@ const PROMPT_DEFINITIONS = [
1545
1590
  1. 每行输出一个独立的 JSON 对象,行与行以换行分隔;不要输出 markdown 代码块标记,不要输出任何解释文字
1546
1591
  2. 每行只能是以下四种操作之一:
1547
1592
  {"op":"frame","node":{"name":"画板名","x":0,"y":0,"width":375,"height":812}}
1548
- {"op":"nodes","nodes":[{...},{"..."}]}
1593
+ {"op":"nodes","nodes":[{...},{...}]}
1549
1594
  {"op":"replace","removeIds":["节点id"],"nodes":[{...}]}
1550
1595
  {"op":"done","message":"给用户的中文完成说明"}
1551
1596
  3. 节点结构必须符合下方 JSON Schema;节点一律不含 parentId 字段,禁止输出 parentId(节点归属由服务端按「最近一个 frame 操作」回填)
@@ -2038,7 +2083,7 @@ const DEPENDENCY_CATEGORIES = [
2038
2083
  {
2039
2084
  value: "ui",
2040
2085
  label: "UI 组件",
2041
- description: "radix / motion / lucide / tailwind 等界面库"
2086
+ description: "Base UI / radix / motion / lucide / tailwind 等界面库"
2042
2087
  },
2043
2088
  {
2044
2089
  value: "editor",
@@ -2048,7 +2093,7 @@ const DEPENDENCY_CATEGORIES = [
2048
2093
  {
2049
2094
  value: "ai",
2050
2095
  label: "AI 能力",
2051
- description: "@tanstack/ai / openai 等 LLM 集成"
2096
+ description: "@tanstack/ai 及其 provider 适配器等 LLM 集成"
2052
2097
  },
2053
2098
  {
2054
2099
  value: "state",
@@ -2063,7 +2108,7 @@ const DEPENDENCY_CATEGORIES = [
2063
2108
  {
2064
2109
  value: "tool",
2065
2110
  label: "工具库",
2066
- description: "zod / nanoid / i18next 等通用工具"
2111
+ description: "zod / nanoid / paraglide 等通用工具"
2067
2112
  },
2068
2113
  {
2069
2114
  value: "other",
@@ -2241,18 +2286,26 @@ const DEFAULT_WATCHED_DEPENDENCIES = [
2241
2286
  {
2242
2287
  name: "openai",
2243
2288
  displayName: "OpenAI SDK",
2244
- description: "OpenAI 官方 SDK,本项目用于 embedding 生成",
2289
+ description: "OpenAI 官方 SDK(项目 LLM 链路已统一走 @tanstack/ai 适配器,本包保留关注)",
2245
2290
  homepage: "https://openai.com",
2246
2291
  category: "ai",
2247
- priority: "normal"
2292
+ priority: "low"
2293
+ },
2294
+ {
2295
+ name: "@base-ui/react",
2296
+ displayName: "Base UI",
2297
+ description: "无样式可访问组件库(shadcn radix-nova 底座),项目 UI 基座",
2298
+ homepage: "https://base-ui.com",
2299
+ category: "ui",
2300
+ priority: "high"
2248
2301
  },
2249
2302
  {
2250
2303
  name: "radix-ui",
2251
2304
  displayName: "Radix UI",
2252
- description: "无样式可访问组件库统一入口(dialog/menu 等)",
2305
+ description: "无样式可访问组件库统一入口(遗留:TipTap ui-primitive / magicui 仍在用,逐步迁移 Base UI)",
2253
2306
  homepage: "https://radix-ui.com",
2254
2307
  category: "ui",
2255
- priority: "high"
2308
+ priority: "normal"
2256
2309
  },
2257
2310
  {
2258
2311
  name: "motion",
@@ -2294,14 +2347,6 @@ const DEFAULT_WATCHED_DEPENDENCIES = [
2294
2347
  category: "ui",
2295
2348
  priority: "normal"
2296
2349
  },
2297
- {
2298
- name: "sonner",
2299
- displayName: "Sonner",
2300
- description: "Toast 通知组件,项目消息提示",
2301
- homepage: "https://sonner.emilkowal.ski",
2302
- category: "ui",
2303
- priority: "normal"
2304
- },
2305
2350
  {
2306
2351
  name: "@tanstack/react-query",
2307
2352
  displayName: "TanStack Query",
@@ -2327,20 +2372,12 @@ const DEFAULT_WATCHED_DEPENDENCIES = [
2327
2372
  priority: "high"
2328
2373
  },
2329
2374
  {
2330
- name: "i18next",
2331
- displayName: "i18next",
2332
- description: "国际化框架,多语言文案管理",
2333
- homepage: "https://www.i18next.com",
2334
- category: "tool",
2335
- priority: "normal"
2336
- },
2337
- {
2338
- name: "react-i18next",
2339
- displayName: "React i18next",
2340
- description: "i18next 的 React 绑定",
2341
- homepage: "https://react.i18next.com",
2375
+ name: "@inlang/paraglide-js",
2376
+ displayName: "Paraglide JS",
2377
+ description: "编译期 i18n 框架,类型安全的多语言文案(项目 i18n 方案)",
2378
+ homepage: "https://inlang.com/m/gerre34r/library-inlang-paraglideJs",
2342
2379
  category: "tool",
2343
- priority: "normal"
2380
+ priority: "high"
2344
2381
  },
2345
2382
  {
2346
2383
  name: "nanoid",
@@ -2364,25 +2401,30 @@ const DEFAULT_WATCHED_DEPENDENCIES = [
2364
2401
  /**
2365
2402
  * IP 地理位置查询工具(服务端专用)
2366
2403
  *
2367
- * - 开发环境 / 内网 IP:返回「本地」
2368
- * - 生产环境:使用 ip-api.com 免费查询(中文,每分钟 45 请求限制)
2369
- * 失败时返回「未知」,不阻塞登录流程
2404
+ * - 内网/保留段 IP:返回「Local」
2405
+ * - 公网 IP:使用 ipwho.is 免费 HTTPS 查询(无 Key,返回英文地名),
2406
+ * 失败时返回「Unknown」,不阻塞登录流程
2407
+ * - 弃用 ip-api.com 免费档:其免费端点不支持 HTTPS(明文外发用户 IP,
2408
+ * 且响应可被中间人篡改污染审计数据),2026-10 审计后切换
2370
2409
  */
2371
- const PRIVATE_IP_PATTERNS = /^(127\.|10\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.|::1$|fc00:|fd00:|fe80:|169\.254\.|localhost)/i;
2410
+ const PRIVATE_IP_PATTERNS = /^(127\.|10\.|192\.168\.|172\.(1[6-9]|2\d|3[01])\.|169\.254\.|100\.(6[4-9]|[7-9]\d|1[01]\d|12[0-7])\.|0\.|198\.1[89]\.|2(2[4-9]|3\d)\.|2[45]\d\.)/;
2411
+ const PRIVATE_IPV6_PATTERNS = /^(::1$|f[cd][0-9a-f]{2}:|fe80:|::ffff:|localhost)/i;
2412
+ function isPrivateIp(ip) {
2413
+ const mapped = ip.match(/^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/i);
2414
+ if (mapped) return PRIVATE_IP_PATTERNS.test(mapped[1]);
2415
+ return PRIVATE_IP_PATTERNS.test(ip) || PRIVATE_IPV6_PATTERNS.test(ip);
2416
+ }
2372
2417
  async function resolveIpLocation(ip) {
2373
2418
  if (!ip) return "Unknown";
2374
- if (PRIVATE_IP_PATTERNS.test(ip)) return "Local";
2419
+ if (isPrivateIp(ip)) return "Local";
2375
2420
  try {
2376
- const controller = new AbortController();
2377
- const timeout = setTimeout(() => controller.abort(), 3e3);
2378
- const res = await fetch(`http://ip-api.com/json/${encodeURIComponent(ip)}?fields=status,country,regionName,city&lang=zh-CN`, { signal: controller.signal });
2379
- clearTimeout(timeout);
2421
+ const res = await fetch(`https://ipwho.is/${encodeURIComponent(ip)}`, { signal: AbortSignal.timeout(3e3) });
2380
2422
  if (!res.ok) return "Unknown";
2381
2423
  const data = await res.json();
2382
- if (data.status !== "success") return "Unknown";
2424
+ if (data.success !== true) return "Unknown";
2383
2425
  const parts = [
2384
2426
  data.city,
2385
- data.regionName,
2427
+ data.region,
2386
2428
  data.country
2387
2429
  ].filter(Boolean);
2388
2430
  return parts.length > 0 ? parts.join(", ") : "Unknown";
@@ -2392,18 +2434,25 @@ async function resolveIpLocation(ip) {
2392
2434
  }
2393
2435
  /**
2394
2436
  * 从 Request 中提取客户端真实 IP
2395
- * 优先级:X-Forwarded-For > X-Real-IP > CF-Connecting-IP
2437
+ *
2438
+ * 优先级:CF-Connecting-IP(Cloudflare 平台注入的权威头,客户端不可伪造)
2439
+ * > X-Real-IP > X-Forwarded-For 末段。
2440
+ *
2441
+ * ⚠ 前提声明:XFF 首值可由客户端任意伪造,因此取**末段**(最靠近本服务的
2442
+ * 可信代理所追加的一跳)。部署平台若自身不覆写 XFF(Vercel 会覆写),
2443
+ * 末段仍可能被上游代理链污染;Cloudflare 场景以 CF-Connecting-IP 为准。
2396
2444
  */
2397
2445
  function getClientIp(request) {
2446
+ const cfip = request.headers.get("cf-connecting-ip");
2447
+ if (cfip) return cfip.trim();
2448
+ const xri = request.headers.get("x-real-ip");
2449
+ if (xri) return xri.trim();
2398
2450
  const xff = request.headers.get("x-forwarded-for");
2399
2451
  if (xff) {
2400
- const first = xff.split(",")[0]?.trim();
2401
- if (first) return first;
2452
+ const segments = xff.split(",").map((s) => s.trim()).filter(Boolean);
2453
+ const last = segments[segments.length - 1];
2454
+ if (last) return last;
2402
2455
  }
2403
- const xri = request.headers.get("x-real-ip");
2404
- if (xri) return xri.trim();
2405
- const cfip = request.headers.get("cf-connecting-ip");
2406
- if (cfip) return cfip.trim();
2407
2456
  return null;
2408
2457
  }
2409
2458
  //#endregion
@@ -2465,7 +2514,8 @@ function parseUserAgent(ua) {
2465
2514
  };
2466
2515
  }
2467
2516
  /**
2468
- * 将 ParsedUA 拼接为可读字符串,如 "Chrome 120 / Windows 10/11 / 桌面"
2517
+ * 将 ParsedUA 拼接为可读字符串,如 "Chrome 120 / Windows 10/11 / Desktop"
2518
+ * (输出为英文原文;中文文案由展示层经 paraglide 映射)
2469
2519
  */
2470
2520
  function formatParsedUA(parsed) {
2471
2521
  return [
@@ -2710,14 +2760,29 @@ function normalizeEmailCategories(raw) {
2710
2760
  }
2711
2761
  return result;
2712
2762
  }
2763
+ let dndMalformedWarned = false;
2764
+ /**
2765
+ * 判定 now(HH:MM)是否落在勿扰窗口内(支持跨零点)。
2766
+ *
2767
+ * 畸形时间输入(空串 / 非数字,如 DB 脏数据)旧实现产出 NaN、比较恒 false、
2768
+ * DND 静默失效——现显式校验,畸形时告警一次并按「不在勿扰窗口」处理。
2769
+ */
2713
2770
  function isInDndWindow(prefs, now) {
2714
2771
  if (!prefs.dndEnabled) return false;
2715
- const [sh, sm] = prefs.dndStart.split(":").map(Number);
2716
- const [eh, em] = prefs.dndEnd.split(":").map(Number);
2717
- const [nh, nm] = now.split(":").map(Number);
2718
- const start = sh * 60 + sm;
2719
- const end = eh * 60 + em;
2720
- const cur = nh * 60 + nm;
2772
+ const parse = (s) => {
2773
+ const [h, m] = s.split(":").map(Number);
2774
+ return Number.isFinite(h) && Number.isFinite(m) ? h * 60 + m : NaN;
2775
+ };
2776
+ const start = parse(prefs.dndStart);
2777
+ const end = parse(prefs.dndEnd);
2778
+ const cur = parse(now);
2779
+ if (Number.isNaN(start) || Number.isNaN(end) || Number.isNaN(cur)) {
2780
+ if (!dndMalformedWarned) {
2781
+ dndMalformedWarned = true;
2782
+ console.warn(`[notifications] 勿扰时段格式非法(须为 HH:MM):start=${JSON.stringify(prefs.dndStart)} end=${JSON.stringify(prefs.dndEnd)},DND 判定按不生效处理`);
2783
+ }
2784
+ return false;
2785
+ }
2721
2786
  if (start <= end) return cur >= start && cur < end;
2722
2787
  return cur >= start || cur < end;
2723
2788
  }
@@ -2725,8 +2790,18 @@ function isInDndWindow(prefs, now) {
2725
2790
  //#region src/contract/modules/registry.ts
2726
2791
  var ModuleRegistry = class {
2727
2792
  modules = /* @__PURE__ */ new Map();
2728
- register(mod) {
2729
- if (this.modules.has(mod.id)) console.warn(`[ModuleRegistry] "${mod.id}" already registered, overwriting`);
2793
+ /**
2794
+ * 注册模块。同 id 重复注册的语义:
2795
+ * - 显式 `{ overwrite: true }`:警告并覆盖(有意的替换场景);
2796
+ * - 生产环境:视为装配期配置错误直接抛出,避免「两个模块意外同 id」被静默掩盖;
2797
+ * - dev/test/HMR:警告并覆盖(模块双执行 / 热更新场景保持宽松)。
2798
+ */
2799
+ register(mod, options) {
2800
+ if (this.modules.has(mod.id)) {
2801
+ const isProd = typeof process !== "undefined" && process.env?.NODE_ENV === "production";
2802
+ if (!options?.overwrite && isProd) throw new Error(`[ModuleRegistry] "${mod.id}" already registered(同 id 模块重复注册;若确需覆盖请传 { overwrite: true })`);
2803
+ console.warn(`[ModuleRegistry] "${mod.id}" already registered, overwriting`);
2804
+ }
2730
2805
  this.modules.set(mod.id, mod);
2731
2806
  }
2732
2807
  getModule(id) {
@@ -2790,4 +2865,4 @@ const ICON_MAP = {
2790
2865
  music4: Music4
2791
2866
  };
2792
2867
  //#endregion
2793
- export { dumpModules as $, promptDefinitionKeys as A, PROVIDER_CATEGORY_VALUES as B, DEFAULT_WATCHED_DEPENDENCIES as C, TIPTAP_ACTION_INSTRUCTIONS as D, PROMPT_DEFINITIONS as E, ADAPTER_KIND_VALUES as F, VIRTUALIZE_THRESHOLD as G, PROVIDER_BADGE_STYLES as H, LOBE_ICON_MAP as I, registerServerSeam as J, getServerSeam as K, MODEL_CAPABILITY_OPTIONS as L, interpolateTemplate as M, SEED_AI_PROVIDERS as N, getPromptDefinition as O, ADAPTER_KINDS as P, WebhookSignatureError as Q, MODEL_TABS as R, resolveIpLocation as S, DEPENDENCY_PRIORITIES as T, DND_STICKY_THRESHOLD as U, AI_SOURCE_MODES as V, LOAD_MORE_STEP as W, BillingUnavailableError as X, HostedAiError as Y, SeatsExceededError as Z, OSS_BASE_FEATURES as _, DEFAULT_EMAIL_CATEGORIES as a, defineProfile as at, parseUserAgent as b, normalizeEmailCategories as c, RESOURCE_KEYS as d, generateAssemblyCode as et, ResourceRegistry as f, FeatureRegistry as g, FEATURE_KEYS as h, DEFAULT_CATEGORIES as i, resolvePluginOrder as it, UnknownPromptVariableError as j, listPromptDefinitions as k, NOTIFICATION_CATEGORIES as l, PlanFeaturesSchema as m, DEVICE_SIZES as n, parseProfileImports as nt, isInDndWindow as o, definePlugin as ot, isResourceDefined as p, registerPrismaSeam as q, moduleRegistry as r, resolveImportSpecifiers as rt, normalizeCategoryFrequencies as s, ICON_MAP as t, generateAssemblyFiles as tt, NOTIFICATION_FREQUENCIES as u, isOssFeature as v, DEPENDENCY_CATEGORIES as w, getClientIp as x, formatParsedUA as y, PROVIDER_CATEGORIES as z };
2868
+ export { dumpModules as $, promptDefinitionKeys as A, PROVIDER_CATEGORY_VALUES as B, DEFAULT_WATCHED_DEPENDENCIES as C, TIPTAP_ACTION_INSTRUCTIONS as D, PROMPT_DEFINITIONS as E, ADAPTER_KIND_VALUES as F, VIRTUALIZE_THRESHOLD as G, PROVIDER_BADGE_STYLES as H, LOBE_ICON_MAP as I, registerServerSeam as J, getServerSeam as K, MODEL_CAPABILITY_OPTIONS as L, interpolateTemplate as M, SEED_AI_PROVIDERS as N, getPromptDefinition as O, ADAPTER_KINDS as P, WebhookSignatureError as Q, MODEL_TABS as R, resolveIpLocation as S, DEPENDENCY_PRIORITIES as T, DND_STICKY_THRESHOLD as U, AI_SOURCE_MODES as V, LOAD_MORE_STEP as W, BillingUnavailableError as X, HostedAiError as Y, SeatsExceededError as Z, OSS_BASE_FEATURES as _, DEFAULT_EMAIL_CATEGORIES as a, resolvePluginOrder as at, parseUserAgent as b, normalizeEmailCategories as c, RESOURCE_KEYS as d, generateAssemblyCode as et, ResourceRegistry as f, FeatureRegistry as g, FEATURE_KEYS as h, DEFAULT_CATEGORIES as i, resolveImportSpecifiers as it, UnknownPromptVariableError as j, listPromptDefinitions as k, NOTIFICATION_CATEGORIES as l, PlanFeaturesSchema as m, DEVICE_SIZES as n, PRO_FEATURES as nt, isInDndWindow as o, defineProfile as ot, isResourceDefined as p, registerPrismaSeam as q, moduleRegistry as r, parseProfileImports as rt, normalizeCategoryFrequencies as s, definePlugin as st, ICON_MAP as t, generateAssemblyFiles as tt, NOTIFICATION_FREQUENCIES as u, isOssFeature as v, DEPENDENCY_CATEGORIES as w, getClientIp as x, formatParsedUA as y, PROVIDER_CATEGORIES as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allbluecn/kernel",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "license": "AGPL-3.0-or-later",
5
5
  "type": "module",
6
6
  "description": "AllBlue 插件协议:类型定义 + 构建期装配器(零运行时)",
@@ -56,8 +56,8 @@
56
56
  "react": "^19",
57
57
  "tsdown": "^0.22.0",
58
58
  "typescript": "^7",
59
- "vitest": "4.1.5",
60
- "zod": "^4.4.3"
59
+ "vitest": "^5.0.5",
60
+ "zod": "^4.6.7"
61
61
  },
62
62
  "dependencies": {},
63
63
  "publishConfig": {