@pactor-app/skills 1.24.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.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -0
  3. package/package.json +26 -0
  4. package/pactor/SKILL.md +373 -0
  5. package/pactor/references/dsl-authoring.md +448 -0
  6. package/prd-to-app/SKILL.md +75 -0
  7. package/prd-to-app/references/acceptance-checklist.md +47 -0
  8. package/prd-to-app/references/component-mapping.md +41 -0
  9. package/prd-to-app/references/mock-data-routes.md +66 -0
  10. package/prd-to-app/references/page-templates.md +274 -0
  11. package/prd-to-app/references/project-structure.md +89 -0
  12. package/prd-to-app/references/theme-and-style.md +41 -0
  13. package/prd-to-app/template/README.md +26 -0
  14. package/prd-to-app/template/app/[[...slug]]/page.tsx +7 -0
  15. package/prd-to-app/template/app/api/auth/login/route.ts +32 -0
  16. package/prd-to-app/template/app/api/auth/logout/route.ts +22 -0
  17. package/prd-to-app/template/app/api/data/[...parts]/route.ts +118 -0
  18. package/prd-to-app/template/app/api/public/pages/[id]/route.ts +40 -0
  19. package/prd-to-app/template/app/api/sitemap/route.ts +21 -0
  20. package/prd-to-app/template/app/api/users/route.ts +57 -0
  21. package/prd-to-app/template/app/favicon.ico +0 -0
  22. package/prd-to-app/template/app/globals.css +248 -0
  23. package/prd-to-app/template/app/layout.tsx +49 -0
  24. package/prd-to-app/template/app/login.css +122 -0
  25. package/prd-to-app/template/eslint.config.mjs +18 -0
  26. package/prd-to-app/template/next-env.d.ts +7 -0
  27. package/prd-to-app/template/next.config.js +32 -0
  28. package/prd-to-app/template/package.json +34 -0
  29. package/prd-to-app/template/pnpm-lock.yaml +6854 -0
  30. package/prd-to-app/template/pnpm-workspace.yaml +7 -0
  31. package/prd-to-app/template/postcss.config.mjs +7 -0
  32. package/prd-to-app/template/public/file.svg +1 -0
  33. package/prd-to-app/template/public/globe.svg +1 -0
  34. package/prd-to-app/template/public/next.svg +1 -0
  35. package/prd-to-app/template/public/skins/chenwunaifu.css +111 -0
  36. package/prd-to-app/template/public/skins/taijingshenlin.css +109 -0
  37. package/prd-to-app/template/public/skins/xuanzhimoyun.css +110 -0
  38. package/prd-to-app/template/public/vercel.svg +1 -0
  39. package/prd-to-app/template/public/window.svg +1 -0
  40. package/prd-to-app/template/scripts/build.mjs +35 -0
  41. package/prd-to-app/template/src/pactor/App.tsx +55 -0
  42. package/prd-to-app/template/src/pactor/actions.ts +438 -0
  43. package/prd-to-app/template/src/pactor/components/card-links.tsx +86 -0
  44. package/prd-to-app/template/src/pactor/components/chip-filter.tsx +89 -0
  45. package/prd-to-app/template/src/pactor/components/chip-node.tsx +46 -0
  46. package/prd-to-app/template/src/pactor/components/debug-chat.tsx +189 -0
  47. package/prd-to-app/template/src/pactor/components/index.ts +28 -0
  48. package/prd-to-app/template/src/pactor/components/log-status.tsx +64 -0
  49. package/prd-to-app/template/src/pactor/components/status-badge.tsx +46 -0
  50. package/prd-to-app/template/src/pactor/components/theme-switcher.tsx +136 -0
  51. package/prd-to-app/template/src/pactor/config.ts +28 -0
  52. package/prd-to-app/template/src/pactor/mocks/audit-mock.ts +403 -0
  53. package/prd-to-app/template/src/pactor/mocks/call-logs-mock.ts +875 -0
  54. package/prd-to-app/template/src/pactor/mocks/client-debug-mock.ts +188 -0
  55. package/prd-to-app/template/src/pactor/mocks/client-templates-mock.ts +497 -0
  56. package/prd-to-app/template/src/pactor/mocks/clients-mock.ts +483 -0
  57. package/prd-to-app/template/src/pactor/mocks/costs-mock.ts +406 -0
  58. package/prd-to-app/template/src/pactor/mocks/dashboard-mock.ts +192 -0
  59. package/prd-to-app/template/src/pactor/mocks/model-debug-mock.ts +144 -0
  60. package/prd-to-app/template/src/pactor/mocks/models-mock.ts +799 -0
  61. package/prd-to-app/template/src/pactor/mocks/ops-usage-mock.ts +806 -0
  62. package/prd-to-app/template/src/pactor/mocks/providers-mock.ts +424 -0
  63. package/prd-to-app/template/src/pactor/mocks/routes-mock.ts +604 -0
  64. package/prd-to-app/template/src/pactor/services.ts +185 -0
  65. package/prd-to-app/template/src/pactor/skin.ts +52 -0
  66. package/prd-to-app/template/src/server/accounts.ts +63 -0
  67. package/prd-to-app/template/src/server/cors.ts +34 -0
  68. package/prd-to-app/template/src/server/sitemap.ts +176 -0
  69. package/prd-to-app/template/src/server/yaml/common/dashboard.yaml +498 -0
  70. package/prd-to-app/template/src/server/yaml/common/login.yaml +84 -0
  71. package/prd-to-app/template/src/server/yaml/provider/provider-create.yaml +340 -0
  72. package/prd-to-app/template/src/server/yaml/provider/provider-detail.yaml +780 -0
  73. package/prd-to-app/template/src/server/yaml/provider/provider-edit.yaml +366 -0
  74. package/prd-to-app/template/src/server/yaml/provider/provider-list.yaml +1989 -0
  75. package/prd-to-app/template/src/server/yaml/route/route-create.yaml +511 -0
  76. package/prd-to-app/template/src/server/yaml/route/route-detail.yaml +610 -0
  77. package/prd-to-app/template/src/server/yaml/route/route-edit.yaml +809 -0
  78. package/prd-to-app/template/src/server/yaml/route/route-list.yaml +1793 -0
  79. package/prd-to-app/template/src/server/yaml/sitemap.yaml +250 -0
  80. package/prd-to-app/template/tsconfig.json +34 -0
