@allbluecn/kernel 0.10.0 → 0.10.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/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, et as generateAssemblyCode, it as parseProfileImports, ot as resolvePluginOrder, rt as extractPluginLocalNames, tt as generateAssemblyFiles } from "./src-CyBj_lD7.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,11 +86,6 @@ async function main() {
86
86
  return;
87
87
  }
88
88
  }
89
- 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);
93
- }
94
89
  async function writeAssemblyFiles(appDir, assembly) {
95
90
  const { writeFile, readFile, unlink, mkdir } = await import("node:fs/promises");
96
91
  const { join } = await import("node:path");
@@ -102,7 +97,13 @@ async function writeAssemblyFiles(appDir, assembly) {
102
97
  await writeFile(join(pluginsDir, "ui.gen.ts"), assembly.uiGen + "\n");
103
98
  const manifestPath = join(pluginsDir, ".gen-manifest.json");
104
99
  const oldManifest = await readFile(manifestPath, "utf8").catch(() => null);
105
- const oldFiles = oldManifest ? JSON.parse(oldManifest).routeFiles : [];
100
+ let oldFiles = [];
101
+ if (oldManifest) try {
102
+ const parsed = JSON.parse(oldManifest);
103
+ oldFiles = Array.isArray(parsed.routeFiles) ? parsed.routeFiles.filter((f) => typeof f === "string") : [];
104
+ } catch {
105
+ console.warn(`旧 gen-manifest 损坏(${manifestPath}),已忽略并重新生成`);
106
+ }
106
107
  const newFiles = [...assembly.routeFiles.keys()];
107
108
  for (const f of oldFiles) if (!newFiles.includes(f)) await unlink(join(appDir, f)).catch(() => {});
108
109
  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 resolveImportSpecifiers, b as parseUserAgent, c as normalizeEmailCategories, ct as definePlugin, d as RESOURCE_KEYS, et as generateAssemblyCode, f as ResourceRegistry, g as FeatureRegistry, h as FEATURE_KEYS, i as DEFAULT_CATEGORIES, it as parseProfileImports, 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 resolvePluginOrder, p as isResourceDefined, q as registerPrismaSeam, r as moduleRegistry, s as normalizeCategoryFrequencies, st as defineProfile, 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-CyBj_lD7.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,10 +82,72 @@ 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
89
+ const IDENTIFIER_RE = /^[A-Za-z_$][\w$]*$/;
90
+ /**
91
+ * 从 profile 源码的 `plugins: [...]` 数组提取本地标识符(按声明顺序)。
92
+ *
93
+ * 2026-10-28 修复:原实现把数组开括号也算作元素内容,首项被解析成
94
+ * `"[\n pluginA"` 而整体跳过 —— 空 plugins(OSS profile)时只打一条
95
+ * warning 无人注意,非空 plugins(Pro saas profile)直接装配失败。
96
+ * 现从开括号后一位开始扫描,并支持行/块注释与嵌套括号。
97
+ */
98
+ function extractPluginLocalNames(source) {
99
+ const start = source.search(/plugins\s*:\s*\[/);
100
+ if (start === -1) {
101
+ console.warn("未能从 profile 源码解析 plugins 数组(约定写法:plugins: [pluginA, pluginB]),按空数组处理");
102
+ return [];
103
+ }
104
+ const arrayStart = source.indexOf("[", start);
105
+ let depth = 0;
106
+ let inString = null;
107
+ const names = [];
108
+ let current = "";
109
+ for (let i = arrayStart + 1; i < source.length; i++) {
110
+ const ch = source[i];
111
+ if (inString) {
112
+ if (ch === "\\") i++;
113
+ else if (ch === inString) inString = null;
114
+ continue;
115
+ }
116
+ if (ch === "\"" || ch === "'" || ch === "`") {
117
+ inString = ch;
118
+ continue;
119
+ }
120
+ if (ch === "/" && source[i + 1] === "/") {
121
+ while (i < source.length && source[i] !== "\n") i++;
122
+ continue;
123
+ }
124
+ if (ch === "/" && source[i + 1] === "*") {
125
+ i = source.indexOf("*/", i + 2);
126
+ if (i === -1) break;
127
+ i++;
128
+ continue;
129
+ }
130
+ if (ch === "[" || ch === "{" || ch === "(") depth++;
131
+ if (ch === "]" || ch === "}" || ch === ")") {
132
+ if (depth === 0) break;
133
+ depth--;
134
+ }
135
+ if (ch === "," && depth === 0) {
136
+ addPluginLocalName(names, current);
137
+ current = "";
138
+ continue;
139
+ }
140
+ current += ch;
141
+ }
142
+ addPluginLocalName(names, current);
143
+ return names;
144
+ }
145
+ function addPluginLocalName(names, raw) {
146
+ const entry = raw.trim();
147
+ if (!entry) return;
148
+ if (IDENTIFIER_RE.test(entry)) names.push(entry);
149
+ else console.warn(`plugins 数组元素 ${JSON.stringify(entry)} 不是标识符(不支持 spread / 变量引用 / 表达式),已跳过`);
150
+ }
89
151
  function parseProfileImports(source) {
90
152
  const map = /* @__PURE__ */ new Map();
91
153
  const re = /import\s+([A-Za-z_$][\w$]*)\s+from\s+['"]([^'"]+)['"]/g;
@@ -99,31 +161,18 @@ function resolveImportSpecifiers(input) {
99
161
  const localName = input.pluginLocalNames[index];
100
162
  if (!localName) throw new Error(`插件 ${plugin.id} 在 profile 源码中找不到对应标识符`);
101
163
  const specifier = input.imports.get(localName);
102
- if (!specifier) throw new Error(`标识符 ${localName} 没有 default import(约定:profile 中插件必须以 default import 引入)`);
164
+ 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
165
  byId.set(plugin.id, specifier);
104
166
  });
105
167
  return byId;
106
168
  }
107
169
  //#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 = [
170
+ //#region src/pro-contract/module.ts
171
+ /**
172
+ * Pro 功能键单一来源(generate-assembly 的 implementedModules 生成亦消费此常量)。
173
+ * 新增 feature 只改这里;ProFeature 联合类型由本数组派生,杜绝双维护漂移。
174
+ */
175
+ const PRO_FEATURES = [
127
176
  "billing",
128
177
  "hostedAi",
129
178
  "sso",
@@ -137,11 +186,40 @@ const ALL_FEATURES = [
137
186
  "globalSearch",
138
187
  "compliance"
139
188
  ];
189
+ //#endregion
190
+ //#region src/generate-assembly.ts
191
+ /**
192
+ * 生成单引号字符串字面量:转义反斜杠与单引号,
193
+ * 防止 profileId / 插件 id / 模块路径 / route path 中的特殊字符污染生成代码。
194
+ */
195
+ const q = (s) => `'${s.replace(/[\\']/g, "\\$&")}'`;
196
+ /**
197
+ * route 贡献路径白名单:以 / 开头,仅允许小写字母、数字、-、_、/。
198
+ * 排除 `..`、绝对路径片段、反常字符,防止生成文件被映射到 src/routes 之外。
199
+ */
200
+ const ROUTE_PATH_RE = /^\/[a-z0-9\-_/]*$/;
201
+ function assertRoutePath(path) {
202
+ if (!ROUTE_PATH_RE.test(path)) throw new Error(`[kernel] 非法 route path: ${JSON.stringify(path)}(须以 / 开头,仅允许小写字母/数字/-/_,不得含 .. 等穿越片段)`);
203
+ }
204
+ function generateAssemblyCode(input) {
205
+ const { profileId, profileModulePath, resolved } = input;
206
+ const ids = resolved.ids.map((id) => q(id)).join(", ");
207
+ return [
208
+ `// AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT`,
209
+ `// profile: ${profileId} (validated: ${resolved.order.length} plugins)`,
210
+ `// 拓扑序(被依赖者在前):${resolved.ids.join(" -> ")}`,
211
+ ``,
212
+ `export { default as profile } from ${q(profileModulePath)}`,
213
+ ``,
214
+ `export const pluginIds: string[] = [${ids}]`
215
+ ].join("\n");
216
+ }
217
+ const HEADER = "// AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT";
140
218
  function generateAssemblyFiles(input) {
141
219
  const specifiers = resolveImportSpecifiers(input);
142
220
  const { resolved } = input;
143
221
  const importLines = resolved.order.map((p, i) => {
144
- return `import ${input.pluginLocalNames[i]} from '${specifiers.get(p.id)}'`;
222
+ return `import ${input.pluginLocalNames[i]} from ${q(specifiers.get(p.id) ?? "")}`;
145
223
  });
146
224
  const pluginList = input.pluginLocalNames.slice(0, resolved.order.length).join(", ");
147
225
  const middlewareParts = resolved.order.map((p, i) => {
@@ -155,25 +233,25 @@ function generateAssemblyFiles(input) {
155
233
  `import { defineProfile, type ProfileDefinition } from '@allbluecn/kernel'`,
156
234
  ``,
157
235
  `export const profile: ProfileDefinition = defineProfile({`,
158
- ` id: '${input.profileId}',`,
236
+ ` id: ${q(input.profileId)},`,
159
237
  ` plugins: [${pluginList}],`,
160
238
  `})`,
161
239
  ``,
162
- `export const pluginIds: string[] = [${resolved.ids.map((i) => `'${i}'`).join(", ")}]`,
240
+ `export const pluginIds: string[] = [${resolved.ids.map((i) => q(i)).join(", ")}]`,
163
241
  ``,
164
242
  `export const pluginMiddleware: unknown[] = [`,
165
243
  middlewareParts,
166
244
  `]`
167
245
  ].join("\n");
168
- const implLines = ALL_FEATURES.map((f) => {
246
+ const implLines = PRO_FEATURES.map((f) => {
169
247
  return ` ${f}: ${resolved.order.some((p) => p.contributes.services?.[f] !== void 0)},`;
170
248
  });
171
249
  const modulesGen = [
172
250
  HEADER,
173
251
  `import type { ProFeature } from '@allbluecn/kernel'`,
174
252
  ``,
175
- `export const profileId = '${input.profileId}' as const`,
176
- `export const activePluginIds = [${resolved.ids.map((i) => `'${i}'`).join(", ")}] as const`,
253
+ `export const profileId = ${q(input.profileId)} as const`,
254
+ `export const activePluginIds = [${resolved.ids.map((i) => q(i)).join(", ")}] as const`,
177
255
  `export type ActivePluginId = (typeof activePluginIds)[number]`,
178
256
  ``,
179
257
  `export const implementedModules: Record<ProFeature, boolean> = {`,
@@ -190,16 +268,17 @@ function generateAssemblyFiles(input) {
190
268
  const spec = specifiers.get(p.id);
191
269
  const slots = p.contributes.uiSlots;
192
270
  if (!slots) continue;
271
+ const uiSpec = q(`${spec}/ui`);
193
272
  for (const [key] of Object.entries(slots.navItems ?? {})) {
194
- uiImports.push(`import { ${key} } from '${spec}/ui'`);
273
+ uiImports.push(`import { ${key} } from ${uiSpec}`);
195
274
  navItems.push(key);
196
275
  }
197
276
  if (slots.settingsTabs?.length) {
198
- uiImports.push(`import { ${local}SettingsTabs } from '${spec}/ui'`);
277
+ uiImports.push(`import { ${local}SettingsTabs } from ${uiSpec}`);
199
278
  settingsTabs.push(`...${local}SettingsTabs`);
200
279
  }
201
280
  for (const [key] of Object.entries(slots.dashboardWidgets ?? {})) {
202
- uiImports.push(`import { ${key} } from '${spec}/ui'`);
281
+ uiImports.push(`import { ${key} } from ${uiSpec}`);
203
282
  widgets.push(key);
204
283
  }
205
284
  }
@@ -218,6 +297,7 @@ function generateAssemblyFiles(input) {
218
297
  const p = resolved.order[i];
219
298
  const spec = specifiers.get(p.id);
220
299
  p.contributes.routes?.forEach((r, j) => {
300
+ assertRoutePath(r.path);
221
301
  const file = routeContributionToFile(r.path);
222
302
  const varName = `${input.pluginLocalNames[i]}_route_${j}`;
223
303
  const routePath = r.path.endsWith("/") ? r.path.slice(0, -1) : r.path;
@@ -225,9 +305,9 @@ function generateAssemblyFiles(input) {
225
305
  HEADER,
226
306
  `import { createFileRoute } from '@tanstack/react-router'`,
227
307
  ...r.beforeLoad || r.loader ? [`import type { PluginRouteContext } from '@allbluecn/kernel'`] : [],
228
- `import { ${varName} } from '${spec}/routes'`,
308
+ `import { ${varName} } from ${q(`${spec}/routes`)}`,
229
309
  ``,
230
- `export const Route = createFileRoute('${routePath}')({`,
310
+ `export const Route = createFileRoute(${q(routePath)})({`,
231
311
  ...r.beforeLoad ? [` beforeLoad: ((ctx: PluginRouteContext) => ${varName}.beforeLoad(ctx)) as any,`] : [],
232
312
  ...r.loader ? [` loader: ((ctx: PluginRouteContext) => ${varName}.loader(ctx)) as any,`] : [],
233
313
  ...r.validateSearch ? [` validateSearch: ${varName}.validateSearch as any,`] : [],
@@ -295,27 +375,43 @@ var SeatsExceededError = class SeatsExceededError extends Error {
295
375
  };
296
376
  //#endregion
297
377
  //#region src/pro-contract/hosted-ai.ts
298
- var HostedAiError = class extends Error {
378
+ var HostedAiError = class HostedAiError extends Error {
299
379
  code;
300
380
  details;
301
381
  constructor(code, message, details) {
302
- super(message);
382
+ super(message, details?.cause !== void 0 ? { cause: details.cause } : void 0);
303
383
  this.code = code;
304
384
  this.details = details;
305
385
  this.name = "HostedAiError";
386
+ Object.setPrototypeOf(this, HostedAiError.prototype);
306
387
  }
307
388
  };
308
389
  //#endregion
309
390
  //#region src/server-seam.ts
310
- let seam = null;
391
+ /** 「模块级单例 + 注册 + 未注册抛错」泛型工厂:新增 seam 时复用,避免复制三件套。 */
392
+ function createSeam(notRegisteredMessage) {
393
+ let impl = null;
394
+ return {
395
+ register: (value) => {
396
+ impl = value;
397
+ },
398
+ get: () => {
399
+ if (!impl) throw new Error(notRegisteredMessage);
400
+ return impl;
401
+ }
402
+ };
403
+ }
404
+ const serverSeam = createSeam("ServerSeam 未注册:宿主需在 start.ts 中调用 registerServerSeam()");
311
405
  function registerServerSeam(impl) {
312
- seam = impl;
406
+ serverSeam.register(impl);
313
407
  }
314
408
  function getServerSeam() {
315
- if (!seam) throw new Error("ServerSeam 未注册:宿主需在 start.ts 中调用 registerServerSeam()");
316
- return seam;
409
+ return serverSeam.get();
410
+ }
411
+ const prismaSeam = createSeam("[@allbluecn/kernel] PrismaSeam not registered. Call registerPrismaSeam(prisma) before using reference engine.");
412
+ function registerPrismaSeam(seam) {
413
+ prismaSeam.register(seam);
317
414
  }
318
- function registerPrismaSeam(seam) {}
319
415
  //#endregion
320
416
  //#region src/contract/constants/perf.ts
321
417
  const VIRTUALIZE_THRESHOLD = 250;
@@ -328,7 +424,13 @@ const AI_SOURCE_MODES = [
328
424
  "local-agent",
329
425
  "byok"
330
426
  ];
331
- /** 卡片角标的预设颜色(按文案匹配),admin 也可自由输入文案 */
427
+ /**
428
+ * 卡片角标的预设颜色(按文案匹配),admin 也可自由输入文案。
429
+ *
430
+ * ⚠ 这里的类名字符串位于 npm 包 dist 内,app 侧 Tailwind v4 不会自动扫描
431
+ * node_modules——消费方 globals.css 必须显式 `@source` 指向本包 dist,
432
+ * 否则角标样式在生产构建被 tree-shake 静默丢失(不报错)。
433
+ */
332
434
  const PROVIDER_BADGE_STYLES = {
333
435
  推荐: "bg-primary/10 text-primary border-primary/30",
334
436
  热门: "bg-orange-500/10 text-orange-600 dark:text-orange-400 border-orange-500/30",
@@ -400,6 +502,11 @@ const ADAPTER_KINDS = [
400
502
  description: "fal.ai 聚合平台,image / video / audio / speech"
401
503
  }
402
504
  ];
505
+ /**
506
+ * 服务商分类筛选项。有意不含 'harness'(沙箱 harness 型服务商需专用上下文,
507
+ * 不进常规筛选)与 'hosted'(已从 ProviderCategory 移除,托管语义归
508
+ * AiSourceMode);若未来放开筛选,在此补全映射。
509
+ */
403
510
  const PROVIDER_CATEGORIES = [
404
511
  {
405
512
  value: "recommended",
@@ -453,7 +560,7 @@ const MODEL_TABS = [
453
560
  },
454
561
  {
455
562
  value: "tools",
456
- label: "对话"
563
+ label: "工具"
457
564
  },
458
565
  {
459
566
  value: "vision",
@@ -489,7 +596,7 @@ const LOBE_ICON_MAP = {
489
596
  };
490
597
  //#endregion
491
598
  //#region src/contract/modules/ai-providers/seed-data.ts
492
- /** 10 个最受欢迎 AI 服务商的种子数据,admin 可在其基础上增删改 */
599
+ /** 18 个 AI 服务商的种子数据(14 个常规 + 4 个 harness 沙箱型),admin 可在其基础上增删改 */
493
600
  const SEED_AI_PROVIDERS = [
494
601
  {
495
602
  providerId: "openai",
@@ -1545,7 +1652,7 @@ const PROMPT_DEFINITIONS = [
1545
1652
  1. 每行输出一个独立的 JSON 对象,行与行以换行分隔;不要输出 markdown 代码块标记,不要输出任何解释文字
1546
1653
  2. 每行只能是以下四种操作之一:
1547
1654
  {"op":"frame","node":{"name":"画板名","x":0,"y":0,"width":375,"height":812}}
1548
- {"op":"nodes","nodes":[{...},{"..."}]}
1655
+ {"op":"nodes","nodes":[{...},{...}]}
1549
1656
  {"op":"replace","removeIds":["节点id"],"nodes":[{...}]}
1550
1657
  {"op":"done","message":"给用户的中文完成说明"}
1551
1658
  3. 节点结构必须符合下方 JSON Schema;节点一律不含 parentId 字段,禁止输出 parentId(节点归属由服务端按「最近一个 frame 操作」回填)
@@ -2038,7 +2145,7 @@ const DEPENDENCY_CATEGORIES = [
2038
2145
  {
2039
2146
  value: "ui",
2040
2147
  label: "UI 组件",
2041
- description: "radix / motion / lucide / tailwind 等界面库"
2148
+ description: "Base UI / radix / motion / lucide / tailwind 等界面库"
2042
2149
  },
2043
2150
  {
2044
2151
  value: "editor",
@@ -2048,7 +2155,7 @@ const DEPENDENCY_CATEGORIES = [
2048
2155
  {
2049
2156
  value: "ai",
2050
2157
  label: "AI 能力",
2051
- description: "@tanstack/ai / openai 等 LLM 集成"
2158
+ description: "@tanstack/ai 及其 provider 适配器等 LLM 集成"
2052
2159
  },
2053
2160
  {
2054
2161
  value: "state",
@@ -2063,7 +2170,7 @@ const DEPENDENCY_CATEGORIES = [
2063
2170
  {
2064
2171
  value: "tool",
2065
2172
  label: "工具库",
2066
- description: "zod / nanoid / i18next 等通用工具"
2173
+ description: "zod / nanoid / paraglide 等通用工具"
2067
2174
  },
2068
2175
  {
2069
2176
  value: "other",
@@ -2241,18 +2348,26 @@ const DEFAULT_WATCHED_DEPENDENCIES = [
2241
2348
  {
2242
2349
  name: "openai",
2243
2350
  displayName: "OpenAI SDK",
2244
- description: "OpenAI 官方 SDK,本项目用于 embedding 生成",
2351
+ description: "OpenAI 官方 SDK(项目 LLM 链路已统一走 @tanstack/ai 适配器,本包保留关注)",
2245
2352
  homepage: "https://openai.com",
2246
2353
  category: "ai",
2247
- priority: "normal"
2354
+ priority: "low"
2355
+ },
2356
+ {
2357
+ name: "@base-ui/react",
2358
+ displayName: "Base UI",
2359
+ description: "无样式可访问组件库(shadcn radix-nova 底座),项目 UI 基座",
2360
+ homepage: "https://base-ui.com",
2361
+ category: "ui",
2362
+ priority: "high"
2248
2363
  },
2249
2364
  {
2250
2365
  name: "radix-ui",
2251
2366
  displayName: "Radix UI",
2252
- description: "无样式可访问组件库统一入口(dialog/menu 等)",
2367
+ description: "无样式可访问组件库统一入口(遗留:TipTap ui-primitive / magicui 仍在用,逐步迁移 Base UI)",
2253
2368
  homepage: "https://radix-ui.com",
2254
2369
  category: "ui",
2255
- priority: "high"
2370
+ priority: "normal"
2256
2371
  },
2257
2372
  {
2258
2373
  name: "motion",
@@ -2294,14 +2409,6 @@ const DEFAULT_WATCHED_DEPENDENCIES = [
2294
2409
  category: "ui",
2295
2410
  priority: "normal"
2296
2411
  },
2297
- {
2298
- name: "sonner",
2299
- displayName: "Sonner",
2300
- description: "Toast 通知组件,项目消息提示",
2301
- homepage: "https://sonner.emilkowal.ski",
2302
- category: "ui",
2303
- priority: "normal"
2304
- },
2305
2412
  {
2306
2413
  name: "@tanstack/react-query",
2307
2414
  displayName: "TanStack Query",
@@ -2327,20 +2434,12 @@ const DEFAULT_WATCHED_DEPENDENCIES = [
2327
2434
  priority: "high"
2328
2435
  },
2329
2436
  {
2330
- name: "i18next",
2331
- displayName: "i18next",
2332
- description: "国际化框架,多语言文案管理",
2333
- homepage: "https://www.i18next.com",
2437
+ name: "@inlang/paraglide-js",
2438
+ displayName: "Paraglide JS",
2439
+ description: "编译期 i18n 框架,类型安全的多语言文案(项目 i18n 方案)",
2440
+ homepage: "https://inlang.com/m/gerre34r/library-inlang-paraglideJs",
2334
2441
  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",
2342
- category: "tool",
2343
- priority: "normal"
2442
+ priority: "high"
2344
2443
  },
2345
2444
  {
2346
2445
  name: "nanoid",
@@ -2364,25 +2463,30 @@ const DEFAULT_WATCHED_DEPENDENCIES = [
2364
2463
  /**
2365
2464
  * IP 地理位置查询工具(服务端专用)
2366
2465
  *
2367
- * - 开发环境 / 内网 IP:返回「本地」
2368
- * - 生产环境:使用 ip-api.com 免费查询(中文,每分钟 45 请求限制)
2369
- * 失败时返回「未知」,不阻塞登录流程
2466
+ * - 内网/保留段 IP:返回「Local」
2467
+ * - 公网 IP:使用 ipwho.is 免费 HTTPS 查询(无 Key,返回英文地名),
2468
+ * 失败时返回「Unknown」,不阻塞登录流程
2469
+ * - 弃用 ip-api.com 免费档:其免费端点不支持 HTTPS(明文外发用户 IP,
2470
+ * 且响应可被中间人篡改污染审计数据),2026-10 审计后切换
2370
2471
  */
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;
2472
+ 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\.)/;
2473
+ const PRIVATE_IPV6_PATTERNS = /^(::1$|f[cd][0-9a-f]{2}:|fe80:|::ffff:|localhost)/i;
2474
+ function isPrivateIp(ip) {
2475
+ const mapped = ip.match(/^::ffff:(\d{1,3}(?:\.\d{1,3}){3})$/i);
2476
+ if (mapped) return PRIVATE_IP_PATTERNS.test(mapped[1]);
2477
+ return PRIVATE_IP_PATTERNS.test(ip) || PRIVATE_IPV6_PATTERNS.test(ip);
2478
+ }
2372
2479
  async function resolveIpLocation(ip) {
2373
2480
  if (!ip) return "Unknown";
2374
- if (PRIVATE_IP_PATTERNS.test(ip)) return "Local";
2481
+ if (isPrivateIp(ip)) return "Local";
2375
2482
  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);
2483
+ const res = await fetch(`https://ipwho.is/${encodeURIComponent(ip)}`, { signal: AbortSignal.timeout(3e3) });
2380
2484
  if (!res.ok) return "Unknown";
2381
2485
  const data = await res.json();
2382
- if (data.status !== "success") return "Unknown";
2486
+ if (data.success !== true) return "Unknown";
2383
2487
  const parts = [
2384
2488
  data.city,
2385
- data.regionName,
2489
+ data.region,
2386
2490
  data.country
2387
2491
  ].filter(Boolean);
2388
2492
  return parts.length > 0 ? parts.join(", ") : "Unknown";
@@ -2392,18 +2496,25 @@ async function resolveIpLocation(ip) {
2392
2496
  }
2393
2497
  /**
2394
2498
  * 从 Request 中提取客户端真实 IP
2395
- * 优先级:X-Forwarded-For > X-Real-IP > CF-Connecting-IP
2499
+ *
2500
+ * 优先级:CF-Connecting-IP(Cloudflare 平台注入的权威头,客户端不可伪造)
2501
+ * > X-Real-IP > X-Forwarded-For 末段。
2502
+ *
2503
+ * ⚠ 前提声明:XFF 首值可由客户端任意伪造,因此取**末段**(最靠近本服务的
2504
+ * 可信代理所追加的一跳)。部署平台若自身不覆写 XFF(Vercel 会覆写),
2505
+ * 末段仍可能被上游代理链污染;Cloudflare 场景以 CF-Connecting-IP 为准。
2396
2506
  */
2397
2507
  function getClientIp(request) {
2508
+ const cfip = request.headers.get("cf-connecting-ip");
2509
+ if (cfip) return cfip.trim();
2510
+ const xri = request.headers.get("x-real-ip");
2511
+ if (xri) return xri.trim();
2398
2512
  const xff = request.headers.get("x-forwarded-for");
2399
2513
  if (xff) {
2400
- const first = xff.split(",")[0]?.trim();
2401
- if (first) return first;
2514
+ const segments = xff.split(",").map((s) => s.trim()).filter(Boolean);
2515
+ const last = segments[segments.length - 1];
2516
+ if (last) return last;
2402
2517
  }
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
2518
  return null;
2408
2519
  }
2409
2520
  //#endregion
@@ -2465,7 +2576,8 @@ function parseUserAgent(ua) {
2465
2576
  };
2466
2577
  }
2467
2578
  /**
2468
- * 将 ParsedUA 拼接为可读字符串,如 "Chrome 120 / Windows 10/11 / 桌面"
2579
+ * 将 ParsedUA 拼接为可读字符串,如 "Chrome 120 / Windows 10/11 / Desktop"
2580
+ * (输出为英文原文;中文文案由展示层经 paraglide 映射)
2469
2581
  */
2470
2582
  function formatParsedUA(parsed) {
2471
2583
  return [
@@ -2710,14 +2822,29 @@ function normalizeEmailCategories(raw) {
2710
2822
  }
2711
2823
  return result;
2712
2824
  }
2825
+ let dndMalformedWarned = false;
2826
+ /**
2827
+ * 判定 now(HH:MM)是否落在勿扰窗口内(支持跨零点)。
2828
+ *
2829
+ * 畸形时间输入(空串 / 非数字,如 DB 脏数据)旧实现产出 NaN、比较恒 false、
2830
+ * DND 静默失效——现显式校验,畸形时告警一次并按「不在勿扰窗口」处理。
2831
+ */
2713
2832
  function isInDndWindow(prefs, now) {
2714
2833
  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;
2834
+ const parse = (s) => {
2835
+ const [h, m] = s.split(":").map(Number);
2836
+ return Number.isFinite(h) && Number.isFinite(m) ? h * 60 + m : NaN;
2837
+ };
2838
+ const start = parse(prefs.dndStart);
2839
+ const end = parse(prefs.dndEnd);
2840
+ const cur = parse(now);
2841
+ if (Number.isNaN(start) || Number.isNaN(end) || Number.isNaN(cur)) {
2842
+ if (!dndMalformedWarned) {
2843
+ dndMalformedWarned = true;
2844
+ console.warn(`[notifications] 勿扰时段格式非法(须为 HH:MM):start=${JSON.stringify(prefs.dndStart)} end=${JSON.stringify(prefs.dndEnd)},DND 判定按不生效处理`);
2845
+ }
2846
+ return false;
2847
+ }
2721
2848
  if (start <= end) return cur >= start && cur < end;
2722
2849
  return cur >= start || cur < end;
2723
2850
  }
@@ -2725,8 +2852,18 @@ function isInDndWindow(prefs, now) {
2725
2852
  //#region src/contract/modules/registry.ts
2726
2853
  var ModuleRegistry = class {
2727
2854
  modules = /* @__PURE__ */ new Map();
2728
- register(mod) {
2729
- if (this.modules.has(mod.id)) console.warn(`[ModuleRegistry] "${mod.id}" already registered, overwriting`);
2855
+ /**
2856
+ * 注册模块。同 id 重复注册的语义:
2857
+ * - 显式 `{ overwrite: true }`:警告并覆盖(有意的替换场景);
2858
+ * - 生产环境:视为装配期配置错误直接抛出,避免「两个模块意外同 id」被静默掩盖;
2859
+ * - dev/test/HMR:警告并覆盖(模块双执行 / 热更新场景保持宽松)。
2860
+ */
2861
+ register(mod, options) {
2862
+ if (this.modules.has(mod.id)) {
2863
+ const isProd = typeof process !== "undefined" && process.env?.NODE_ENV === "production";
2864
+ if (!options?.overwrite && isProd) throw new Error(`[ModuleRegistry] "${mod.id}" already registered(同 id 模块重复注册;若确需覆盖请传 { overwrite: true })`);
2865
+ console.warn(`[ModuleRegistry] "${mod.id}" already registered, overwriting`);
2866
+ }
2730
2867
  this.modules.set(mod.id, mod);
2731
2868
  }
2732
2869
  getModule(id) {
@@ -2790,4 +2927,4 @@ const ICON_MAP = {
2790
2927
  music4: Music4
2791
2928
  };
2792
2929
  //#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 };
2930
+ 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, resolveImportSpecifiers as at, parseUserAgent as b, normalizeEmailCategories as c, definePlugin as ct, RESOURCE_KEYS as d, generateAssemblyCode as et, ResourceRegistry as f, FeatureRegistry as g, FEATURE_KEYS as h, DEFAULT_CATEGORIES as i, parseProfileImports 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, resolvePluginOrder as ot, isResourceDefined as p, registerPrismaSeam as q, moduleRegistry as r, extractPluginLocalNames as rt, normalizeCategoryFrequencies as s, defineProfile 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.2",
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": {