skill-schedule 0.2.0 → 0.2.1

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 (116) hide show
  1. package/SKILL.md +12 -6
  2. package/dist/cli/cmd_read.js +96 -104
  3. package/dist/cli/cmd_read.js.map +1 -1
  4. package/dist/cli/config.d.ts +16 -0
  5. package/dist/cli/config.d.ts.map +1 -0
  6. package/dist/cli/config.js +84 -0
  7. package/dist/cli/config.js.map +1 -0
  8. package/dist/cli/health.d.ts +7 -0
  9. package/dist/cli/health.d.ts.map +1 -0
  10. package/dist/cli/health.js +32 -0
  11. package/dist/cli/health.js.map +1 -0
  12. package/dist/config.d.ts +43 -0
  13. package/dist/config.d.ts.map +1 -0
  14. package/dist/config.js +64 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/fetch/db.d.ts +4 -0
  17. package/dist/fetch/db.d.ts.map +1 -1
  18. package/dist/fetch/db.js +10 -0
  19. package/dist/fetch/db.js.map +1 -1
  20. package/dist/fetch/errors.d.ts +1 -1
  21. package/dist/fetch/errors.d.ts.map +1 -1
  22. package/dist/fetch/errors.js.map +1 -1
  23. package/dist/fetch/feishu.d.ts +33 -9
  24. package/dist/fetch/feishu.d.ts.map +1 -1
  25. package/dist/fetch/feishu.js +137 -23
  26. package/dist/fetch/feishu.js.map +1 -1
  27. package/dist/fetch/index.d.ts +4 -4
  28. package/dist/fetch/index.d.ts.map +1 -1
  29. package/dist/fetch/index.js +3 -3
  30. package/dist/fetch/index.js.map +1 -1
  31. package/dist/fetch/paths.d.ts +5 -3
  32. package/dist/fetch/paths.d.ts.map +1 -1
  33. package/dist/fetch/paths.js +19 -24
  34. package/dist/fetch/paths.js.map +1 -1
  35. package/dist/health.d.ts +41 -0
  36. package/dist/health.d.ts.map +1 -0
  37. package/dist/health.js +580 -0
  38. package/dist/health.js.map +1 -0
  39. package/dist/help/helpFile.d.ts +6 -27
  40. package/dist/help/helpFile.d.ts.map +1 -1
  41. package/dist/help/helpFile.js +13 -50
  42. package/dist/help/helpFile.js.map +1 -1
  43. package/dist/help/helpPaths.d.ts +13 -12
  44. package/dist/help/helpPaths.d.ts.map +1 -1
  45. package/dist/help/helpPaths.js +23 -29
  46. package/dist/help/helpPaths.js.map +1 -1
  47. package/dist/help/lookup.d.ts.map +1 -1
  48. package/dist/help/lookup.js +8 -1
  49. package/dist/help/lookup.js.map +1 -1
  50. package/dist/help/output.d.ts +15 -14
  51. package/dist/help/output.d.ts.map +1 -1
  52. package/dist/help/output.js +40 -53
  53. package/dist/help/output.js.map +1 -1
  54. package/dist/help/scenes/help-assets.d.ts +10 -10
  55. package/dist/help/scenes/help-assets.d.ts.map +1 -1
  56. package/dist/help/scenes/help-assets.js +10 -10
  57. package/dist/help/scenes/help-assets.js.map +1 -1
  58. package/dist/plan/check.d.ts +3 -0
  59. package/dist/plan/check.d.ts.map +1 -0
  60. package/dist/plan/check.js +71 -0
  61. package/dist/plan/check.js.map +1 -0
  62. package/dist/plan/context.d.ts +18 -0
  63. package/dist/plan/context.d.ts.map +1 -0
  64. package/dist/plan/context.js +4 -0
  65. package/dist/plan/context.js.map +1 -0
  66. package/dist/plan/ensure.d.ts +4 -0
  67. package/dist/plan/ensure.d.ts.map +1 -0
  68. package/dist/plan/ensure.js +140 -0
  69. package/dist/plan/ensure.js.map +1 -0
  70. package/dist/plan/index.d.ts +8 -0
  71. package/dist/plan/index.d.ts.map +1 -0
  72. package/dist/plan/index.js +56 -0
  73. package/dist/plan/index.js.map +1 -0
  74. package/dist/plan/iso.d.ts +27 -0
  75. package/dist/plan/iso.d.ts.map +1 -0
  76. package/dist/plan/iso.js +55 -0
  77. package/dist/plan/iso.js.map +1 -0
  78. package/dist/plan/overview.d.ts +23 -0
  79. package/dist/plan/overview.d.ts.map +1 -0
  80. package/dist/plan/overview.js +38 -0
  81. package/dist/plan/overview.js.map +1 -0
  82. package/dist/plan/pull.d.ts +25 -0
  83. package/dist/plan/pull.d.ts.map +1 -0
  84. package/dist/plan/pull.js +83 -0
  85. package/dist/plan/pull.js.map +1 -0
  86. package/dist/plan/receipt.d.ts +52 -0
  87. package/dist/plan/receipt.d.ts.map +1 -0
  88. package/dist/plan/receipt.js +57 -0
  89. package/dist/plan/receipt.js.map +1 -0
  90. package/dist/plan/remoteDay.d.ts +62 -0
  91. package/dist/plan/remoteDay.d.ts.map +1 -0
  92. package/dist/plan/remoteDay.js +102 -0
  93. package/dist/plan/remoteDay.js.map +1 -0
  94. package/dist/plan/single.d.ts +4 -0
  95. package/dist/plan/single.d.ts.map +1 -0
  96. package/dist/plan/single.js +176 -0
  97. package/dist/plan/single.js.map +1 -0
  98. package/dist/plan/sync.d.ts +14 -0
  99. package/dist/plan/sync.d.ts.map +1 -0
  100. package/dist/plan/sync.js +158 -0
  101. package/dist/plan/sync.js.map +1 -0
  102. package/dist/plan/upsert.d.ts +5 -0
  103. package/dist/plan/upsert.d.ts.map +1 -0
  104. package/dist/plan/upsert.js +102 -0
  105. package/dist/plan/upsert.js.map +1 -0
  106. package/dist/policy/index.d.ts +2 -2
  107. package/dist/policy/index.d.ts.map +1 -1
  108. package/dist/policy/index.js +1 -1
  109. package/dist/policy/index.js.map +1 -1
  110. package/dist/policy/plan.d.ts +16 -1
  111. package/dist/policy/plan.d.ts.map +1 -1
  112. package/dist/policy/plan.js +51 -1
  113. package/dist/policy/plan.js.map +1 -1
  114. package/dist/policy/wakewords.js +4 -4
  115. package/dist/policy/wakewords.js.map +1 -1
  116. package/package.json +1 -1
