@pactor-app/skills 1.44.0 → 1.46.0

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.
@@ -3,6 +3,7 @@
3
3
  import { usePathname, useRouter, useSearchParams } from "next/navigation";
4
4
  import { Suspense } from "react";
5
5
  import { SitemapApp } from "pactor-app";
6
+ import { Login } from "@pactor-app/blocks";
6
7
 
7
8
  import { apiBaseUrl, pageEndpoint, sitemapSources } from "./config";
8
9
  import { pactorActions } from "./actions";
@@ -19,6 +20,10 @@ import { pactorComponents } from "./components";
19
20
  *(app/api/d/[...parts]/route.ts)原样转发到 serverBaseUrl(见 config.ts);
20
21
  * 没有服务层接口时转发层返回空数据,页面按空态渲染。
21
22
  *
23
+ * 业务区块组件(@pactor-app/blocks)不进 ui 内置注册表:login 页 DSL 的
24
+ * `type: Login` 经 `components` prop 注册(样式见 layout.tsx 的
25
+ * blocks/styles.css)。
26
+ *
22
27
  * 登录 / 登出是普通 HTTP 调用,由 DSL 中的内置 request 动作直接表达
23
28
  *(见 src/server/yaml/ 的登录页 / 布局 DSL),无需客户端注册服务。
24
29
  *
