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.
Files changed (106) hide show
  1. package/dist/cli/cmd_read.d.ts +3 -0
  2. package/dist/cli/cmd_read.d.ts.map +1 -0
  3. package/dist/cli/cmd_read.js +868 -0
  4. package/dist/cli/cmd_read.js.map +1 -0
  5. package/dist/fetch/db.d.ts +107 -0
  6. package/dist/fetch/db.d.ts.map +1 -0
  7. package/dist/fetch/db.js +433 -0
  8. package/dist/fetch/db.js.map +1 -0
  9. package/dist/fetch/domains.d.ts +51 -0
  10. package/dist/fetch/domains.d.ts.map +1 -0
  11. package/dist/fetch/domains.js +203 -0
  12. package/dist/fetch/domains.js.map +1 -0
  13. package/dist/fetch/errors.d.ts +11 -0
  14. package/dist/fetch/errors.d.ts.map +1 -0
  15. package/dist/fetch/errors.js +18 -0
  16. package/dist/fetch/errors.js.map +1 -0
  17. package/dist/fetch/index.d.ts +6 -0
  18. package/dist/fetch/index.d.ts.map +1 -0
  19. package/dist/fetch/index.js +5 -0
  20. package/dist/fetch/index.js.map +1 -0
  21. package/dist/fetch/paths.d.ts +6 -0
  22. package/dist/fetch/paths.d.ts.map +1 -0
  23. package/dist/fetch/paths.js +31 -0
  24. package/dist/fetch/paths.js.map +1 -0
  25. package/dist/help/index.d.ts +3 -0
  26. package/dist/help/index.d.ts.map +1 -0
  27. package/dist/help/index.js +2 -0
  28. package/dist/help/index.js.map +1 -0
  29. package/dist/help/lookup.d.ts +11 -0
  30. package/dist/help/lookup.d.ts.map +1 -0
  31. package/dist/help/lookup.js +52 -0
  32. package/dist/help/lookup.js.map +1 -0
  33. package/dist/index.d.ts +5 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +6 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/policy/care.d.ts +4 -0
  38. package/dist/policy/care.d.ts.map +1 -0
  39. package/dist/policy/care.js +12 -0
  40. package/dist/policy/care.js.map +1 -0
  41. package/dist/policy/category.d.ts +8 -0
  42. package/dist/policy/category.d.ts.map +1 -0
  43. package/dist/policy/category.js +44 -0
  44. package/dist/policy/category.js.map +1 -0
  45. package/dist/policy/index.d.ts +9 -0
  46. package/dist/policy/index.d.ts.map +1 -0
  47. package/dist/policy/index.js +6 -0
  48. package/dist/policy/index.js.map +1 -0
  49. package/dist/policy/item.d.ts +18 -0
  50. package/dist/policy/item.d.ts.map +1 -0
  51. package/dist/policy/item.js +81 -0
  52. package/dist/policy/item.js.map +1 -0
  53. package/dist/policy/ticket.d.ts +6 -0
  54. package/dist/policy/ticket.d.ts.map +1 -0
  55. package/dist/policy/ticket.js +25 -0
  56. package/dist/policy/ticket.js.map +1 -0
  57. package/dist/policy/wakewords.d.ts +15 -0
  58. package/dist/policy/wakewords.d.ts.map +1 -0
  59. package/dist/policy/wakewords.js +120 -0
  60. package/dist/policy/wakewords.js.map +1 -0
  61. package/dist/render/envelope.d.ts +6 -0
  62. package/dist/render/envelope.d.ts.map +1 -0
  63. package/dist/render/envelope.js +61 -0
  64. package/dist/render/envelope.js.map +1 -0
  65. package/dist/render/errors.d.ts +5 -0
  66. package/dist/render/errors.d.ts.map +1 -0
  67. package/dist/render/errors.js +10 -0
  68. package/dist/render/errors.js.map +1 -0
  69. package/dist/render/html.d.ts +13 -0
  70. package/dist/render/html.d.ts.map +1 -0
  71. package/dist/render/html.js +66 -0
  72. package/dist/render/html.js.map +1 -0
  73. package/dist/render/index.d.ts +8 -0
  74. package/dist/render/index.d.ts.map +1 -0
  75. package/dist/render/index.js +6 -0
  76. package/dist/render/index.js.map +1 -0
  77. package/dist/render/templates.d.ts +5 -0
  78. package/dist/render/templates.d.ts.map +1 -0
  79. package/dist/render/templates.js +68 -0
  80. package/dist/render/templates.js.map +1 -0
  81. package/dist/render/views.d.ts +83 -0
  82. package/dist/render/views.d.ts.map +1 -0
  83. package/dist/render/views.js +56 -0
  84. package/dist/render/views.js.map +1 -0
  85. package/package.json +32 -0
  86. package/templates/care_query.html +16 -0
  87. package/templates/care_receipt.html +16 -0
  88. package/templates/help.html +16 -0
  89. package/templates/inventory_records.html +16 -0
  90. package/templates/inventory_round.html +16 -0
  91. package/templates/item_detail.html +16 -0
  92. package/templates/item_receipt.html +16 -0
  93. package/templates/item_search.html +16 -0
  94. package/templates/item_update_receipt.html +16 -0
  95. package/templates/location_query.html +16 -0
  96. package/templates/location_receipt.html +16 -0
  97. package/templates/outfit_pick.html +16 -0
  98. package/templates/shopping_query.html +16 -0
  99. package/templates/shopping_receipt.html +16 -0
  100. package/templates/stats_alert.html +16 -0
  101. package/templates/stats_overview.html +16 -0
  102. package/templates/tag_query.html +16 -0
  103. package/templates/tag_receipt.html +16 -0
  104. package/templates/ticket_query.html +16 -0
  105. package/templates/ticket_receipt.html +16 -0
  106. 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, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
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