skill-home 0.1.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/dist/cli/cmd_read.d.ts +3 -0
- package/dist/cli/cmd_read.d.ts.map +1 -0
- package/dist/cli/cmd_read.js +868 -0
- package/dist/cli/cmd_read.js.map +1 -0
- package/dist/fetch/db.d.ts +107 -0
- package/dist/fetch/db.d.ts.map +1 -0
- package/dist/fetch/db.js +433 -0
- package/dist/fetch/db.js.map +1 -0
- package/dist/fetch/domains.d.ts +51 -0
- package/dist/fetch/domains.d.ts.map +1 -0
- package/dist/fetch/domains.js +203 -0
- package/dist/fetch/domains.js.map +1 -0
- package/dist/fetch/errors.d.ts +11 -0
- package/dist/fetch/errors.d.ts.map +1 -0
- package/dist/fetch/errors.js +18 -0
- package/dist/fetch/errors.js.map +1 -0
- package/dist/fetch/index.d.ts +6 -0
- package/dist/fetch/index.d.ts.map +1 -0
- package/dist/fetch/index.js +5 -0
- package/dist/fetch/index.js.map +1 -0
- package/dist/fetch/paths.d.ts +6 -0
- package/dist/fetch/paths.d.ts.map +1 -0
- package/dist/fetch/paths.js +31 -0
- package/dist/fetch/paths.js.map +1 -0
- package/dist/help/index.d.ts +3 -0
- package/dist/help/index.d.ts.map +1 -0
- package/dist/help/index.js +2 -0
- package/dist/help/index.js.map +1 -0
- package/dist/help/lookup.d.ts +11 -0
- package/dist/help/lookup.d.ts.map +1 -0
- package/dist/help/lookup.js +52 -0
- package/dist/help/lookup.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/policy/care.d.ts +4 -0
- package/dist/policy/care.d.ts.map +1 -0
- package/dist/policy/care.js +12 -0
- package/dist/policy/care.js.map +1 -0
- package/dist/policy/category.d.ts +8 -0
- package/dist/policy/category.d.ts.map +1 -0
- package/dist/policy/category.js +44 -0
- package/dist/policy/category.js.map +1 -0
- package/dist/policy/index.d.ts +9 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +6 -0
- package/dist/policy/index.js.map +1 -0
- package/dist/policy/item.d.ts +18 -0
- package/dist/policy/item.d.ts.map +1 -0
- package/dist/policy/item.js +81 -0
- package/dist/policy/item.js.map +1 -0
- package/dist/policy/ticket.d.ts +6 -0
- package/dist/policy/ticket.d.ts.map +1 -0
- package/dist/policy/ticket.js +25 -0
- package/dist/policy/ticket.js.map +1 -0
- package/dist/policy/wakewords.d.ts +15 -0
- package/dist/policy/wakewords.d.ts.map +1 -0
- package/dist/policy/wakewords.js +120 -0
- package/dist/policy/wakewords.js.map +1 -0
- package/dist/render/envelope.d.ts +6 -0
- package/dist/render/envelope.d.ts.map +1 -0
- package/dist/render/envelope.js +61 -0
- package/dist/render/envelope.js.map +1 -0
- package/dist/render/errors.d.ts +5 -0
- package/dist/render/errors.d.ts.map +1 -0
- package/dist/render/errors.js +10 -0
- package/dist/render/errors.js.map +1 -0
- package/dist/render/html.d.ts +13 -0
- package/dist/render/html.d.ts.map +1 -0
- package/dist/render/html.js +66 -0
- package/dist/render/html.js.map +1 -0
- package/dist/render/index.d.ts +8 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +6 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/templates.d.ts +5 -0
- package/dist/render/templates.d.ts.map +1 -0
- package/dist/render/templates.js +68 -0
- package/dist/render/templates.js.map +1 -0
- package/dist/render/views.d.ts +83 -0
- package/dist/render/views.d.ts.map +1 -0
- package/dist/render/views.js +56 -0
- package/dist/render/views.js.map +1 -0
- package/package.json +32 -0
- package/templates/care_query.html +16 -0
- package/templates/care_receipt.html +16 -0
- package/templates/help.html +16 -0
- package/templates/inventory_records.html +16 -0
- package/templates/inventory_round.html +16 -0
- package/templates/item_detail.html +16 -0
- package/templates/item_receipt.html +16 -0
- package/templates/item_search.html +16 -0
- package/templates/item_update_receipt.html +16 -0
- package/templates/location_query.html +16 -0
- package/templates/location_receipt.html +16 -0
- package/templates/outfit_pick.html +16 -0
- package/templates/shopping_query.html +16 -0
- package/templates/shopping_receipt.html +16 -0
- package/templates/stats_alert.html +16 -0
- package/templates/stats_overview.html +16 -0
- package/templates/tag_query.html +16 -0
- package/templates/tag_receipt.html +16 -0
- package/templates/ticket_query.html +16 -0
- package/templates/ticket_receipt.html +16 -0
- package/templates/trip_receipt.html +16 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// 口径层·分类/位置/状态(老家 references/categories.md + statuses.md 对应)。
|
|
2
|
+
// 8 顶级统一不带前缀;位置须两级路径;11 状态机;食品判定关键词(seed_key 落库前启发式)。
|
|
3
|
+
import { HomePolicyError } from '../fetch/errors.js';
|
|
4
|
+
export const HOME_TOPS = [
|
|
5
|
+
'食物与饮品', '衣物与穿戴', '家居与陈设', '工具与器材',
|
|
6
|
+
'数码与电子', '健康与医药', '文体与娱乐', '资产与凭证',
|
|
7
|
+
];
|
|
8
|
+
export const HOME_STATUSES = [
|
|
9
|
+
'在家', '备用', '穿着中', '旅游中', '洗护中', '借用中', '维修中', '已用完', '快递中', '待处理', '已废弃',
|
|
10
|
+
];
|
|
11
|
+
const FOOD_CATS = ['食物', '饮品', '饮料', '零食', '酒', '茶', '咖啡'];
|
|
12
|
+
const FOOD_NAMES = ['水', '奶', '茶', '咖啡', '果汁', '酒', '酸奶', '面包', '饼干', '米', '面', '油', '醋', '糖', '果', '菜', '肉', '蛋', '零食'];
|
|
13
|
+
export function normalizeLocation(loc) {
|
|
14
|
+
if (typeof loc !== 'string' || !loc.trim())
|
|
15
|
+
throw new HomePolicyError('POLICY_BAD_LOCATION', '位置须为非空字符串(至少两级,如 客厅/冰箱)');
|
|
16
|
+
const segs = loc.replace(///g, '/').split('/').map((s) => s.trim()).filter(Boolean);
|
|
17
|
+
if (segs.length < 2)
|
|
18
|
+
throw new HomePolicyError('POLICY_BAD_LOCATION', '位置须至少两级路径:' + loc);
|
|
19
|
+
return segs.join('/');
|
|
20
|
+
}
|
|
21
|
+
export function normalizeStatus(st) {
|
|
22
|
+
if (typeof st !== 'string' || !HOME_STATUSES.includes(st)) {
|
|
23
|
+
throw new HomePolicyError('POLICY_BAD_STATUS', '非法状态:' + String(st) + '(11 态:' + HOME_STATUSES.join('、') + ')');
|
|
24
|
+
}
|
|
25
|
+
return st;
|
|
26
|
+
}
|
|
27
|
+
export function isFoodItem(category, name) {
|
|
28
|
+
const c = category ?? '';
|
|
29
|
+
if (FOOD_CATS.some((k) => c.includes(k)))
|
|
30
|
+
return true;
|
|
31
|
+
return FOOD_NAMES.some((k) => name.includes(k));
|
|
32
|
+
}
|
|
33
|
+
export function validateCategoryName(name) {
|
|
34
|
+
if (typeof name !== 'string' || !name.trim() || name.trim().length > 30) {
|
|
35
|
+
throw new HomePolicyError('POLICY_BAD_CATEGORY', '分类名须 1~30 字非空');
|
|
36
|
+
}
|
|
37
|
+
const n = name.trim();
|
|
38
|
+
if (/^[\d\[\(]/.test(n))
|
|
39
|
+
throw new HomePolicyError('POLICY_BAD_CATEGORY', '分类名禁数字前缀:' + n);
|
|
40
|
+
if (/[\u{1F300}-\u{1FAFF}]/u.test(n))
|
|
41
|
+
throw new HomePolicyError('POLICY_BAD_CATEGORY', '分类名禁 emoji:' + n);
|
|
42
|
+
return n;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=category.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"category.js","sourceRoot":"","sources":["../../src/policy/category.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { HOME_TOPS, HOME_STATUSES, normalizeLocation, normalizeStatus, isFoodItem, validateCategoryName } from './category.js';
|
|
2
|
+
export type { HomeTop } from './category.js';
|
|
3
|
+
export { validateAddInput, parseUpdateOp, needId } from './item.js';
|
|
4
|
+
export { TICKET_KINDS, parseTicketKind, checkDate, checkMoney } from './ticket.js';
|
|
5
|
+
export type { TicketKind } from './ticket.js';
|
|
6
|
+
export { CARE_QUERY_KINDS, CARE_WRITE_KINDS, parseCareKind } from './care.js';
|
|
7
|
+
export { WAKE_TABLE, DEPRECATED_PHRASES, routeWakeword } from './wakewords.js';
|
|
8
|
+
export type { HomeKey, WakeRoute, WakeEntry } from './wakewords.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC/H,YAAY,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACnF,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/E,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { HOME_TOPS, HOME_STATUSES, normalizeLocation, normalizeStatus, isFoodItem, validateCategoryName } from './category.js';
|
|
2
|
+
export { validateAddInput, parseUpdateOp, needId } from './item.js';
|
|
3
|
+
export { TICKET_KINDS, parseTicketKind, checkDate, checkMoney } from './ticket.js';
|
|
4
|
+
export { CARE_QUERY_KINDS, CARE_WRITE_KINDS, parseCareKind } from './care.js';
|
|
5
|
+
export { WAKE_TABLE, DEPRECATED_PHRASES, routeWakeword } from './wakewords.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE/H,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEnF,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare function validateAddInput(p: Record<string, unknown>): {
|
|
2
|
+
name: string;
|
|
3
|
+
category_id: number;
|
|
4
|
+
location: string;
|
|
5
|
+
owner: string;
|
|
6
|
+
purchase_price: number | null;
|
|
7
|
+
remark: string | null;
|
|
8
|
+
photo: string | null;
|
|
9
|
+
quantity: number;
|
|
10
|
+
location_status: string;
|
|
11
|
+
purchase_date: string | null;
|
|
12
|
+
expiration_date: string | null;
|
|
13
|
+
reason: string | null;
|
|
14
|
+
tags: string[];
|
|
15
|
+
};
|
|
16
|
+
export declare function parseUpdateOp(p: Record<string, unknown>): string;
|
|
17
|
+
export declare function needId(p: Record<string, unknown>): number;
|
|
18
|
+
//# sourceMappingURL=item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item.d.ts","sourceRoot":"","sources":["../../src/policy/item.ts"],"names":[],"mappings":"AAKA,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAC5D,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IACnE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3E,QAAQ,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACxE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;CACvE,CAoCA;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAahE;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAIzD"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// 口径层·物品增改查校验(老家 features/add.md + commands.md 对应)。
|
|
2
|
+
// add 须 name+category_id+location;update 须 id;数量/状态/移动各守卫;坏输入阻断不返空。
|
|
3
|
+
import { HomePolicyError } from '../fetch/errors.js';
|
|
4
|
+
import { normalizeLocation, normalizeStatus } from './category.js';
|
|
5
|
+
export function validateAddInput(p) {
|
|
6
|
+
const name = typeof p.name === 'string' ? p.name.trim() : '';
|
|
7
|
+
if (!name)
|
|
8
|
+
throw new HomePolicyError('POLICY_BAD_INPUT', '录物品须给 name');
|
|
9
|
+
const cid = p.category_id ?? p.categoryId;
|
|
10
|
+
if (!Number.isInteger(cid) || cid <= 0)
|
|
11
|
+
throw new HomePolicyError('POLICY_BAD_INPUT', '录物品须给 category_id 正整数(从 categories 表查)');
|
|
12
|
+
const location = normalizeLocation(p.location);
|
|
13
|
+
const quantity = p.quantity === undefined ? 1 : p.quantity;
|
|
14
|
+
if (!Number.isInteger(quantity) || quantity <= 0)
|
|
15
|
+
throw new HomePolicyError('POLICY_BAD_INPUT', 'quantity 须为正整数');
|
|
16
|
+
const status = p.location_status === undefined || p.location_status === null ? '在家' : normalizeStatus(p.location_status);
|
|
17
|
+
let price = null;
|
|
18
|
+
if (p.price !== undefined && p.price !== null) {
|
|
19
|
+
if (typeof p.price !== 'number' || !(p.price >= 0))
|
|
20
|
+
throw new HomePolicyError('POLICY_BAD_INPUT', 'price 须为非负数');
|
|
21
|
+
price = p.price;
|
|
22
|
+
}
|
|
23
|
+
else if (p.purchase_price !== undefined && p.purchase_price !== null) {
|
|
24
|
+
if (typeof p.purchase_price !== 'number' || !(p.purchase_price >= 0))
|
|
25
|
+
throw new HomePolicyError('POLICY_BAD_INPUT', 'purchase_price 须为非负数');
|
|
26
|
+
price = p.purchase_price;
|
|
27
|
+
}
|
|
28
|
+
for (const d of ['purchase_date', 'purchaseDate', 'expiration_date', 'expirationDate']) {
|
|
29
|
+
const v = p[d];
|
|
30
|
+
if (v !== undefined && v !== null && typeof v === 'string' && v && !/^\d{4}-\d{2}-\d{2}$/.test(v)) {
|
|
31
|
+
throw new HomePolicyError('POLICY_BAD_DATE', '日期须 YYYY-MM-DD:' + d);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const tags = [];
|
|
35
|
+
if (p.tags !== undefined && p.tags !== null) {
|
|
36
|
+
if (typeof p.tags !== 'string')
|
|
37
|
+
throw new HomePolicyError('POLICY_BAD_INPUT', 'tags 须为逗号分隔字符串');
|
|
38
|
+
for (const t of p.tags.split(',')) {
|
|
39
|
+
const s = t.trim();
|
|
40
|
+
if (s)
|
|
41
|
+
tags.push(s);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
name, category_id: cid, location, owner: typeof p.owner === 'string' && p.owner ? p.owner : '使用者',
|
|
46
|
+
purchase_price: price, remark: typeof p.remark === 'string' ? p.remark : null,
|
|
47
|
+
photo: typeof p.photo === 'string' ? p.photo : null, quantity: quantity, location_status: status,
|
|
48
|
+
purchase_date: (p.purchase_date ?? p.purchaseDate ?? null),
|
|
49
|
+
expiration_date: (p.expiration_date ?? p.expirationDate ?? null),
|
|
50
|
+
reason: typeof p.reason === 'string' ? p.reason : null, tags,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export function parseUpdateOp(p) {
|
|
54
|
+
if (p.op !== undefined) {
|
|
55
|
+
if (typeof p.op !== 'string' || !p.op)
|
|
56
|
+
throw new HomePolicyError('POLICY_BAD_INPUT', 'op 须为非空字符串');
|
|
57
|
+
return p.op;
|
|
58
|
+
}
|
|
59
|
+
if (p.plus !== undefined || p.minus !== undefined || p.set !== undefined || p.quantity !== undefined)
|
|
60
|
+
return 'qty';
|
|
61
|
+
if (p.location_status !== undefined || p.status !== undefined)
|
|
62
|
+
return 'status';
|
|
63
|
+
if (p.new_location !== undefined || p.newLocation !== undefined)
|
|
64
|
+
return 'move';
|
|
65
|
+
if (p.tags !== undefined)
|
|
66
|
+
return 'tags';
|
|
67
|
+
if (p.target !== undefined || p.sources !== undefined)
|
|
68
|
+
return 'merge';
|
|
69
|
+
if (p.related !== undefined)
|
|
70
|
+
return 'relate';
|
|
71
|
+
if (p.photo !== undefined && Object.keys(p).length <= 3)
|
|
72
|
+
return 'photo';
|
|
73
|
+
return 'generic';
|
|
74
|
+
}
|
|
75
|
+
export function needId(p) {
|
|
76
|
+
const v = p.id ?? p.item_id ?? p.itemId;
|
|
77
|
+
if (!Number.isInteger(v) || v <= 0)
|
|
78
|
+
throw new HomePolicyError('POLICY_BAD_INPUT', '须给 id 正整数');
|
|
79
|
+
return v;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"item.js","sourceRoot":"","sources":["../../src/policy/item.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const TICKET_KINDS: readonly ["purchase", "warranty", "cert", "account"];
|
|
2
|
+
export type TicketKind = (typeof TICKET_KINDS)[number];
|
|
3
|
+
export declare function parseTicketKind(p: Record<string, unknown>): TicketKind;
|
|
4
|
+
export declare function checkDate(v: unknown, field: string): string | null;
|
|
5
|
+
export declare function checkMoney(v: unknown, field: string): number | null;
|
|
6
|
+
//# sourceMappingURL=ticket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket.d.ts","sourceRoot":"","sources":["../../src/policy/ticket.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,YAAY,sDAAuD,CAAC;AACjF,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAItE;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIlE;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAInE"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// 口径层·票据凭证校验(老家 scripts/票据凭证/cli.py 对应)。
|
|
2
|
+
// purchase/warranty/cert/account 四 kind;kind+op 分流;日期/金额/主密钥守卫。
|
|
3
|
+
import { HomePolicyError } from '../fetch/errors.js';
|
|
4
|
+
export const TICKET_KINDS = ['purchase', 'warranty', 'cert', 'account'];
|
|
5
|
+
export function parseTicketKind(p) {
|
|
6
|
+
const k = (p.kind ?? p.domain ?? 'purchase');
|
|
7
|
+
if (!TICKET_KINDS.includes(k))
|
|
8
|
+
throw new HomePolicyError('POLICY_BAD_INPUT', '未知 ticket kind:' + String(k));
|
|
9
|
+
return k;
|
|
10
|
+
}
|
|
11
|
+
export function checkDate(v, field) {
|
|
12
|
+
if (v === undefined || v === null || v === '')
|
|
13
|
+
return null;
|
|
14
|
+
if (typeof v !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(v))
|
|
15
|
+
throw new HomePolicyError('POLICY_BAD_DATE', field + ' 须 YYYY-MM-DD');
|
|
16
|
+
return v;
|
|
17
|
+
}
|
|
18
|
+
export function checkMoney(v, field) {
|
|
19
|
+
if (v === undefined || v === null || v === '')
|
|
20
|
+
return null;
|
|
21
|
+
if (typeof v !== 'number' || !(v >= 0))
|
|
22
|
+
throw new HomePolicyError('POLICY_BAD_INPUT', field + ' 须为非负数');
|
|
23
|
+
return v;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=ticket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket.js","sourceRoot":"","sources":["../../src/policy/ticket.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,gEAAgE;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAU,CAAC;AAGjF,MAAM,UAAU,eAAe,CAAC,CAA0B;IACxD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,UAAU,CAAW,CAAC;IACvD,IAAI,CAAE,YAAkC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,iBAAiB,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IACnI,OAAO,CAAe,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,CAAU,EAAE,KAAa;IACjD,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC3D,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,iBAAiB,EAAE,KAAK,GAAG,eAAe,CAAC,CAAC;IACnI,OAAO,CAAC,CAAC;AACX,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAU,EAAE,KAAa;IAClD,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC3D,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,KAAK,GAAG,QAAQ,CAAC,CAAC;IACxG,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type HomeKey = 'home.item.search' | 'home.item.detail' | 'home.item.add' | 'home.item.update' | 'home.tag.query' | 'home.tag.write' | 'home.inventory.round' | 'home.inventory.records' | 'home.location.query' | 'home.location.write' | 'home.outfit.pick' | 'home.trip.manage' | 'home.stats.overview' | 'home.stats.alert' | 'home.shopping.query' | 'home.shopping.write' | 'home.ticket.query' | 'home.ticket.write' | 'home.care.query' | 'home.care.write' | 'home.help.lookup';
|
|
2
|
+
export interface WakeRoute {
|
|
3
|
+
key: HomeKey;
|
|
4
|
+
params: Record<string, unknown>;
|
|
5
|
+
}
|
|
6
|
+
export interface WakeEntry {
|
|
7
|
+
phrase: string;
|
|
8
|
+
key: HomeKey;
|
|
9
|
+
needs?: string[];
|
|
10
|
+
preset?: Record<string, unknown>;
|
|
11
|
+
}
|
|
12
|
+
export declare const WAKE_TABLE: WakeEntry[];
|
|
13
|
+
export declare const DEPRECATED_PHRASES: string[];
|
|
14
|
+
export declare function routeWakeword(text: string, ctx?: Record<string, unknown>): WakeRoute;
|
|
15
|
+
//# sourceMappingURL=wakewords.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wakewords.d.ts","sourceRoot":"","sources":["../../src/policy/wakewords.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GACf,kBAAkB,GAAG,kBAAkB,GAAG,eAAe,GAAG,kBAAkB,GAC9E,gBAAgB,GAAG,gBAAgB,GACnC,sBAAsB,GAAG,wBAAwB,GACjD,qBAAqB,GAAG,qBAAqB,GAC7C,kBAAkB,GAAG,kBAAkB,GACvC,qBAAqB,GAAG,kBAAkB,GAC1C,qBAAqB,GAAG,qBAAqB,GAC7C,mBAAmB,GAAG,mBAAmB,GACzC,iBAAiB,GAAG,iBAAiB,GACrC,kBAAkB,CAAC;AAEvB,MAAM,WAAW,SAAS;IAAG,GAAG,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAAE;AAC7E,MAAM,WAAW,SAAS;IAAG,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAAE;AAEhH,eAAO,MAAM,UAAU,EAAE,SAAS,EA4FjC,CAAC;AAGF,eAAO,MAAM,kBAAkB,UAA4B,CAAC;AAI5D,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,SAAS,CAYxF"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// 口径层·唤醒词路由:自然语言 → 21 联动 key;最长匹配;联动 3 词废弃不路由。
|
|
2
|
+
// HELP 速查唯一上游;改这里,HELP 构建期跟进。
|
|
3
|
+
import { HomePolicyError } from '../fetch/errors.js';
|
|
4
|
+
export const WAKE_TABLE = [
|
|
5
|
+
{ phrase: '居家管家 帮助', key: 'home.help.lookup' },
|
|
6
|
+
{ phrase: '居家管家帮助', key: 'home.help.lookup' },
|
|
7
|
+
{ phrase: '居家管家能做什么', key: 'home.help.lookup' },
|
|
8
|
+
{ phrase: '查物品(HTML)', key: 'home.item.search' },
|
|
9
|
+
{ phrase: '看物品(HTML)', key: 'home.item.detail', needs: ['id'] },
|
|
10
|
+
{ phrase: '统物品(HTML)', key: 'home.stats.overview' },
|
|
11
|
+
{ phrase: '查物品', key: 'home.item.search' },
|
|
12
|
+
{ phrase: '看物品', key: 'home.item.detail', needs: ['id'] },
|
|
13
|
+
{ phrase: '录物品', key: 'home.item.add' },
|
|
14
|
+
{ phrase: '拍物品', key: 'home.item.add', preset: { photo: '1' } },
|
|
15
|
+
{ phrase: '改物品', key: 'home.item.update', needs: ['id'] },
|
|
16
|
+
{ phrase: '移物品', key: 'home.item.update', needs: ['id'], preset: { op: 'move' } },
|
|
17
|
+
{ phrase: '补物品', key: 'home.item.update', needs: ['id'], preset: { op: 'qty' } },
|
|
18
|
+
{ phrase: '减物品', key: 'home.item.update', needs: ['id'], preset: { op: 'qty' } },
|
|
19
|
+
{ phrase: '标物品', key: 'home.item.update', needs: ['id'], preset: { op: 'tags' } },
|
|
20
|
+
{ phrase: '废物品', key: 'home.item.update', needs: ['id'], preset: { op: 'status' } },
|
|
21
|
+
{ phrase: '借物品', key: 'home.item.update', needs: ['id'], preset: { op: 'status' } },
|
|
22
|
+
{ phrase: '修物品', key: 'home.item.update', needs: ['id'], preset: { op: 'status' } },
|
|
23
|
+
{ phrase: '盘物品', key: 'home.inventory.round', preset: { op: 'round' } },
|
|
24
|
+
{ phrase: '盘全部', key: 'home.inventory.round', preset: { op: 'round', scope: 'all' } },
|
|
25
|
+
{ phrase: '穿什么', key: 'home.outfit.pick' },
|
|
26
|
+
{ phrase: '带物品', key: 'home.trip.manage', preset: { mode: 'pack' } },
|
|
27
|
+
{ phrase: '归物品', key: 'home.trip.manage', preset: { mode: 'return' } },
|
|
28
|
+
{ phrase: '统物品', key: 'home.stats.overview', preset: { kind: 'summary' } },
|
|
29
|
+
{ phrase: '查高频', key: 'home.stats.overview', preset: { kind: 'summary' } },
|
|
30
|
+
{ phrase: '查低频', key: 'home.stats.alert', preset: { kind: 'idle' } },
|
|
31
|
+
{ phrase: '查过期', key: 'home.stats.alert', preset: { kind: 'expiring' } },
|
|
32
|
+
{ phrase: '看标签', key: 'home.tag.query' },
|
|
33
|
+
{ phrase: '合标签', key: 'home.tag.write', preset: { op: 'merge' } },
|
|
34
|
+
{ phrase: '查快递', key: 'home.shopping.query', preset: { kind: 'express' } },
|
|
35
|
+
{ phrase: '推位置', key: 'home.location.query', preset: { mode: 'suggest' } },
|
|
36
|
+
{ phrase: '找位置', key: 'home.location.query', preset: { mode: 'find' } },
|
|
37
|
+
{ phrase: '查账号', key: 'home.ticket.query', preset: { kind: 'account' } },
|
|
38
|
+
{ phrase: '存账号', key: 'home.ticket.write', preset: { kind: 'account', op: 'add' } },
|
|
39
|
+
{ phrase: '改账号', key: 'home.ticket.write', preset: { kind: 'account', op: 'update' } },
|
|
40
|
+
{ phrase: '看密码', key: 'home.ticket.write', preset: { kind: 'account', op: 'show' } },
|
|
41
|
+
{ phrase: '查异常', key: 'home.care.query', preset: { kind: 'lint' } },
|
|
42
|
+
{ phrase: '借用', key: 'home.care.query', preset: { kind: 'borrow' } },
|
|
43
|
+
{ phrase: '家人档案', key: 'home.care.query', preset: { kind: 'member' } },
|
|
44
|
+
{ phrase: '管位置', key: 'home.location.write', preset: { op: 'manage' } },
|
|
45
|
+
{ phrase: '固定位', key: 'home.location.write', preset: { op: 'fixed' } },
|
|
46
|
+
{ phrase: '收纳建议', key: 'home.location.query', preset: { mode: 'storage' } },
|
|
47
|
+
{ phrase: '空间视图', key: 'home.location.query', preset: { mode: 'space' } },
|
|
48
|
+
{ phrase: '查闲置', key: 'home.stats.alert', preset: { kind: 'idle' } },
|
|
49
|
+
{ phrase: '盘点统计', key: 'home.stats.overview', preset: { kind: 'inventory' } },
|
|
50
|
+
{ phrase: '首次使用', key: 'home.care.write', preset: { kind: 'init' } },
|
|
51
|
+
{ phrase: '备份导出', key: 'home.care.write', preset: { kind: 'backup' } },
|
|
52
|
+
{ phrase: '导入恢复', key: 'home.care.write', preset: { kind: 'import' } },
|
|
53
|
+
{ phrase: '批量录入', key: 'home.item.add', preset: { op: 'batch' } },
|
|
54
|
+
{ phrase: '补录', key: 'home.item.add', preset: { op: 'backfill' } },
|
|
55
|
+
{ phrase: '紧急定位', key: 'home.item.search', preset: { locate: true } },
|
|
56
|
+
{ phrase: '筛选浏览', key: 'home.item.search', preset: { browse: true } },
|
|
57
|
+
{ phrase: '拍照找物品', key: 'home.item.search', preset: { photo: true } },
|
|
58
|
+
{ phrase: '查重复', key: 'home.item.search', preset: { dupes: true } },
|
|
59
|
+
{ phrase: '合并物品', key: 'home.item.update', needs: ['id'], preset: { op: 'merge' } },
|
|
60
|
+
{ phrase: '撤销操作', key: 'home.item.update', preset: { op: 'undo' } },
|
|
61
|
+
{ phrase: '物品关联', key: 'home.item.update', needs: ['id'], preset: { op: 'relate' } },
|
|
62
|
+
{ phrase: '管标签', key: 'home.tag.write', preset: { op: 'overview' } },
|
|
63
|
+
{ phrase: '管分类', key: 'home.tag.write', preset: { op: 'category' } },
|
|
64
|
+
{ phrase: '整理建议', key: 'home.tag.write', preset: { op: 'tidy' } },
|
|
65
|
+
{ phrase: '查看照片', key: 'home.item.detail', needs: ['id'], preset: { view: 'photos' } },
|
|
66
|
+
{ phrase: '管照片', key: 'home.item.update', needs: ['id'], preset: { op: 'photo' } },
|
|
67
|
+
{ phrase: '照片墙', key: 'home.item.search', preset: { wall: true } },
|
|
68
|
+
{ phrase: '盘点记录', key: 'home.inventory.records' },
|
|
69
|
+
{ phrase: '差异处理', key: 'home.inventory.round', preset: { op: 'resolve' } },
|
|
70
|
+
{ phrase: '搬家盘点', key: 'home.inventory.round', preset: { op: 'move' } },
|
|
71
|
+
{ phrase: '历史', key: 'home.item.detail', needs: ['id'], preset: { view: 'history' } },
|
|
72
|
+
{ phrase: '数量变更', key: 'home.item.update', needs: ['id'], preset: { op: 'qty' } },
|
|
73
|
+
{ phrase: '状态变更', key: 'home.item.update', needs: ['id'], preset: { op: 'status' } },
|
|
74
|
+
{ phrase: '盘点', key: 'home.inventory.round', preset: { op: 'round' } },
|
|
75
|
+
{ phrase: '购物清单', key: 'home.shopping.query', preset: { kind: 'list' } },
|
|
76
|
+
{ phrase: '缺货检测', key: 'home.shopping.query', preset: { kind: 'missing' } },
|
|
77
|
+
{ phrase: '囤货盘点', key: 'home.shopping.query', preset: { kind: 'stock' } },
|
|
78
|
+
{ phrase: '查购买记录', key: 'home.ticket.query', preset: { kind: 'purchase' } },
|
|
79
|
+
{ phrase: '查上月购买', key: 'home.ticket.query', preset: { kind: 'purchase', range: 'last-month' } },
|
|
80
|
+
{ phrase: '查今年花费', key: 'home.ticket.query', preset: { kind: 'purchase', range: 'year' } },
|
|
81
|
+
{ phrase: '查退货窗口', key: 'home.ticket.query', preset: { kind: 'purchase', range: 'return' } },
|
|
82
|
+
{ phrase: '登记购买记录', key: 'home.ticket.write', preset: { kind: 'purchase', op: 'add' } },
|
|
83
|
+
{ phrase: '查保修状态', key: 'home.ticket.query', preset: { kind: 'warranty' } },
|
|
84
|
+
{ phrase: '登记保修', key: 'home.ticket.write', preset: { kind: 'warranty', op: 'register' } },
|
|
85
|
+
{ phrase: '记录维修', key: 'home.ticket.write', preset: { kind: 'warranty', op: 'repair' } },
|
|
86
|
+
{ phrase: '设置保养周期', key: 'home.ticket.write', preset: { kind: 'warranty', op: 'cycle' } },
|
|
87
|
+
{ phrase: '执行保养', key: 'home.ticket.write', preset: { kind: 'warranty', op: 'maintain' } },
|
|
88
|
+
{ phrase: '查证件到期', key: 'home.ticket.query', preset: { kind: 'cert' } },
|
|
89
|
+
{ phrase: '登记证件', key: 'home.ticket.write', preset: { kind: 'cert', op: 'add' } },
|
|
90
|
+
{ phrase: '证件归档', key: 'home.ticket.write', preset: { kind: 'cert', op: 'archive' } },
|
|
91
|
+
{ phrase: '更新证件', key: 'home.ticket.write', preset: { kind: 'cert', op: 'update' } },
|
|
92
|
+
{ phrase: '衣橱分析', key: 'home.outfit.pick', preset: { kind: 'wardrobe' } },
|
|
93
|
+
{ phrase: '换季', key: 'home.outfit.pick', preset: { kind: 'season' } },
|
|
94
|
+
{ phrase: '旅行穿搭', key: 'home.outfit.pick', preset: { kind: 'trip-plan' } },
|
|
95
|
+
{ phrase: '改购物清单', key: 'home.shopping.write', preset: { op: 'check' } },
|
|
96
|
+
];
|
|
97
|
+
// 废弃词(SM9 外联动 3 词,本技能不路由;combos 登记走后续票)。
|
|
98
|
+
export const DEPRECATED_PHRASES = ['联动总览', '记到卡路里', '记到记账'];
|
|
99
|
+
const SORTED = [...WAKE_TABLE].sort((a, b) => b.phrase.length - a.phrase.length);
|
|
100
|
+
export function routeWakeword(text, ctx = {}) {
|
|
101
|
+
if (typeof text !== 'string' || text.length === 0)
|
|
102
|
+
throw new HomePolicyError('POLICY_NO_MATCH', '唤醒词为空');
|
|
103
|
+
const hit = SORTED.find((e) => text.includes(e.phrase));
|
|
104
|
+
if (!hit) {
|
|
105
|
+
throw new HomePolicyError('POLICY_NO_MATCH', '无命中唤醒词:' + text + '(联动 3 词走后续票)');
|
|
106
|
+
}
|
|
107
|
+
for (const s of hit.needs || []) {
|
|
108
|
+
if (ctx[s] === undefined || ctx[s] === null || ctx[s] === '') {
|
|
109
|
+
throw new HomePolicyError('POLICY_MISSING_SLOT', '缺槽位 ' + s + ':' + hit.phrase);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return { key: hit.key, params: { ...(hit.preset || {}), ...pickCtx(ctx, hit.needs || []) } };
|
|
113
|
+
}
|
|
114
|
+
function pickCtx(ctx, needs) {
|
|
115
|
+
const o = {};
|
|
116
|
+
for (const k of needs)
|
|
117
|
+
o[k] = ctx[k];
|
|
118
|
+
return o;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=wakewords.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wakewords.js","sourceRoot":"","sources":["../../src/policy/wakewords.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Envelope, type EnvelopeShape } from 'base-link-core';
|
|
2
|
+
export declare const HOME_KEY_SHAPES: Record<string, EnvelopeShape>;
|
|
3
|
+
export declare function homeShapeFor(key: string): EnvelopeShape;
|
|
4
|
+
export declare function buildHomeEnvelope(key: string, data: unknown): Envelope;
|
|
5
|
+
export declare function parseHomeEnvelope(input: unknown): Envelope;
|
|
6
|
+
//# sourceMappingURL=envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../src/render/envelope.ts"],"names":[],"mappings":"AACA,OAAO,EAAmD,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAsBzD,CAAC;AAEF,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAIvD;AAGD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,CAatE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAG1D"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// 渲染层·envelope:21 联动 key×shape 映射(拆分表);key 字符串后续票落表时冻结,此处只做形状分配与全字段校验。
|
|
2
|
+
import { createEnvelope, parseEnvelope, parseRegistryKey } from 'base-link-core';
|
|
3
|
+
import { HomeRenderError } from './errors.js';
|
|
4
|
+
export const HOME_KEY_SHAPES = {
|
|
5
|
+
'home.item.search': 'list',
|
|
6
|
+
'home.item.detail': 'detail',
|
|
7
|
+
'home.item.add': 'receipt',
|
|
8
|
+
'home.item.update': 'receipt',
|
|
9
|
+
'home.tag.query': 'list',
|
|
10
|
+
'home.tag.write': 'receipt',
|
|
11
|
+
'home.inventory.round': 'receipt',
|
|
12
|
+
'home.inventory.records': 'list',
|
|
13
|
+
'home.location.query': 'list',
|
|
14
|
+
'home.location.write': 'receipt',
|
|
15
|
+
'home.outfit.pick': 'list',
|
|
16
|
+
'home.trip.manage': 'receipt',
|
|
17
|
+
'home.stats.overview': 'stat',
|
|
18
|
+
'home.stats.alert': 'list',
|
|
19
|
+
'home.shopping.query': 'list',
|
|
20
|
+
'home.shopping.write': 'receipt',
|
|
21
|
+
'home.ticket.query': 'list',
|
|
22
|
+
'home.ticket.write': 'receipt',
|
|
23
|
+
'home.care.query': 'list',
|
|
24
|
+
'home.care.write': 'receipt',
|
|
25
|
+
'home.help.lookup': 'list',
|
|
26
|
+
};
|
|
27
|
+
export function homeShapeFor(key) {
|
|
28
|
+
const s = HOME_KEY_SHAPES[key];
|
|
29
|
+
if (!s)
|
|
30
|
+
throw new HomeRenderError('HOME_UNKNOWN_KEY', '未知联动 key:' + key);
|
|
31
|
+
return s;
|
|
32
|
+
}
|
|
33
|
+
// 建 envelope:key 先过命名空间,再按分配形状做全字段校验;错形状载荷即 throw。
|
|
34
|
+
export function buildHomeEnvelope(key, data) {
|
|
35
|
+
let parsedKey = '';
|
|
36
|
+
try {
|
|
37
|
+
parsedKey = parseRegistryKey(key).key;
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
throw new HomeRenderError('HOME_UNKNOWN_KEY', '非法 key:' + e.message);
|
|
41
|
+
}
|
|
42
|
+
const shape = homeShapeFor(parsedKey);
|
|
43
|
+
if (typeof data !== 'object' || data === null || Array.isArray(data)) {
|
|
44
|
+
throw new HomeRenderError('HOME_BAD_PAYLOAD', '载荷须为对象:' + parsedKey);
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
return createEnvelope({ skill: 'home', shape, key: parsedKey, data: data });
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
throw new HomeRenderError('HOME_SHAPE_MISMATCH', shape + ' 全字段未过:' + e.message);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function parseHomeEnvelope(input) {
|
|
54
|
+
try {
|
|
55
|
+
return parseEnvelope(input);
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
throw new HomeRenderError('HOME_BAD_PAYLOAD', 'envelope 非法:' + e.message);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=envelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.js","sourceRoot":"","sources":["../../src/render/envelope.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,gBAAgB,EAAqC,MAAM,gBAAgB,CAAC;AACpH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,CAAC,MAAM,eAAe,GAAkC;IAC5D,kBAAkB,EAAE,MAAM;IAC1B,kBAAkB,EAAE,QAAQ;IAC5B,eAAe,EAAE,SAAS;IAC1B,kBAAkB,EAAE,SAAS;IAC7B,gBAAgB,EAAE,MAAM;IACxB,gBAAgB,EAAE,SAAS;IAC3B,sBAAsB,EAAE,SAAS;IACjC,wBAAwB,EAAE,MAAM;IAChC,qBAAqB,EAAE,MAAM;IAC7B,qBAAqB,EAAE,SAAS;IAChC,kBAAkB,EAAE,MAAM;IAC1B,kBAAkB,EAAE,SAAS;IAC7B,qBAAqB,EAAE,MAAM;IAC7B,kBAAkB,EAAE,MAAM;IAC1B,qBAAqB,EAAE,MAAM;IAC7B,qBAAqB,EAAE,SAAS;IAChC,mBAAmB,EAAE,MAAM;IAC3B,mBAAmB,EAAE,SAAS;IAC9B,iBAAiB,EAAE,MAAM;IACzB,iBAAiB,EAAE,SAAS;IAC5B,kBAAkB,EAAE,MAAM;CAC3B,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,CAAC,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,WAAW,GAAG,GAAG,CAAC,CAAC;IACzE,OAAO,CAAC,CAAC;AACX,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,iBAAiB,CAAC,GAAW,EAAE,IAAa;IAC1D,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,IAAI,CAAC;QAAC,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;IAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,CAAC;QAAC,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,SAAS,GAAI,CAAW,CAAC,OAAO,CAAC,CAAC;IAAC,CAAC;IAC9F,MAAM,KAAK,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACtC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,SAAS,GAAG,SAAS,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,CAAC;QACH,OAAO,cAAc,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,IAAa,EAAE,CAAC,CAAC;IACvF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,eAAe,CAAC,qBAAqB,EAAE,KAAK,GAAG,SAAS,GAAI,CAAW,CAAC,OAAO,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,CAAC;QAAC,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;IAAC,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC;QAAC,MAAM,IAAI,eAAe,CAAC,kBAAkB,EAAE,cAAc,GAAI,CAAW,CAAC,OAAO,CAAC,CAAC;IAAC,CAAC;AACrG,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare class HomeRenderError extends Error {
|
|
2
|
+
readonly code: 'HOME_UNKNOWN_KEY' | 'HOME_SHAPE_MISMATCH' | 'HOME_BAD_PAYLOAD' | 'HOME_HTML_TOO_LARGE' | 'HOME_TEMPLATE_MISSING' | 'HOME_MARKER_INVALID';
|
|
3
|
+
constructor(code: HomeRenderError['code'], message: string);
|
|
4
|
+
}
|
|
5
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/render/errors.ts"],"names":[],"mappings":"AACA,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EACT,kBAAkB,GAAG,qBAAqB,GAAG,kBAAkB,GAC/D,qBAAqB,GAAG,uBAAuB,GAAG,qBAAqB,CAAC;gBAChE,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM;CAK3D"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// 渲染层错误:坏 key/形状/载荷/超体积/缺模板一律 throw(fallback 形状是唯一的显式降级通道)。
|
|
2
|
+
export class HomeRenderError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
constructor(code, message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = 'HomeRenderError';
|
|
7
|
+
this.code = code;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/render/errors.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,CAE+D;IAC5E,YAAY,IAA6B,EAAE,OAAe;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Envelope } from 'base-link-core';
|
|
2
|
+
export declare const HOME_HTML_MAX_BYTES: number;
|
|
3
|
+
export declare function escapeHtml(s: string): string;
|
|
4
|
+
export declare function renderEnvelopeHtml(env: Envelope): string;
|
|
5
|
+
export declare function estimateBytes(html: string): number;
|
|
6
|
+
export declare function assertHtmlSize(html: string, max?: number): void;
|
|
7
|
+
export declare const SHARED_CSS_MARKER = "<!--SHARED-CSS-->";
|
|
8
|
+
export declare const SHARED_HELPERS_MARKER = "<!--SHARED-HELPERS-->";
|
|
9
|
+
export declare const CONTENT_MARKER = "<!--CONTENT-->";
|
|
10
|
+
export declare const SHARED_CSS = ".page{font-family:system-ui,sans-serif;max-width:720px;margin:0 auto;padding:12px}.item{border:1px solid #ddd;border-radius:8px;padding:8px;margin:8px 0}.item-head{display:flex;gap:8px;align-items:center}.badge{background:#eee;border-radius:4px;padding:0 6px}.receipt{background:#f0fff0;border:1px solid #090;border-radius:8px;padding:12px}.stat{display:flex;gap:8px}.analysis{white-space:pre-wrap}.hm-empty{color:#888}";
|
|
11
|
+
export declare const SHARED_HELPERS = "<script>function copyItem(id){var e=document.getElementById(id);if(e&&navigator.clipboard){navigator.clipboard.writeText(e.innerText);}}</script>";
|
|
12
|
+
export declare function fillTemplate(template: string, contentHtml: string): string;
|
|
13
|
+
//# sourceMappingURL=html.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/render/html.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG/C,eAAO,MAAM,mBAAmB,QAAa,CAAC;AAE9C,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE5C;AAiBD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAoBxD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAA4C;AAG/F,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAsB,GAAG,IAAI,CAI5E;AAGD,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AACrD,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAC7D,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAE/C,eAAO,MAAM,UAAU,waAAwa,CAAC;AAChc,eAAO,MAAM,cAAc,sJAAsJ,CAAC;AAElL,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAU1E"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { HomeRenderError } from './errors.js';
|
|
2
|
+
export const HOME_HTML_MAX_BYTES = 256 * 1024;
|
|
3
|
+
export function escapeHtml(s) {
|
|
4
|
+
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
5
|
+
}
|
|
6
|
+
function itemHtml(n) {
|
|
7
|
+
const id = escapeHtml(String(n.id ?? ''));
|
|
8
|
+
const name = escapeHtml(String(n.name ?? ''));
|
|
9
|
+
const loc = escapeHtml(String(n.location ?? n.locations ?? ''));
|
|
10
|
+
const qty = n.quantity !== undefined ? ' ×' + escapeHtml(String(n.quantity)) : '';
|
|
11
|
+
return '<div class="item"><div class="item-head"><span class="id">#' + id + '</span><span class="name">' + name + '</span></div><div class="content">' + loc + qty + '</div></div>';
|
|
12
|
+
}
|
|
13
|
+
function listHtml(items) {
|
|
14
|
+
if (!items.length)
|
|
15
|
+
return '<div class="hm-empty">暂无记录</div>';
|
|
16
|
+
return items.map((x) => itemHtml(x)).join('');
|
|
17
|
+
}
|
|
18
|
+
// 按形状渲染 envelope 为 section 页;未知形状 throw 不返空页。
|
|
19
|
+
// #43 H2:analysis/fallback 经 HOME_KEY_SHAPES 不可达(21 键仅 list/detail/receipt/stat),保留作显式降级与未来扩展直调分支,单测直构 envelope 覆盖。
|
|
20
|
+
export function renderEnvelopeHtml(env) {
|
|
21
|
+
const head = '<section data-skill="home" data-shape="' + env.shape + '" data-key="' + escapeHtml(env.key) + '">';
|
|
22
|
+
const d = env.data;
|
|
23
|
+
switch (env.shape) {
|
|
24
|
+
case 'list': return head + listHtml(d.items) + '</section>';
|
|
25
|
+
case 'detail': return head + itemHtml(d.item) + '</section>';
|
|
26
|
+
case 'receipt': {
|
|
27
|
+
let msg = String(d.message ?? '');
|
|
28
|
+
// 看密码脱敏:HTML 快照不落明文(JSON 真相仍含明文,仅对话回显)。
|
|
29
|
+
if (env.key === 'home.ticket.write' && /密码/.test(msg))
|
|
30
|
+
msg = '密码已脱敏(仅对话 JSON 回显,不进 HTML)';
|
|
31
|
+
return head + '<div class="receipt">' + escapeHtml(msg) + '</div></section>';
|
|
32
|
+
}
|
|
33
|
+
case 'stat': {
|
|
34
|
+
const rows = Object.entries((d.metrics || {}));
|
|
35
|
+
return head + rows.map(([k, v]) => '<div class="stat"><b>' + v + '</b><span>' + escapeHtml(k) + '</span></div>').join('') + '</section>';
|
|
36
|
+
}
|
|
37
|
+
case 'analysis': return head + '<div class="analysis">' + escapeHtml(String(d.summary ?? '')) + '</div></section>';
|
|
38
|
+
case 'fallback': return head + '<div data-degraded="1">' + escapeHtml(String(d.reason ?? '')) + '</div></section>';
|
|
39
|
+
default: throw new HomeRenderError('HOME_SHAPE_MISMATCH', '无法渲染形状:' + String(env.shape));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export function estimateBytes(html) { return Buffer.byteLength(html, 'utf8'); }
|
|
43
|
+
// 体积门:超限 throw(调用方走 fallback 形状显式降级,不静默截断)。
|
|
44
|
+
export function assertHtmlSize(html, max = HOME_HTML_MAX_BYTES) {
|
|
45
|
+
if (estimateBytes(html) > max) {
|
|
46
|
+
throw new HomeRenderError('HOME_HTML_TOO_LARGE', 'HTML 超体积:' + estimateBytes(html) + ' > ' + max);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// 共享标记填充:CSS/HELPERS/CONTENT 三标记各恰出现 1 次,否则 throw。
|
|
50
|
+
export const SHARED_CSS_MARKER = '<!--SHARED-CSS-->';
|
|
51
|
+
export const SHARED_HELPERS_MARKER = '<!--SHARED-HELPERS-->';
|
|
52
|
+
export const CONTENT_MARKER = '<!--CONTENT-->';
|
|
53
|
+
export const SHARED_CSS = '.page{font-family:system-ui,sans-serif;max-width:720px;margin:0 auto;padding:12px}.item{border:1px solid #ddd;border-radius:8px;padding:8px;margin:8px 0}.item-head{display:flex;gap:8px;align-items:center}.badge{background:#eee;border-radius:4px;padding:0 6px}.receipt{background:#f0fff0;border:1px solid #090;border-radius:8px;padding:12px}.stat{display:flex;gap:8px}.analysis{white-space:pre-wrap}.hm-empty{color:#888}';
|
|
54
|
+
export const SHARED_HELPERS = '<script>function copyItem(id){var e=document.getElementById(id);if(e&&navigator.clipboard){navigator.clipboard.writeText(e.innerText);}}</script>';
|
|
55
|
+
export function fillTemplate(template, contentHtml) {
|
|
56
|
+
for (const m of [SHARED_CSS_MARKER, SHARED_HELPERS_MARKER, CONTENT_MARKER]) {
|
|
57
|
+
if (template.split(m).length - 1 !== 1) {
|
|
58
|
+
throw new HomeRenderError('HOME_MARKER_INVALID', '标记须恰出现 1 次:' + m);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return template
|
|
62
|
+
.split(SHARED_CSS_MARKER).join('<style>' + SHARED_CSS + '</style>')
|
|
63
|
+
.split(SHARED_HELPERS_MARKER).join(SHARED_HELPERS)
|
|
64
|
+
.split(CONTENT_MARKER).join(contentHtml);
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=html.js.map
|