@@ -48,7 +53,7 @@ function PactorAppInner() {
48
53
  pathname={pathname}
49
54
  query={Object.fromEntries(searchParams.entries())}
50
55
  navigate={(to) => router.push(to)}
51
- components={pactorComponents}
56
+ components={{ ...pactorComponents, Login }}
52
57
  actions={pactorActions}
53
58
  pageEndpoint={pageEndpoint}
54
59
  />
@@ -4,14 +4,61 @@
4
4
  * 页面 DSL 引用的自定义组件注册表(页面级自定义组件
5
5
  * `components={{...}}`),经 SitemapApp 的 `components` prop 全局注册。
6
6
  * ChipFilter / ChipNode 快筛组件已内置在 @pactor-app/ui,无需在此注册。
7
+ *
8
+ * Chat 展示组件(ChatPage / Bubble / Composer 等 18 个)归属
9
+ * @pactor-app/chat 的 /components 子路径,不进 ui 内置注册表,
10
+ * 在此展开注册(DSL 类型名 = 导出符号名);样式见 app/layout.tsx 的
11
+ * pactor-app/styles.css(聚合单入口)。
7
12
  */
13
+ import {
14
+ AgentStatus,
15
+ ArtifactPanel,
16
+ Attachment,
17
+ Bubble,
18
+ ChatMessage,
19
+ ChatPage,
20
+ Citation,
21
+ Composer,
22
+ ConversationList,
23
+ MessageList,
24
+ Prompt,
25
+ Sender,
26
+ StepsPanel,
27
+ StreamingText,
28
+ Suggestion,
29
+ Thinking,
30
+ ToolCall,
31
+ Welcome,
32
+ } from "@pactor-app/chat/components";
8
33
  import { StatusBadge } from "./status-badge";
9
34
  import { LogStatus } from "./log-status";
10
35
  import { DebugChat } from "./debug-chat";
11
36
  import { CardLink, StatusToggleIcon, TextLink } from "./card-links";
12
37
  import { ThemeSwitcher } from "./theme-switcher";
13
38
 
39
+ const chatComponents: Record<string, unknown> = {
40
+ AgentStatus,
41
+ ArtifactPanel,
42
+ Attachment,
43
+ Bubble,
44
+ ChatMessage,
45
+ ChatPage,
46
+ Citation,
47
+ Composer,
48
+ ConversationList,
49
+ MessageList,
50
+ Prompt,
51
+ Sender,
52
+ StepsPanel,
53
+ StreamingText,
54
+ Suggestion,
55
+ Thinking,
56
+ ToolCall,
57
+ Welcome,
58
+ };
59
+
14
60
  export const pactorComponents: Record<string, unknown> = {
61
+ ...chatComponents,
15
62
  StatusBadge,
16
63
  LogStatus,
17
64
  DebugChat,
@@ -1,4 +1,4 @@
1
- import { readFileSync, readdirSync } from "node:fs";
1
+ import { readFileSync, readdirSync, watch } from "node:fs";
2
2
  import { join, relative } from "node:path";
3
3
 
4
4
  import type { PageDsl, PermissionConfig } from "@pactor-app/core";
@@ -20,7 +20,7 @@ import type { DemoUser } from "./accounts";
20
20
  * 动态字段(updatedAt / user / permissions)。
21
21
  */
22
22
 
23
- /* ---------------- YAML DSL 文件加载(src/server/yaml/,启动时读入内存) ---------------- */
23
+ /* ---------------- YAML DSL 文件加载(src/server/yaml/,缓存 + dev 下 fs.watch 失效重读) ---------------- */
24
24
 
25
25
  const YAML_DIR = join(process.cwd(), "src/server/yaml");
26
26
 
@@ -60,8 +60,6 @@ interface SitemapFile {
60
60
  menus: SitemapResource["menus"];
61
61
  }
62
62
 
63
- const site = loadYaml<SitemapFile>("sitemap.yaml");
64
-
65
63
  /** 递归收集 yaml 下所有页面 DSL(含 route / provider / ops 等域子目录;跳过 sitemap.yaml),按 id → 相对路径建索引 */
66
64
  function collectPageFiles(dir: string): Map<string, string> {
67
65
  return new Map(
@@ -75,21 +73,59 @@ function collectPageFiles(dir: string): Map<string, string> {
75
73
  );
76
74
  }
77
75
 
78
- const pageFiles = collectPageFiles(YAML_DIR);
76
+ interface YamlState {
77
+ site: SitemapFile;
78
+ pageDsls: Map<string, PageDsl>;
79
+ lazyPageDsls: Map<string, PageDsl>;
80
+ }
81
+
82
+ function loadState(): YamlState {
83
+ const site = loadYaml<SitemapFile>("sitemap.yaml");
84
+ const pageFiles = collectPageFiles(YAML_DIR);
85
+
86
+ function loadPageDsl(id: string): PageDsl {
87
+ const file = pageFiles.get(id);
88
+ if (!file) throw new Error(`页面 DSL 缺失:${id}.yaml`);
89
+ return loadYaml<PageDsl>(file);
90
+ }
91
+
92
+ // 页面 DSL:按 id 约定从 yaml/<域>/<id>.yaml 加载;lazy 页不内联进 sitemap
93
+ return {
94
+ site,
95
+ pageDsls: new Map(
96
+ site.pages.filter((p) => !p.lazy).map((p) => [p.id, loadPageDsl(p.id)]),
97
+ ),
98
+ lazyPageDsls: new Map(
99
+ site.pages.filter((p) => p.lazy).map((p) => [p.id, loadPageDsl(p.id)]),
100
+ ),
101
+ };
102
+ }
103
+
104
+ let stateCache: YamlState | null = null;
79
105
 
80
- function loadPageDsl(id: string): PageDsl {
81
- const file = pageFiles.get(id);
82
- if (!file) throw new Error(`页面 DSL 缺失:${id}.yaml`);
83
- return loadYaml<PageDsl>(file);
106
+ /** YAML 状态:首次请求时读入缓存;dev 下 yaml 目录任一文件变更由 fs.watch 失效缓存,下次请求重读,无需重启 */
107
+ function state(): YamlState {
108
+ if (!stateCache) stateCache = loadState();
109
+ return stateCache;
84
110
  }
85
111
 
86
- /** 页面 DSL:按 id 约定从 yaml/<域>/<id>.yaml 加载;lazy 页不在此内联 */
87
- const pageDsls = new Map(
88
- site.pages.filter((p) => !p.lazy).map((p) => [p.id, loadPageDsl(p.id)]),
89
- );
90
- const lazyPageDsls = new Map(
91
- site.pages.filter((p) => p.lazy).map((p) => [p.id, loadPageDsl(p.id)]),
92
- );
112
+ // watcher 挂 globalThis:Next dev 重编译会重新执行本模块,只更新失效回调、不重复建 watcher
113
+ const globalForYamlWatch = globalThis as unknown as {
114
+ __pactorYamlInvalidate?: () => void;
115
+ __pactorYamlWatcher?: ReturnType<typeof watch>;
116
+ };
117
+ globalForYamlWatch.__pactorYamlInvalidate = () => {
118
+ stateCache = null;
119
+ };
120
+ if (process.env.NODE_ENV !== "production" && !globalForYamlWatch.__pactorYamlWatcher) {
121
+ globalForYamlWatch.__pactorYamlWatcher = watch(
122
+ YAML_DIR,
123
+ { recursive: true },
124
+ () => {
125
+ globalForYamlWatch.__pactorYamlInvalidate?.();
126
+ },
127
+ );
128
+ }
93
129
 
94
130
  /* ---------------- 会话裁剪 ---------------- */
95
131
 
@@ -140,6 +176,7 @@ function filterMenus(
140
176
  * 匿名 → 仅 public 页;guest → + 首页;admin → + 用户列表 / 报表组。
141
177
  */
142
178
  export function buildSitemap(user: DemoUser | null): SitemapResource {
179
+ const { site, pageDsls } = state();
143
180
  const pages: SitemapResource["pages"] = site.pages
144
181
  .filter((p) => canSee(p, user))
145
182
  .map((p) => ({
@@ -167,6 +204,7 @@ export function getLazyPage(
167
204
  pageId: string,
168
205
  user: DemoUser | null,
169
206
  ): { version: number; pageDsl: PageDsl } | null {
207
+ const { site, lazyPageDsls } = state();
170
208
  const entry = site.pages.find((p) => p.id === pageId);
171
209
  const pageDsl = lazyPageDsls.get(pageId);
172
210
  if (!entry?.lazy || !pageDsl || !canSee(entry, user)) {
@@ -1,4 +1,5 @@
1
- # 登录页 DSL:type: Login 业务组件(packages/ui components/business/Login/),
1
+ # 登录页 DSL:type: Login 业务组件(@pactor-app/blocks,经 App.tsx 的
2
+ # components prop 注册;样式在 app/layout.tsx 挂载 blocks/styles.css),
2
3
  # 布局(layout: split / centered / brand-card / overlap / backdrop)与修饰
3
4
  # (brandSide / brandRatio / authVariant / brandPanelBackground / decor)正交组合,
4
5
  # 品牌区/文案/辅助入口/页脚全部 props 化,样式走语义令牌(深浅色/换肤自适应),