@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.
- package/package.json +1 -1
- package/pactor-dsl/SKILL.md +4 -1
- package/pactor-dsl/references/dsl-authoring.md +2 -2
- package/pactor-prd/SKILL.md +2 -2
- package/pactor-prd/references/asset-library.md +2 -2
- package/pactor-prd/references/component-mapping.md +5 -3
- package/pactor-prd/references/page-templates.md +3 -3
- package/pactor-prd/template/app/layout.tsx +4 -3
- package/pactor-prd/template/package.json +2 -0
- package/pactor-prd/template/pnpm-lock.yaml +6898 -0
- package/pactor-prd/template/src/pactor/App.tsx +6 -1
- package/pactor-prd/template/src/pactor/components/index.ts +47 -0
- package/pactor-prd/template/src/server/sitemap.ts +54 -16
- package/pactor-prd/template/src/server/yaml/common/login.yaml +2 -1
|
@@ -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
|
-
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
if (!
|
|
83
|
-
return
|
|
106
|
+
/** YAML 状态:首次请求时读入缓存;dev 下 yaml 目录任一文件变更由 fs.watch 失效缓存,下次请求重读,无需重启 */
|
|
107
|
+
function state(): YamlState {
|
|
108
|
+
if (!stateCache) stateCache = loadState();
|
|
109
|
+
return stateCache;
|
|
84
110
|
}
|
|
85
111
|
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
|
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 化,样式走语义令牌(深浅色/换肤自适应),
|