@@ -0,0 +1,403 @@
1
+ /**
2
+ * 审计日志(系统管理)演示数据服务(MVP mock,静态页面)。
3
+ * audit.list / audit.detail 注册为 Pactor service;接入真实后端后替换为
4
+ * http / service 数据源,DSL 绑定路径保持不变。
5
+ * 数据形态对齐 PRD《系统管理/02-审计》:列表(Timestamp / Operator / Operation /
6
+ * Resource Type / Resource ID / IP)+ 详情(变更前 / 变更后 / Diff / 操作上下文
7
+ * 四个 Tab,敏感数据脱敏显示)。
8
+ * 审计范围覆盖 Provider / Model / Alias / Route / Client / Quota / RateLimit /
9
+ * Pricing / 服务设置 / AppKey 创建停用 / Secret Rotation。
10
+ * Diff 行与复合文案全部在 mock 层预计算(表达式引擎不支持数组方法与函数调用)。
11
+ */
12
+
13
+ export interface AuditDiffLine {
14
+ type: "add" | "remove" | "same";
15
+ text: string;
16
+ }
17
+
18
+ export interface AuditContextRow {
19
+ label: string;
20
+ value: string;
21
+ }
22
+
23
+ export interface AuditRecord {
24
+ id: string;
25
+ /** ISO 日期(yyyy-MM-dd),时间范围过滤用 */
26
+ date: string;
27
+ /** 完整时间戳(UTC+8 展示口径) */
28
+ timeUtc: string;
29
+ /** 列表短格式 MM-DD HH:mm */
30
+ timeShort: string;
31
+ operator: string;
32
+ /** 操作展示名(修改 / 创建AppKey / Rotate Secret …) */
33
+ operation: string;
34
+ /** 操作类型过滤值 */
35
+ operationType: string;
36
+ /** 资源类型展示名(Route Policy / API Client …) */
37
+ resourceType: string;
38
+ /** 资源类型过滤值 */
39
+ resourceTypeKey: string;
40
+ resourceId: string;
41
+ ip: string;
42
+ requestId: string;
43
+ userAgent: string;
44
+ /** null = 该操作无此侧快照(创建无变更前 / 删除无变更后) */
45
+ beforeJson: string | null;
46
+ afterJson: string | null;
47
+ diffLines: AuditDiffLine[];
48
+ context: AuditContextRow[];
49
+ }
50
+
51
+ const OPERATION_LABELS: Record<string, string> = {
52
+ create: "创建",
53
+ update: "修改",
54
+ delete: "删除",
55
+ enable: "启用",
56
+ disable: "停用",
57
+ "appkey-create": "创建AppKey",
58
+ "appkey-disable": "停用AppKey",
59
+ "secret-rotate": "Rotate Secret",
60
+ "settings-update": "修改服务设置",
61
+ };
62
+
63
+ const RESOURCE_TYPE_LABELS: Record<string, string> = {
64
+ provider: "Provider",
65
+ model: "Model",
66
+ alias: "Model Alias",
67
+ route: "Route",
68
+ "route-policy": "Route Policy",
69
+ client: "API Client",
70
+ appkey: "AppKey",
71
+ quota: "Quota Policy",
72
+ ratelimit: "RateLimit Policy",
73
+ pricing: "Pricing",
74
+ settings: "服务设置",
75
+ };
76
+
77
+ export const OPERATOR_OPTIONS = [
78
+ { label: "全部操作人", value: "all" },
79
+ { label: "张三", value: "张三" },
80
+ { label: "李四", value: "李四" },
81
+ { label: "王五", value: "王五" },
82
+ { label: "管理员", value: "管理员" },
83
+ ];
84
+
85
+ export const OPERATION_OPTIONS = [
86
+ { label: "全部操作类型", value: "all" },
87
+ ...Object.entries(OPERATION_LABELS).map(([value, label]) => ({
88
+ label,
89
+ value,
90
+ })),
91
+ ];
92
+
93
+ export const RESOURCE_TYPE_OPTIONS = [
94
+ { label: "全部资源类型", value: "all" },
95
+ ...Object.entries(RESOURCE_TYPE_LABELS).map(([value, label]) => ({
96
+ label,
97
+ value,
98
+ })),
99
+ ];
100
+
101
+ /** 原始条目:[日期时间, 操作人, 操作类型, 资源类型, Resource ID, IP, 变更前, 变更后] */
102
+ type RawEntry = [
103
+ string,
104
+ string,
105
+ string,
106
+ string,
107
+ string,
108
+ string,
109
+ Record<string, unknown> | null,
110
+ Record<string, unknown> | null,
111
+ ];
112
+
113
+ const RAW: RawEntry[] = [
114
+ [
115
+ "2026-09-18 14:20:03",
116
+ "张三",
117
+ "update",
118
+ "route-policy",
119
+ "reasoning-def",
120
+ "10.0.1.5",
121
+ { policy: "fallback", maxRetries: 2, timeoutMs: 30000 },
122
+ { policy: "fallback", maxRetries: 3, timeoutMs: 60000 },
123
+ ],
124
+ [
125
+ "2026-09-18 10:00:41",
126
+ "李四",
127
+ "appkey-create",
128
+ "client",
129
+ "agent-app",
130
+ "10.0.1.8",
131
+ null,
132
+ {
133
+ appKeyId: "ak-2f8c1d9e",
134
+ secret: "sk-****3f9a",
135
+ client: "agent-app",
136
+ status: "active",
137
+ },
138
+ ],
139
+ [
140
+ "2026-09-17 17:42:19",
141
+ "管理员",
142
+ "settings-update",
143
+ "settings",
144
+ "service-settings",
145
+ "10.0.0.2",
146
+ { promptPolicy: "masked", logRetentionDays: 90, currency: "USD" },
147
+ { promptPolicy: "masked", logRetentionDays: 120, currency: "USD" },
148
+ ],
149
+ [
150
+ "2026-09-17 11:05:52",
151
+ "王五",
152
+ "update",
153
+ "pricing",
154
+ "gpt-5-pro",
155
+ "10.0.1.12",
156
+ { inputPer1M: 12.0, outputPer1M: 48.0, currency: "USD" },
157
+ { inputPer1M: 14.0, outputPer1M: 56.0, currency: "USD" },
158
+ ],
159
+ [
160
+ "2026-09-16 16:33:08",
161
+ "张三",
162
+ "create",
163
+ "route",
164
+ "code-assist",
165
+ "10.0.1.5",
166
+ null,
167
+ {
168
+ code: "code-assist",
169
+ targetModel: "claude-sonnet-4",
170
+ fallback: ["gpt-5-pro"],
171
+ status: "enabled",
172
+ },
173
+ ],
174
+ [
175
+ "2026-09-16 09:12:47",
176
+ "李四",
177
+ "disable",
178
+ "provider",
179
+ "azure-openai-east",
180
+ "10.0.1.8",
181
+ { status: "enabled", weight: 50, region: "eastus" },
182
+ { status: "disabled", weight: 50, region: "eastus" },
183
+ ],
184
+ [
185
+ "2026-09-15 15:58:26",
186
+ "王五",
187
+ "update",
188
+ "quota",
189
+ "agent-app-monthly",
190
+ "10.0.1.12",
191
+ { metric: "TOTAL_TOKEN", limit: 5000000, cycle: "month" },
192
+ { metric: "TOTAL_TOKEN", limit: 8000000, cycle: "month" },
193
+ ],
194
+ [
195
+ "2026-09-15 10:21:33",
196
+ "张三",
197
+ "secret-rotate",
198
+ "appkey",
199
+ "ak-7b31c904",
200
+ "10.0.1.5",
201
+ { appKeyId: "ak-7b31c904", secret: "sk-****a1c2" },
202
+ { appKeyId: "ak-7b31c904", secret: "sk-****e7d4" },
203
+ ],
204
+ [
205
+ "2026-09-14 18:44:09",
206
+ "管理员",
207
+ "update",
208
+ "model",
209
+ "gpt-5-pro",
210
+ "10.0.0.2",
211
+ { contextWindow: 272000, maxOutput: 32768, capabilities: ["tools"] },
212
+ {
213
+ contextWindow: 272000,
214
+ maxOutput: 65536,
215
+ capabilities: ["tools", "reasoning"],
216
+ },
217
+ ],
218
+ [
219
+ "2026-09-14 09:37:55",
220
+ "李四",
221
+ "appkey-disable",
222
+ "appkey",
223
+ "ak-9d20f153",
224
+ "10.0.1.8",
225
+ { appKeyId: "ak-9d20f153", client: "expired-trial", status: "active" },
226
+ { appKeyId: "ak-9d20f153", client: "expired-trial", status: "disabled" },
227
+ ],
228
+ [
229
+ "2026-09-13 14:02:18",
230
+ "王五",
231
+ "create",
232
+ "ratelimit",
233
+ "agent-app-rpm",
234
+ "10.0.1.12",
235
+ null,
236
+ { metric: "REQUEST", limit: 600, window: "1m", mode: "hard" },
237
+ ],
238
+ [
239
+ "2026-09-13 08:59:44",
240
+ "张三",
241
+ "update",
242
+ "alias",
243
+ "smart-default",
244
+ "10.0.1.5",
245
+ { alias: "smart-default", pointsTo: "gpt-5-pro" },
246
+ { alias: "smart-default", pointsTo: "claude-sonnet-4" },
247
+ ],
248
+ [
249
+ "2026-09-12 19:26:31",
250
+ "管理员",
251
+ "delete",
252
+ "client",
253
+ "legacy-bot",
254
+ "10.0.0.2",
255
+ {
256
+ code: "legacy-bot",
257
+ name: "Legacy Bot",
258
+ appKeyId: "ak-00c4de11",
259
+ status: "disabled",
260
+ },
261
+ null,
262
+ ],
263
+ [
264
+ "2026-08-29 11:15:07",
265
+ "李四",
266
+ "enable",
267
+ "provider",
268
+ "openai-main",
269
+ "10.0.1.8",
270
+ { status: "disabled", weight: 100, region: "us-east-1" },
271
+ { status: "enabled", weight: 100, region: "us-east-1" },
272
+ ],
273
+ [
274
+ "2026-08-21 16:48:53",
275
+ "张三",
276
+ "settings-update",
277
+ "settings",
278
+ "service-settings",
279
+ "10.0.1.5",
280
+ { timezone: "UTC", currencyDecimals: 4 },
281
+ { timezone: "Asia/Shanghai", currencyDecimals: 4 },
282
+ ],
283
+ ];
284
+
285
+ function pretty(obj: Record<string, unknown> | null): string | null {
286
+ return obj ? JSON.stringify(obj, null, 2) : null;
287
+ }
288
+
289
+ /** 行级对齐 diff:同位相同 → same;仅变更后 → add;仅变更前 → remove;均不同 → remove+add */
290
+ function diffLines(before: string | null, after: string | null): AuditDiffLine[] {
291
+ const b = before?.split("\n") ?? [];
292
+ const a = after?.split("\n") ?? [];
293
+ const lines: AuditDiffLine[] = [];
294
+ const n = Math.max(a.length, b.length);
295
+ for (let i = 0; i < n; i++) {
296
+ const al = a[i];
297
+ const bl = b[i];
298
+ if (al === bl) {
299
+ lines.push({ type: "same", text: ` ${al ?? ""}` });
300
+ } else {
301
+ if (bl !== undefined) lines.push({ type: "remove", text: `- ${bl}` });
302
+ if (al !== undefined) lines.push({ type: "add", text: `+ ${al}` });
303
+ }
304
+ }
305
+ return lines;
306
+ }
307
+
308
+ function build(): AuditRecord[] {
309
+ return RAW.map((raw, i) => {
310
+ const [time, operator, opType, resType, resourceId, ip, before, after] =
311
+ raw;
312
+ const beforeJson = pretty(before);
313
+ const afterJson = pretty(after);
314
+ const id = `aud-${String(1000 + i)}`;
315
+ return {
316
+ id,
317
+ date: time.slice(0, 10),
318
+ timeUtc: `${time} (UTC+8)`,
319
+ timeShort: time.slice(5, 16),
320
+ operator,
321
+ operation: OPERATION_LABELS[opType],
322
+ operationType: opType,
323
+ resourceType: RESOURCE_TYPE_LABELS[resType],
324
+ resourceTypeKey: resType,
325
+ resourceId,
326
+ ip,
327
+ requestId: `req-audit-${(92140 + i * 37).toString(16)}`,
328
+ userAgent: "GateWeave Console/1.0 (Chrome 139; macOS)",
329
+ beforeJson,
330
+ afterJson,
331
+ diffLines: diffLines(beforeJson, afterJson),
332
+ context: [
333
+ { label: "操作人", value: operator },
334
+ { label: "操作类型", value: OPERATION_LABELS[opType] },
335
+ { label: "资源", value: `${RESOURCE_TYPE_LABELS[resType]} / ${resourceId}` },
336
+ { label: "来源", value: "管理控制台" },
337
+ { label: "User-Agent", value: "GateWeave Console/1.0 (Chrome 139; macOS)" },
338
+ { label: "会话", value: `sess-${(5520 + i * 13).toString(16)}` },
339
+ { label: "结果", value: "成功" },
340
+ ],
341
+ };
342
+ });
343
+ }
344
+
345
+ const AUDITS = build();
346
+
347
+ export const AUDIT_IDS = AUDITS.map((r) => r.id);
348
+
349
+ export interface AuditQuery {
350
+ start?: string;
351
+ end?: string;
352
+ operator?: string;
353
+ operation?: string;
354
+ resourceType?: string;
355
+ resourceId?: string;
356
+ }
357
+
358
+ export function queryAudits(q: AuditQuery): {
359
+ items: AuditRecord[];
360
+ filteredText: string;
361
+ } {
362
+ const items = AUDITS.filter((r) => {
363
+ if (q.start && r.date < q.start) return false;
364
+ if (q.end && r.date > q.end) return false;
365
+ if (q.operator && q.operator !== "all" && r.operator !== q.operator)
366
+ return false;
367
+ if (
368
+ q.operation &&
369
+ q.operation !== "all" &&
370
+ r.operationType !== q.operation
371
+ )
372
+ return false;
373
+ if (
374
+ q.resourceType &&
375
+ q.resourceType !== "all" &&
376
+ r.resourceTypeKey !== q.resourceType
377
+ )
378
+ return false;
379
+ if (
380
+ q.resourceId &&
381
+ !r.resourceId.toLowerCase().includes(q.resourceId.toLowerCase())
382
+ )
383
+ return false;
384
+ return true;
385
+ });
386
+ return {
387
+ items,
388
+ filteredText: items.length.toLocaleString("en-US"),
389
+ };
390
+ }
391
+
392
+ export function getAudit(id: string): AuditRecord | undefined {
393
+ return AUDITS.find((r) => r.id === id);
394
+ }
395
+
396
+ /** 操作人筛选项(Select options):「全部」+ 记录中去重的操作人 */
397
+ export function listAuditOperators(): { label: string; value: string }[] {
398
+ const names = [...new Set(AUDITS.map((r) => r.operator))];
399
+ return [
400
+ { label: "全部操作人", value: "all" },
401
+ ...names.map((name) => ({ label: name, value: name })),
402
+ ];
403
+ }