@@ -0,0 +1,55 @@
1
+ // 日程与计划·时间口径(能力内部件):本地库的 (日期, "HH:MM") ↔ 飞书 ISO 8601(+08:00)。
2
+ // 一条口径只写一处:24:00 在本地是「当天末」,在飞书是「次日 00:00」——两侧互相换算都走这里。
3
+ // 老出处:`feishu_sync.py:628`(`_to_iso`)、`:639`(`_from_iso`)、`:459`(`_ensure_iso`)、
4
+ // `schedule_cli.py:1431`(跨日边界:飞书 end 次日 00:00 等价于本地 23:59)。
5
+ export const TZ_SUFFIX = '+08:00';
6
+ /** 分片拉取的窗口宽度(小时)。老家 `feishu_sync.py:522` 的 `timedelta(hours=6)`。 */
7
+ export const SHARD_HOURS = 6;
8
+ function pad(n) { return String(n).padStart(2, '0'); }
9
+ export function nextDay(date) {
10
+ const [y, m, d] = date.split('-').map(Number);
11
+ const t = new Date(y, m - 1, d);
12
+ t.setDate(t.getDate() + 1);
13
+ return t.getFullYear() + '-' + pad(t.getMonth() + 1) + '-' + pad(t.getDate());
14
+ }
15
+ /** 本地 (日期, HH:MM) → 飞书 ISO。`24:00` 换到次日 `00:00`(飞书日历不接受 24:00)。 */
16
+ export function toFeishuISO(date, hhmm) {
17
+ if (hhmm === '24:00')
18
+ return nextDay(date) + 'T00:00:00' + TZ_SUFFIX;
19
+ return date + 'T' + hhmm + ':00' + TZ_SUFFIX;
20
+ }
21
+ export function dayStartISO(date) { return date + 'T00:00:00' + TZ_SUFFIX; }
22
+ export function dayEndISO(date) { return date + 'T23:59:59' + TZ_SUFFIX; }
23
+ /** ISO → 'HH:MM';抠不出来返空串(不猜)。 */
24
+ export function hhmmOfISO(iso) {
25
+ const i = iso.indexOf('T');
26
+ if (i < 0 || i + 6 > iso.length)
27
+ return '';
28
+ return iso.slice(i + 1, i + 6);
29
+ }
30
+ export function dateOfISO(iso) { return iso.slice(0, 10); }
31
+ /**
32
+ * 远端一对 (start, end) ISO → 本地槽位 (HH:MM, HH:MM)。
33
+ * 跨日规则:结束落在次日 00:00 ⇒ 本地记 23:59(两条口径在这里对上,别处不许再抄一遍)。
34
+ */
35
+ export function remoteSlotOf(startISO, endISO) {
36
+ let end = hhmmOfISO(endISO);
37
+ if (end === '00:00' && dateOfISO(startISO) !== dateOfISO(endISO))
38
+ end = '23:59';
39
+ return { start: hhmmOfISO(startISO), end };
40
+ }
41
+ /** 一天的检索分片:按 6 小时切片(规避 `+search-event` 单次返回上限)。 */
42
+ export function shardWindows(date) {
43
+ const out = [];
44
+ for (let h = 0; h < 24; h += SHARD_HOURS) {
45
+ const endH = h + SHARD_HOURS;
46
+ out.push({
47
+ start: date + 'T' + pad(h) + ':00:00' + TZ_SUFFIX,
48
+ end: endH >= 24 ? nextDay(date) + 'T00:00:00' + TZ_SUFFIX : date + 'T' + pad(endH) + ':00:00' + TZ_SUFFIX,
49
+ });
50
+ }
51
+ return out;
52
+ }
53
+ /** 24 小时的槽位标签(聚合视图用):`00:00 - 01:00`。 */
54
+ export function hourLabel(h) { return pad(h) + ':00 - ' + pad(h + 1) + ':00'; }
55
+ //# sourceMappingURL=iso.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iso.js","sourceRoot":"","sources":["../../src/plan/iso.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { ScheduleDb } from '../fetch/index.js';
2
+ export interface PlanHourRow {
3
+ hour: number;
4
+ label: string;
5
+ text: string;
6
+ }
7
+ export interface PlanDayRow {
8
+ date: string;
9
+ hours: PlanHourRow[];
10
+ /** 填了几格(0..24)——一眼看出这天有没有排过。 */
11
+ plannedHours: number;
12
+ createdAt: string | null;
13
+ updatedAt: string | null;
14
+ }
15
+ export interface PlanOverviewPayload {
16
+ items: PlanDayRow[];
17
+ total: number;
18
+ dates: string[];
19
+ view: 'aggregate';
20
+ note: string;
21
+ }
22
+ export declare function buildPlanOverview(handle: ScheduleDb, dates: string[]): PlanOverviewPayload;
23
+ //# sourceMappingURL=overview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overview.d.ts","sourceRoot":"","sources":["../../src/plan/overview.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAC1E,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,gCAAgC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAID,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,mBAAmB,CAG1F"}
@@ -0,0 +1,38 @@
1
+ // 日程与计划·24h 聚合视图与多日查询(#15/#16)。
2
+ //
3
+ // 分桶口径(照老实物 `schedule_db.py:697-746` 的 `_read_plan_dict`):
4
+ // 每条活跃事件按 **time_start 的整点**落桶,同一小时内多条以 `+` 拼接;
5
+ // 空桶出力「未规划」;日期随附该日的 created_at/updated_at。
6
+ // **有意保留的损失**(老实物自己在输出里就点名了):聚合视图丢 notes/飞书同步状态/ID——
7
+ // 想要全字段请走 `查日程`(`plan.today` 的 list 档),聚合视图只服务「一天 24 格长什么样」。
8
+ // 多日查询(#16)是这条视图的独门能力:一次给多个日期,逐日一段。
9
+ import { listPlanEvents, getPlanTimestamps } from '../fetch/index.js';
10
+ import { hourLabel } from './iso.js';
11
+ const NOTE = '这是 24h 聚合视图:同小时内的多条事件用 + 合并,丢 notes/飞书同步状态/ID;要看全字段请用「查日程」。';
12
+ export function buildPlanOverview(handle, dates) {
13
+ const items = dates.map((date) => buildDay(handle, date));
14
+ return { items, total: items.length, dates, view: 'aggregate', note: NOTE };
15
+ }
16
+ function buildDay(handle, date) {
17
+ const events = listPlanEvents(handle, date);
18
+ const bucket = Array.from({ length: 24 }, () => []);
19
+ for (const e of events) {
20
+ const h = Number(e.time_start.slice(0, 2));
21
+ if (Number.isInteger(h) && h >= 0 && h <= 23)
22
+ bucket[h].push(e.title.trim());
23
+ }
24
+ const hours = bucket.map((titles, h) => ({
25
+ hour: h,
26
+ label: hourLabel(h),
27
+ text: titles.length ? titles.join('+') : '未规划',
28
+ }));
29
+ const ts = getPlanTimestamps(handle, date);
30
+ return {
31
+ date,
32
+ hours,
33
+ plannedHours: bucket.filter((t) => t.length > 0).length,
34
+ createdAt: ts.createdAt,
35
+ updatedAt: ts.updatedAt,
36
+ };
37
+ }
38
+ //# sourceMappingURL=overview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overview.js","sourceRoot":"","sources":["../../src/plan/overview.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,EAAE;AACF,2DAA2D;AAC3D,kDAAkD;AAClD,6CAA6C;AAC7C,qDAAqD;AACrD,6DAA6D;AAC7D,oCAAoC;AACpC,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAoBrC,MAAM,IAAI,GAAG,6DAA6D,CAAC;AAE3E,MAAM,UAAU,iBAAiB,CAAC,MAAkB,EAAE,KAAe;IACnE,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAC1D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC9E,CAAC;AAED,SAAS,QAAQ,CAAC,MAAkB,EAAE,IAAY;IAChD,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAe,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAChE,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3C,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,MAAM,KAAK,GAAkB,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACtD,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK;KAC/C,CAAC,CAAC,CAAC;IACJ,MAAM,EAAE,GAAG,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC3C,OAAO;QACL,IAAI;QACJ,KAAK;QACL,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM;QACvD,SAAS,EAAE,EAAE,CAAC,SAAS;QACvB,SAAS,EAAE,EAAE,CAAC,SAAS;KACxB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { type LarkEvent } from '../fetch/feishu.js';
2
+ export interface RemoteEvent extends LarkEvent {
3
+ /** 本地口径的时间槽(跨日 00:00 已换成本地 23:59)。 */
4
+ slotStart: string;
5
+ slotEnd: string;
6
+ }
7
+ export interface PullResult {
8
+ events: RemoteEvent[];
9
+ errors: string[];
10
+ /** 读数原料:两路各发了几次请求(分片合规、阶段 3 补了几条,都由它读)。 */
11
+ calls: {
12
+ agenda: number;
13
+ search: number;
14
+ detail: number;
15
+ };
16
+ }
17
+ export declare function pullFeishuDate(cli: string, date: string): PullResult;
18
+ /** 远端自然键:四元组(日期 + 起 + 止 + 标题)——本地键是三元组,两侧口径不同是既有事实(S-01/S-03)。 */
19
+ export declare function remoteKeyOf(date: string, e: {
20
+ slotStart: string;
21
+ slotEnd: string;
22
+ summary: string;
23
+ }): string;
24
+ export declare function localKeyOf(date: string, timeStart: string, timeEnd: string): string;
25
+ //# sourceMappingURL=pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/plan/pull.ts"],"names":[],"mappings":"AAcA,OAAO,EAA8C,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAGhG,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,2CAA2C;IAC3C,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3D;AASD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CAmDpE;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAE5G;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnF"}
@@ -0,0 +1,83 @@
1
+ // 日程与计划·三阶段合并拉取(能力内部件):把某一天的远端事件读全,且读得准。
2
+ //
3
+ // 老实现的教训(`feishu_sync.py:398-565`):单用 `+agenda` 有索引延迟(刚建的可能读不到),
4
+ // 单用 `+search-event` 既没有 description、一天又只回前 20 条。于是三阶段合并:
5
+ // 阶段 1 甲路:`+agenda` 整日(带 description)
6
+ // 阶段 1 乙路:`+search-event` 按 6 小时**分片**(索引最新,规避单次返回上限)
7
+ // 阶段 2 :按 event_id 合并去重(甲路优先——它带 description)
8
+ // 阶段 3 :description 仍为空者,逐条 `events get` 补齐(归属锚靠它才判得出)
9
+ //
10
+ // 有意偏离 D-13(老实现缺陷):老家分片循环在异常分支里 `continue` 跳过了 `cur = cur_end`,
11
+ // 远端一抖就原地转圈、`ThreadPoolExecutor` 退出时 `wait` 等它 → 整条命令挂死
12
+ // (`feishu_sync.py:546-550`;实测 25s 超时未返回、同一窗口重复查 472 次)。本实现**游标一定推进**:
13
+ // 分片失败只记账并继续下一片;两路全断则上抛,由调用方降级——绝不空转。
14
+ import { ScheduleFetchError } from '../fetch/errors.js';
15
+ import { larkAgenda, larkSearchEvents, larkGetEvent } from '../fetch/feishu.js';
16
+ import { dayStartISO, dayEndISO, shardWindows, remoteSlotOf } from './iso.js';
17
+ function msg(e) { return e instanceof Error ? e.message : String(e); }
18
+ function toRemote(e) {
19
+ const slot = remoteSlotOf(e.start, e.end);
20
+ return { ...e, slotStart: slot.start, slotEnd: slot.end };
21
+ }
22
+ export function pullFeishuDate(cli, date) {
23
+ const errors = [];
24
+ const calls = { agenda: 0, search: 0, detail: 0 };
25
+ // 阶段 1 甲路:议程(失败不致命——乙路兜底,与老家同口径)
26
+ let agenda = [];
27
+ let agendaFailed = false;
28
+ calls.agenda++;
29
+ try {
30
+ agenda = larkAgenda(cli, dayStartISO(date), dayEndISO(date));
31
+ }
32
+ catch (e) {
33
+ agendaFailed = true;
34
+ errors.push('议程拉取失败:' + msg(e));
35
+ }
36
+ // 阶段 1 乙路:分片检索(每片独立成败;失败只记账,游标照推)
37
+ const shards = shardWindows(date);
38
+ const found = [];
39
+ let shardFailed = 0;
40
+ for (const w of shards) {
41
+ calls.search++;
42
+ try {
43
+ found.push(...larkSearchEvents(cli, w.start, w.end));
44
+ }
45
+ catch (e) {
46
+ shardFailed++;
47
+ errors.push('分片检索失败(' + w.start + '~' + w.end + '):' + msg(e));
48
+ }
49
+ }
50
+ if (agendaFailed && shardFailed === shards.length) {
51
+ // 两路全断=远端真的不可达:上抛让调用方降级,不在这里假装「远端没有事件」。
52
+ throw new ScheduleFetchError('LARK_BAD_RESPONSE', '远端不可达:议程与全部 ' + shards.length + ' 个分片都失败(' + errors[0] + ')');
53
+ }
54
+ // 阶段 2:合并去重(甲路优先)
55
+ const byId = new Map();
56
+ for (const e of agenda)
57
+ byId.set(e.eventId, e);
58
+ for (const e of found)
59
+ if (!byId.has(e.eventId))
60
+ byId.set(e.eventId, e);
61
+ // 阶段 3:逐条补 description(归属锚只有补齐后才判得准)
62
+ for (const e of byId.values()) {
63
+ if (e.description)
64
+ continue;
65
+ calls.detail++;
66
+ const full = larkGetEvent(cli, e.eventId);
67
+ if (full) {
68
+ e.description = full.description;
69
+ e.owned = full.owned;
70
+ if (!e.summary)
71
+ e.summary = full.summary;
72
+ }
73
+ }
74
+ return { events: [...byId.values()].map(toRemote), errors, calls };
75
+ }
76
+ /** 远端自然键:四元组(日期 + 起 + 止 + 标题)——本地键是三元组,两侧口径不同是既有事实(S-01/S-03)。 */
77
+ export function remoteKeyOf(date, e) {
78
+ return date + '|' + e.slotStart + '|' + e.slotEnd + '|' + e.summary;
79
+ }
80
+ export function localKeyOf(date, timeStart, timeEnd) {
81
+ return date + '|' + timeStart + '|' + timeEnd;
82
+ }
83
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/plan/pull.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ export declare const LOCAL_STATES: readonly ["created", "found", "updated", "deleted", "upserted", "unchanged", "preview", "reviewed", "checked"];
2
+ export type LocalState = (typeof LOCAL_STATES)[number];
3
+ /** 远端侧状态:`found_feishu`/`created_feishu`/`unavailable` 三值沿用老家口径(S-04),后两值是合成写新增的档。 */
4
+ export declare const REMOTE_STATES: readonly ["found_feishu", "created_feishu", "updated_feishu", "deleted_feishu", "unavailable", "skipped", "none"];
5
+ export type RemoteState = (typeof REMOTE_STATES)[number];
6
+ export interface PlanReceipt {
7
+ ok: boolean;
8
+ message: string;
9
+ op: string;
10
+ /** 本地侧做了什么。 */
11
+ local: LocalState;
12
+ /** 远端侧做了什么(`unavailable`=远端没成;`skipped`=调用方显式只要本地;`none`=本 op 与远端无关)。 */
13
+ remote: RemoteState;
14
+ /** 远端对象的标识(没有就 null——不写空串冒充)。 */
15
+ remoteId: string | null;
16
+ /** 两侧是否都对齐(出口据此给退出码)。 */
17
+ achieved: boolean;
18
+ /** 真失败:非空即「这一趟没达成」(退出码非 0)。 */
19
+ errors: string[];
20
+ /** 说明性的话(已自动处理/不是我的对象等):进回执给人看,不影响达成判定。 */
21
+ notes: string[];
22
+ id?: number;
23
+ date?: string;
24
+ dates?: string[];
25
+ counts?: Record<string, number>;
26
+ items?: unknown[];
27
+ /** op 自己的附加格(例如自检的「留下了什么/怎么清」)。 */
28
+ extra?: Record<string, unknown>;
29
+ }
30
+ export interface ReceiptInput {
31
+ op: string;
32
+ message: string;
33
+ local: LocalState;
34
+ remote: RemoteState;
35
+ remoteId?: string | null;
36
+ errors?: string[];
37
+ notes?: string[];
38
+ id?: number;
39
+ date?: string;
40
+ dates?: string[];
41
+ counts?: Record<string, number>;
42
+ items?: unknown[];
43
+ /** op 自己的附加格(例如自检的「留下了什么/怎么清」)。 */
44
+ extra?: Record<string, unknown>;
45
+ }
46
+ /** 达成判据:远端侧不是「没成」,且没有记账错误。
47
+ * `skipped`(参数只要本地)与 `none`(本 op 与远端无关)都算达成——调用方要的就是这个范围。 */
48
+ export declare function achievedOf(remote: RemoteState, errors: string[]): boolean;
49
+ export declare function buildReceipt(input: ReceiptInput): PlanReceipt;
50
+ /** 远端侧一句话(人读):写在 message 里,机读看 `remote` 字段。 */
51
+ export declare const REMOTE_LABEL: Record<RemoteState, string>;
52
+ //# sourceMappingURL=receipt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipt.d.ts","sourceRoot":"","sources":["../../src/plan/receipt.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,YAAY,gHAAiH,CAAC;AAC3I,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,sFAAsF;AACtF,eAAO,MAAM,aAAa,mHAEhB,CAAC;AACX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,eAAe;IACf,KAAK,EAAE,UAAU,CAAC;IAClB,yEAAyE;IACzE,MAAM,EAAE,WAAW,CAAC;IACpB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,yBAAyB;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;IAClB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;8DAC8D;AAC9D,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAGzE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,WAAW,CAqB7D;AAED,+CAA+C;AAC/C,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAQpD,CAAC"}
@@ -0,0 +1,57 @@
1
+ // 日程与计划·合成写回执(能力内部件):一条写命令**分字段**报「本地侧 / 远端侧 / 远端标识」。
2
+ //
3
+ // 判据出处:`docs/agents/合成写判据.md` 第一节第 4/5 条;修正的有意偏离 D-14——
4
+ // 老家回执在「命中本地且已有远端标识」那一支根本没有 `feishu` 键(`schedule_db.py:1062` 对 `:1066`/`:1083`),
5
+ // 消费方按字段取会 KeyError。本实现**三格永在**,且「这一趟算不算达成」是显式字段(`achieved`),
6
+ // 由出口映射成退出码(没达成 → 非 0,照裁定 A6②/用户故事 6;降级照老 A6①:远端不可用不拦住本地写)。
7
+ export const LOCAL_STATES = ['created', 'found', 'updated', 'deleted', 'upserted', 'unchanged', 'preview', 'reviewed', 'checked'];
8
+ /** 远端侧状态:`found_feishu`/`created_feishu`/`unavailable` 三值沿用老家口径(S-04),后两值是合成写新增的档。 */
9
+ export const REMOTE_STATES = [
10
+ 'found_feishu', 'created_feishu', 'updated_feishu', 'deleted_feishu', 'unavailable', 'skipped', 'none',
11
+ ];
12
+ /** 达成判据:远端侧不是「没成」,且没有记账错误。
13
+ * `skipped`(参数只要本地)与 `none`(本 op 与远端无关)都算达成——调用方要的就是这个范围。 */
14
+ export function achievedOf(remote, errors) {
15
+ if (errors.length)
16
+ return false;
17
+ return remote !== 'unavailable';
18
+ }
19
+ export function buildReceipt(input) {
20
+ const errors = input.errors ?? [];
21
+ const achieved = achievedOf(input.remote, errors);
22
+ const out = {
23
+ ok: achieved,
24
+ message: input.message,
25
+ op: input.op,
26
+ local: input.local,
27
+ remote: input.remote,
28
+ remoteId: input.remoteId ?? null,
29
+ achieved,
30
+ errors,
31
+ notes: input.notes ?? [],
32
+ };
33
+ if (input.id !== undefined)
34
+ out.id = input.id;
35
+ if (input.date !== undefined)
36
+ out.date = input.date;
37
+ if (input.dates !== undefined)
38
+ out.dates = input.dates;
39
+ if (input.counts !== undefined)
40
+ out.counts = input.counts;
41
+ if (input.items !== undefined)
42
+ out.items = input.items;
43
+ if (input.extra !== undefined)
44
+ Object.assign(out, input.extra);
45
+ return out;
46
+ }
47
+ /** 远端侧一句话(人读):写在 message 里,机读看 `remote` 字段。 */
48
+ export const REMOTE_LABEL = {
49
+ found_feishu: '远端已有(认出来了,未重复建)',
50
+ created_feishu: '远端已建',
51
+ updated_feishu: '远端已改',
52
+ deleted_feishu: '远端已删',
53
+ unavailable: '远端没成(远端不可用或写失败)',
54
+ skipped: '远端按参数跳过(只做本地)',
55
+ none: '本命令不碰远端',
56
+ };
57
+ //# sourceMappingURL=receipt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipt.js","sourceRoot":"","sources":["../../src/plan/receipt.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,EAAE;AACF,wDAAwD;AACxD,iFAAiF;AACjF,8DAA8D;AAC9D,4DAA4D;AAC5D,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,CAAU,CAAC;AAG3I,sFAAsF;AACtF,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,cAAc,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM;CAC9F,CAAC;AA6CX;8DAC8D;AAC9D,MAAM,UAAU,UAAU,CAAC,MAAmB,EAAE,MAAgB;IAC9D,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAChC,OAAO,MAAM,KAAK,aAAa,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAmB;IAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC;IAClC,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,MAAM,GAAG,GAAgB;QACvB,EAAE,EAAE,QAAQ;QACZ,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;QAChC,QAAQ;QACR,MAAM;QACN,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE;KACzB,CAAC;IACF,IAAI,KAAK,CAAC,EAAE,KAAK,SAAS;QAAE,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;IAC9C,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;QAAE,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACpD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QAAE,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IACvD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;QAAE,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC1D,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QAAE,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IACvD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QAAE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC/D,OAAO,GAAG,CAAC;AACb,CAAC;AAED,+CAA+C;AAC/C,MAAM,CAAC,MAAM,YAAY,GAAgC;IACvD,YAAY,EAAE,iBAAiB;IAC/B,cAAc,EAAE,MAAM;IACtB,cAAc,EAAE,MAAM;IACtB,cAAc,EAAE,MAAM;IACtB,WAAW,EAAE,iBAAiB;IAC9B,OAAO,EAAE,eAAe;IACxB,IAAI,EAAE,SAAS;CAChB,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { type RemoteEvent } from './pull.js';
2
+ import type { RemoteState } from './receipt.js';
3
+ export interface RemoteSnapshot {
4
+ cli: string;
5
+ date: string;
6
+ events: RemoteEvent[];
7
+ /** 拉取期间记下的错(分片失败等):不假装远端干净,也不因此阻断本地写。 */
8
+ pullErrors: string[];
9
+ calls: {
10
+ agenda: number;
11
+ search: number;
12
+ detail: number;
13
+ };
14
+ /** 已被本地事件认领的远端对象 id(=远端一侧的「已对上」集合)。 */
15
+ claimed: Set<string>;
16
+ }
17
+ /** 一次拉取;拿不到远端(两路全断)即上抛,由调用方按降级处理。 */
18
+ export declare function takeSnapshot(cli: string, date: string): RemoteSnapshot;
19
+ export interface AlignSpec {
20
+ date: string;
21
+ timeStart: string;
22
+ timeEnd: string;
23
+ title: string;
24
+ notes?: string | null;
25
+ /** 本地已存的远端标识(有就先按它认;认不到再按四元组认;都没有就建)。 */
26
+ remoteId?: string | null;
27
+ }
28
+ export interface AlignOutcome {
29
+ remote: RemoteState;
30
+ remoteId: string | null;
31
+ /** 真失败(远端建/写失败等):非空即这一条没对齐。 */
32
+ errors: string[];
33
+ /** 说明性的话(已自动改认/不是我的对象):不影响达成判定。 */
34
+ notes: string[];
35
+ }
36
+ /** 远端判重:先按本地存的标识认,再按四元组认(只看带归属锚的)。 */
37
+ export declare function matchIn(snap: RemoteSnapshot, spec: AlignSpec): RemoteEvent | null;
38
+ /**
39
+ * 把一条本地事实对齐到远端:命中即回填标识(幂等),未命中即建(描述带归属锚)。
40
+ * 拿不到远端标识(D-11)**绝不写空**:返回 `unavailable` + 明确错误,让调用方与退出码如实反映。
41
+ */
42
+ export declare function alignOne(snap: RemoteSnapshot, spec: AlignSpec): AlignOutcome;
43
+ /**
44
+ * 同槽兜底清理(S-12 的同槽一侧):飞书日历没有「改时间」,改时段=建新 + 删旧;
45
+ * 删旧失败或历史上留了重复时,把该槽位里**带归属锚**的其它对象删掉,只留 keeper。
46
+ * 不带锚的一律不动。
47
+ */
48
+ export declare function cleanSlot(snap: RemoteSnapshot, spec: AlignSpec & {
49
+ keepId: string;
50
+ }): {
51
+ deleted: string[];
52
+ errors: string[];
53
+ };
54
+ /** 孤儿=带归属锚、但没有任何本地事件认领的远端对象(S-12:该清;不带锚的进不来这个集合)。 */
55
+ export declare function orphansOf(snap: RemoteSnapshot): RemoteEvent[];
56
+ /** 删远端对象(删计划、孤儿清理、自检清理共用这一个出口)。 */
57
+ export declare function removeRemote(snap: RemoteSnapshot, eventId: string): {
58
+ ok: boolean;
59
+ error?: string;
60
+ };
61
+ export declare function rethrowRemoteUnavailable(e: unknown): never;
62
+ //# sourceMappingURL=remoteDay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteDay.d.ts","sourceRoot":"","sources":["../../src/plan/remoteDay.ts"],"names":[],"mappings":"AAWA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,yCAAyC;IACzC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1D,uCAAuC;IACvC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACtB;AAED,qCAAqC;AACrC,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,CAGtE;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,mCAAmC;IACnC,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,sCAAsC;AACtC,wBAAgB,OAAO,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,IAAI,CAQjF;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,GAAG,YAAY,CA+B5E;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAiB7H;AAED,qDAAqD;AACrD,wBAAgB,SAAS,CAAC,IAAI,EAAE,cAAc,GAAG,WAAW,EAAE,CAE7D;AAED,mCAAmC;AACnC,wBAAgB,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAUnG;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,OAAO,GAAG,KAAK,CAG1D"}
@@ -0,0 +1,102 @@
1
+ // 日程与计划·远端当日快照与判重(能力内部件):一次拉取、多次判定、一次收口。
2
+ //
3
+ // 两侧自然键**不必相同**(判据第一节):本地是 `(日期, 起, 止)` 三元组(title 只展示、不参与身份,S-02),
4
+ // 远端是 `(日期, 起, 止, 标题)` 四元组(S-03)。所以判重有两道:
5
+ // ① 本地有没有这一条 → 由 `fetch/db.ts` 的三元组查重管(不在本件)
6
+ // ② 远端有没有这一条 → 由本件管(**不再只看本地存的标识**,这就是 D-12 的修法:
7
+ // 老家 `op=sync` 调了 `searchFeishuEvents` 却把返回值丢了,见 `cmd_read.ts:293` 旧码)
8
+ //
9
+ // 「谁是我管的」只有一个判据:远端对象描述里带归属锚(S-06/S-12)。不带锚的**一律不许动**。
10
+ import { ScheduleFetchError } from '../fetch/errors.js';
11
+ import { larkCreateEvent, larkDeleteEvent, composeFeishuDescription } from '../fetch/feishu.js';
12
+ import { pullFeishuDate } from './pull.js';
13
+ import { toFeishuISO } from './iso.js';
14
+ /** 一次拉取;拿不到远端(两路全断)即上抛,由调用方按降级处理。 */
15
+ export function takeSnapshot(cli, date) {
16
+ const pulled = pullFeishuDate(cli, date);
17
+ return { cli, date, events: pulled.events, pullErrors: pulled.errors, calls: pulled.calls, claimed: new Set() };
18
+ }
19
+ /** 远端判重:先按本地存的标识认,再按四元组认(只看带归属锚的)。 */
20
+ export function matchIn(snap, spec) {
21
+ if (spec.remoteId) {
22
+ const byId = snap.events.find((e) => e.eventId === spec.remoteId);
23
+ if (byId)
24
+ return byId;
25
+ }
26
+ return snap.events.find((e) => e.owned && e.summary === spec.title && e.slotStart === spec.timeStart && e.slotEnd === spec.timeEnd) ?? null;
27
+ }
28
+ /**
29
+ * 把一条本地事实对齐到远端:命中即回填标识(幂等),未命中即建(描述带归属锚)。
30
+ * 拿不到远端标识(D-11)**绝不写空**:返回 `unavailable` + 明确错误,让调用方与退出码如实反映。
31
+ */
32
+ export function alignOne(snap, spec) {
33
+ const errors = [];
34
+ const notes = [];
35
+ const hit = matchIn(snap, spec);
36
+ if (hit) {
37
+ snap.claimed.add(hit.eventId);
38
+ if (spec.remoteId && spec.remoteId !== hit.eventId) {
39
+ notes.push('本地存的远端标识与远端实际不符,已按四元组改认:' + spec.remoteId + ' → ' + hit.eventId);
40
+ }
41
+ return { remote: 'found_feishu', remoteId: hit.eventId, errors, notes };
42
+ }
43
+ // 远端同槽位有不带锚的对象:那不是我的,不动它,但要说出来(免得用户以为系统漏了)。
44
+ const foreign = snap.events.find((e) => !e.owned && e.summary === spec.title && e.slotStart === spec.timeStart && e.slotEnd === spec.timeEnd);
45
+ if (foreign)
46
+ notes.push('远端同槽位存在不带归属标记的事件(不是本技能管的,不动它):' + foreign.eventId);
47
+ try {
48
+ const created = larkCreateEvent(snap.cli, toFeishuISO(spec.date, spec.timeStart), toFeishuISO(spec.date, spec.timeEnd), spec.title, composeFeishuDescription(spec.notes));
49
+ snap.events.push({ ...created, slotStart: spec.timeStart, slotEnd: spec.timeEnd });
50
+ snap.claimed.add(created.eventId);
51
+ return { remote: 'created_feishu', remoteId: created.eventId, errors, notes };
52
+ }
53
+ catch (e) {
54
+ const m = e instanceof Error ? e.message : String(e);
55
+ return { remote: 'unavailable', remoteId: null, errors: [...errors, m], notes };
56
+ }
57
+ }
58
+ /**
59
+ * 同槽兜底清理(S-12 的同槽一侧):飞书日历没有「改时间」,改时段=建新 + 删旧;
60
+ * 删旧失败或历史上留了重复时,把该槽位里**带归属锚**的其它对象删掉,只留 keeper。
61
+ * 不带锚的一律不动。
62
+ */
63
+ export function cleanSlot(snap, spec) {
64
+ const deleted = [];
65
+ const errors = [];
66
+ const others = snap.events.filter((e) => e.owned && e.eventId !== spec.keepId && e.slotStart === spec.timeStart && e.slotEnd === spec.timeEnd);
67
+ for (const e of others) {
68
+ try {
69
+ larkDeleteEvent(snap.cli, e.eventId);
70
+ deleted.push(e.eventId);
71
+ snap.claimed.delete(e.eventId);
72
+ snap.events = snap.events.filter((x) => x.eventId !== e.eventId);
73
+ }
74
+ catch (err) {
75
+ errors.push('同槽清理失败:' + e.eventId + '(' + (err instanceof Error ? err.message : String(err)) + ')');
76
+ }
77
+ }
78
+ return { deleted, errors };
79
+ }
80
+ /** 孤儿=带归属锚、但没有任何本地事件认领的远端对象(S-12:该清;不带锚的进不来这个集合)。 */
81
+ export function orphansOf(snap) {
82
+ return snap.events.filter((e) => e.owned && !snap.claimed.has(e.eventId));
83
+ }
84
+ /** 删远端对象(删计划、孤儿清理、自检清理共用这一个出口)。 */
85
+ export function removeRemote(snap, eventId) {
86
+ try {
87
+ larkDeleteEvent(snap.cli, eventId);
88
+ snap.claimed.delete(eventId);
89
+ snap.events = snap.events.filter((e) => e.eventId !== eventId);
90
+ return { ok: true };
91
+ }
92
+ catch (e) {
93
+ const m = e instanceof Error ? e.message : String(e);
94
+ return { ok: false, error: m };
95
+ }
96
+ }
97
+ export function rethrowRemoteUnavailable(e) {
98
+ if (e instanceof ScheduleFetchError)
99
+ throw e;
100
+ throw new ScheduleFetchError('LARK_BAD_RESPONSE', '远端不可达:' + (e instanceof Error ? e.message : String(e)));
101
+ }
102
+ //# sourceMappingURL=remoteDay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remoteDay.js","sourceRoot":"","sources":["../../src/plan/remoteDay.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,mEAAmE;AACnE,0CAA0C;AAC1C,+CAA+C;AAC/C,mDAAmD;AACnD,4EAA4E;AAC5E,EAAE;AACF,sDAAsD;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAChG,OAAO,EAAE,cAAc,EAAoB,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAcvC,qCAAqC;AACrC,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,IAAY;IACpD,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,GAAG,EAAU,EAAE,CAAC;AAC1H,CAAC;AAqBD,sCAAsC;AACtC,MAAM,UAAU,OAAO,CAAC,IAAoB,EAAE,IAAe;IAC3D,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClE,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;IACxB,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CACrB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,CAC3G,IAAI,IAAI,CAAC;AACZ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAoB,EAAE,IAAe;IAC5D,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAChC,IAAI,GAAG,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC;YACnD,KAAK,CAAC,IAAI,CAAC,0BAA0B,GAAG,IAAI,CAAC,QAAQ,GAAG,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC1E,CAAC;IACD,4CAA4C;IAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAC9B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,CAC5G,CAAC;IACF,IAAI,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,gCAAgC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5E,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,eAAe,CAC7B,IAAI,CAAC,GAAG,EACR,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EACtC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,EACpC,IAAI,CAAC,KAAK,EACV,wBAAwB,CAAC,IAAI,CAAC,KAAK,CAAC,CACrC,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAClC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAChF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACrD,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;IAClF,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,IAAoB,EAAE,IAAoC;IAClF,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAC/B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,CAC5G,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAC/B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC;QACnE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,OAAO,GAAG,GAAG,GAAG,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QACtG,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC7B,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,SAAS,CAAC,IAAoB;IAC5C,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,YAAY,CAAC,IAAoB,EAAE,OAAe;IAChE,IAAI,CAAC;QACH,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;QAC/D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACrD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IACjC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,CAAU;IACjD,IAAI,CAAC,YAAY,kBAAkB;QAAE,MAAM,CAAC,CAAC;IAC7C,MAAM,IAAI,kBAAkB,CAAC,mBAAmB,EAAE,QAAQ,GAAG,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7G,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type PlanOpCtx, type PlanOpResult } from './context.js';
2
+ export declare function runUpdate(ctx: PlanOpCtx): PlanOpResult;
3
+ export declare function runDeactivate(ctx: PlanOpCtx): PlanOpResult;
4
+ //# sourceMappingURL=single.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"single.d.ts","sourceRoot":"","sources":["../../src/plan/single.ts"],"names":[],"mappings":"AAUA,OAAO,EAAiB,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAIhF,wBAAgB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,YAAY,CAiGtD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,SAAS,GAAG,YAAY,CAmD1D"}