@lemoncat7/dsh-partner 2.8.2 → 2.8.4

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 (210) hide show
  1. package/README.md +27 -406
  2. package/docs/bark-notifications.md +27 -0
  3. package/docs/concern-workflow.md +39 -0
  4. package/docs/observation-contract.md +11 -1
  5. package/docs/pendant-loading.md +30 -0
  6. package/docs/releases/1.12.0.md +16 -0
  7. package/docs/releases/1.14.2.md +8 -0
  8. package/docs/releases/1.15.0.md +15 -0
  9. package/docs/releases/1.16.0.md +15 -0
  10. package/docs/releases/1.16.1.md +12 -0
  11. package/docs/releases/1.16.2.md +12 -0
  12. package/docs/releases/2.0.0.md +19 -0
  13. package/docs/releases/2.1.0.md +8 -0
  14. package/docs/releases/2.2.0.md +8 -0
  15. package/docs/releases/2.3.0.md +8 -0
  16. package/docs/releases/2.4.0.md +8 -0
  17. package/docs/releases/2.5.0.md +8 -0
  18. package/docs/releases/2.8.0.md +6 -0
  19. package/docs/releases/2.8.3.md +20 -0
  20. package/docs/releases/2.8.4.md +35 -0
  21. package/docs/releases/README.md +14 -0
  22. package/lib/agent-runtime.d.ts +1 -0
  23. package/lib/agent-runtime.d.ts.map +1 -1
  24. package/lib/agent-runtime.js +23 -8
  25. package/lib/agent-runtime.js.map +1 -1
  26. package/lib/api/features/pendant-api.d.ts.map +1 -1
  27. package/lib/api/features/pendant-api.js +11 -2
  28. package/lib/api/features/pendant-api.js.map +1 -1
  29. package/lib/api/features/push-api.d.ts +4 -0
  30. package/lib/api/features/push-api.d.ts.map +1 -0
  31. package/lib/api/features/push-api.js +47 -0
  32. package/lib/api/features/push-api.js.map +1 -0
  33. package/lib/api.d.ts +3 -0
  34. package/lib/api.d.ts.map +1 -1
  35. package/lib/api.js +18 -1
  36. package/lib/api.js.map +1 -1
  37. package/lib/autonomy.d.ts.map +1 -1
  38. package/lib/autonomy.js +8 -5
  39. package/lib/autonomy.js.map +1 -1
  40. package/lib/client-api.d.ts +11 -0
  41. package/lib/client-api.d.ts.map +1 -1
  42. package/lib/client-api.js.map +1 -1
  43. package/lib/client.d.ts.map +1 -1
  44. package/lib/client.js +2573 -1855
  45. package/lib/client.js.map +4 -4
  46. package/lib/client.pendant.js +4157 -0
  47. package/lib/collaboration/composition.d.ts.map +1 -1
  48. package/lib/collaboration/composition.js +1 -0
  49. package/lib/collaboration/composition.js.map +1 -1
  50. package/lib/collaboration/ssh-task-access.d.ts +33 -0
  51. package/lib/collaboration/ssh-task-access.d.ts.map +1 -0
  52. package/lib/collaboration/ssh-task-access.js +26 -0
  53. package/lib/collaboration/ssh-task-access.js.map +1 -0
  54. package/lib/companions/removal.d.ts.map +1 -1
  55. package/lib/companions/removal.js +4 -0
  56. package/lib/companions/removal.js.map +1 -1
  57. package/lib/concern-domain.d.ts +5 -0
  58. package/lib/concern-domain.d.ts.map +1 -1
  59. package/lib/concern-domain.js.map +1 -1
  60. package/lib/concern-execution-notes.d.ts +2 -0
  61. package/lib/concern-execution-notes.d.ts.map +1 -1
  62. package/lib/concern-execution-notes.js +9 -2
  63. package/lib/concern-execution-notes.js.map +1 -1
  64. package/lib/concern-execution-receipt.d.ts.map +1 -1
  65. package/lib/concern-execution-receipt.js +3 -2
  66. package/lib/concern-execution-receipt.js.map +1 -1
  67. package/lib/concern-execution.d.ts +3 -1
  68. package/lib/concern-execution.d.ts.map +1 -1
  69. package/lib/concern-execution.js +32 -5
  70. package/lib/concern-execution.js.map +1 -1
  71. package/lib/concern-knowledge-source.d.ts +23 -0
  72. package/lib/concern-knowledge-source.d.ts.map +1 -0
  73. package/lib/concern-knowledge-source.js +30 -0
  74. package/lib/concern-knowledge-source.js.map +1 -0
  75. package/lib/concern-note-source.d.ts +2 -1
  76. package/lib/concern-note-source.d.ts.map +1 -1
  77. package/lib/concern-note-source.js +6 -2
  78. package/lib/concern-note-source.js.map +1 -1
  79. package/lib/concern-store.d.ts +1 -0
  80. package/lib/concern-store.d.ts.map +1 -1
  81. package/lib/concern-store.js +29 -2
  82. package/lib/concern-store.js.map +1 -1
  83. package/lib/domain.d.ts +2 -0
  84. package/lib/domain.d.ts.map +1 -1
  85. package/lib/domain.js.map +1 -1
  86. package/lib/heartbeat.d.ts.map +1 -1
  87. package/lib/heartbeat.js +2 -1
  88. package/lib/heartbeat.js.map +1 -1
  89. package/lib/index.d.ts.map +1 -1
  90. package/lib/index.js +18 -1
  91. package/lib/index.js.map +1 -1
  92. package/lib/notifications/bark-adapter.d.ts +9 -0
  93. package/lib/notifications/bark-adapter.d.ts.map +1 -0
  94. package/lib/notifications/bark-adapter.js +69 -0
  95. package/lib/notifications/bark-adapter.js.map +1 -0
  96. package/lib/notifications/push-config.d.ts +10 -0
  97. package/lib/notifications/push-config.d.ts.map +1 -0
  98. package/lib/notifications/push-config.js +79 -0
  99. package/lib/notifications/push-config.js.map +1 -0
  100. package/lib/notifications/push-credentials.d.ts +9 -0
  101. package/lib/notifications/push-credentials.d.ts.map +1 -0
  102. package/lib/notifications/push-credentials.js +16 -0
  103. package/lib/notifications/push-credentials.js.map +1 -0
  104. package/lib/notifications/push-domain.d.ts +66 -0
  105. package/lib/notifications/push-domain.d.ts.map +1 -0
  106. package/lib/notifications/push-domain.js +6 -0
  107. package/lib/notifications/push-domain.js.map +1 -0
  108. package/lib/notifications/push-observer.d.ts +19 -0
  109. package/lib/notifications/push-observer.d.ts.map +1 -0
  110. package/lib/notifications/push-observer.js +96 -0
  111. package/lib/notifications/push-observer.js.map +1 -0
  112. package/lib/notifications/push-service.d.ts +33 -0
  113. package/lib/notifications/push-service.d.ts.map +1 -0
  114. package/lib/notifications/push-service.js +228 -0
  115. package/lib/notifications/push-service.js.map +1 -0
  116. package/lib/notifications/push-state.d.ts +3 -0
  117. package/lib/notifications/push-state.d.ts.map +1 -0
  118. package/lib/notifications/push-state.js +23 -0
  119. package/lib/notifications/push-state.js.map +1 -0
  120. package/lib/observation-budget.d.ts +3 -2
  121. package/lib/observation-budget.d.ts.map +1 -1
  122. package/lib/observation-budget.js +5 -3
  123. package/lib/observation-budget.js.map +1 -1
  124. package/lib/observation-executor.d.ts.map +1 -1
  125. package/lib/observation-executor.js +6 -0
  126. package/lib/observation-executor.js.map +1 -1
  127. package/lib/observation-loop.d.ts +3 -0
  128. package/lib/observation-loop.d.ts.map +1 -1
  129. package/lib/observation-loop.js +154 -18
  130. package/lib/observation-loop.js.map +1 -1
  131. package/lib/observation-model-retry.d.ts +20 -0
  132. package/lib/observation-model-retry.d.ts.map +1 -0
  133. package/lib/observation-model-retry.js +48 -0
  134. package/lib/observation-model-retry.js.map +1 -0
  135. package/lib/observation-progress.d.ts +19 -0
  136. package/lib/observation-progress.d.ts.map +1 -0
  137. package/lib/observation-progress.js +77 -0
  138. package/lib/observation-progress.js.map +1 -0
  139. package/lib/observation-workflow.d.ts +40 -0
  140. package/lib/observation-workflow.d.ts.map +1 -0
  141. package/lib/observation-workflow.js +154 -0
  142. package/lib/observation-workflow.js.map +1 -0
  143. package/lib/pendant/badge-art.d.ts +9 -0
  144. package/lib/pendant/badge-art.d.ts.map +1 -0
  145. package/lib/pendant/badge-art.js +68 -0
  146. package/lib/pendant/badge-art.js.map +1 -0
  147. package/lib/pendant/card-image.d.ts.map +1 -1
  148. package/lib/pendant/card-image.js +11 -9
  149. package/lib/pendant/card-image.js.map +1 -1
  150. package/lib/pendant/renderer-loader.d.ts +9 -0
  151. package/lib/pendant/renderer-loader.d.ts.map +1 -0
  152. package/lib/pendant/renderer-loader.js +12 -0
  153. package/lib/pendant/renderer-loader.js.map +1 -0
  154. package/lib/pendant/renderer.d.ts +2 -6
  155. package/lib/pendant/renderer.d.ts.map +1 -1
  156. package/lib/pendant/renderer.js +1 -67
  157. package/lib/pendant/renderer.js.map +1 -1
  158. package/lib/pendant/static-card.d.ts +20 -0
  159. package/lib/pendant/static-card.d.ts.map +1 -0
  160. package/lib/pendant/static-card.js +55 -0
  161. package/lib/pendant/static-card.js.map +1 -0
  162. package/lib/pendant/widget.d.ts.map +1 -1
  163. package/lib/pendant/widget.js +9 -5
  164. package/lib/pendant/widget.js.map +1 -1
  165. package/lib/pendant-renderer.js +14 -14
  166. package/lib/recording-snapshot.d.ts.map +1 -1
  167. package/lib/recording-snapshot.js +12 -2
  168. package/lib/recording-snapshot.js.map +1 -1
  169. package/lib/storage/migrate-layout.d.ts.map +1 -1
  170. package/lib/storage/migrate-layout.js +2 -0
  171. package/lib/storage/migrate-layout.js.map +1 -1
  172. package/lib/storage/split-state.js +2 -2
  173. package/lib/storage/split-state.js.map +1 -1
  174. package/lib/store.d.ts.map +1 -1
  175. package/lib/store.js +2 -0
  176. package/lib/store.js.map +1 -1
  177. package/lib/ui/capability-editor.d.ts.map +1 -1
  178. package/lib/ui/capability-editor.js +3 -5
  179. package/lib/ui/capability-editor.js.map +1 -1
  180. package/lib/ui/channels-panel.d.ts.map +1 -1
  181. package/lib/ui/channels-panel.js +7 -1
  182. package/lib/ui/channels-panel.js.map +1 -1
  183. package/lib/ui/memory/concern-board.d.ts.map +1 -1
  184. package/lib/ui/memory/concern-board.js +3 -1
  185. package/lib/ui/memory/concern-board.js.map +1 -1
  186. package/lib/ui/memory/concern-execution-status.d.ts +8 -0
  187. package/lib/ui/memory/concern-execution-status.d.ts.map +1 -0
  188. package/lib/ui/memory/concern-execution-status.js +31 -0
  189. package/lib/ui/memory/concern-execution-status.js.map +1 -0
  190. package/lib/ui/push-channels.d.ts +11 -0
  191. package/lib/ui/push-channels.d.ts.map +1 -0
  192. package/lib/ui/push-channels.js +28 -0
  193. package/lib/ui/push-channels.js.map +1 -0
  194. package/lib/ui/push-draft.d.ts +30 -0
  195. package/lib/ui/push-draft.d.ts.map +1 -0
  196. package/lib/ui/push-draft.js +13 -0
  197. package/lib/ui/push-draft.js.map +1 -0
  198. package/lib/ui/push-editor.d.ts +10 -0
  199. package/lib/ui/push-editor.d.ts.map +1 -0
  200. package/lib/ui/push-editor.js +99 -0
  201. package/lib/ui/push-editor.js.map +1 -0
  202. package/lib/ui/runtime-settings.d.ts +18 -0
  203. package/lib/ui/runtime-settings.d.ts.map +1 -0
  204. package/lib/ui/runtime-settings.js +25 -0
  205. package/lib/ui/runtime-settings.js.map +1 -0
  206. package/lib/ui/workspace-components.d.ts +7 -1
  207. package/lib/ui/workspace-components.d.ts.map +1 -1
  208. package/lib/ui/workspace-components.js +8 -4
  209. package/lib/ui/workspace-components.js.map +1 -1
  210. package/package.json +6 -1
@@ -0,0 +1,66 @@
1
+ /** Single-direction channels share delivery semantics, not chat pairing. */
2
+ export interface PushTarget {
3
+ id: string;
4
+ name: string;
5
+ enabled: boolean;
6
+ credentialId: string;
7
+ fingerprint: string;
8
+ }
9
+ export interface PushChannel {
10
+ id: string;
11
+ companionId: string;
12
+ platform: 'bark';
13
+ name: string;
14
+ baseUrl: string;
15
+ enabled: boolean;
16
+ revision: number;
17
+ createdAt: number;
18
+ updatedAt: number;
19
+ targets: PushTarget[];
20
+ notifyProblems: boolean;
21
+ content: 'summary' | 'title';
22
+ group: string;
23
+ sound: string;
24
+ openUrl: string;
25
+ }
26
+ export interface PushEvent {
27
+ id: string;
28
+ companionId: string;
29
+ title: string;
30
+ text: string;
31
+ createdAt: number;
32
+ outcome: 'completed' | 'problem';
33
+ }
34
+ export interface PushDelivery {
35
+ id: string;
36
+ companionId: string;
37
+ eventId: string;
38
+ channelId: string;
39
+ targetId: string;
40
+ revision: number;
41
+ title: string;
42
+ body: string;
43
+ createdAt: number;
44
+ updatedAt: number;
45
+ nextAttemptAt: number;
46
+ expiresAt?: number;
47
+ status: 'pending' | 'sending' | 'accepted' | 'failed' | 'canceled';
48
+ attempts: number;
49
+ lastError?: string;
50
+ }
51
+ export type PushChannelView = Omit<PushChannel, 'targets'> & {
52
+ targets: Array<Pick<PushTarget, 'id' | 'name' | 'enabled'> & {
53
+ configured: boolean;
54
+ }>;
55
+ pending: number;
56
+ failed: number;
57
+ lastDelivery?: Pick<PushDelivery, 'status' | 'updatedAt' | 'lastError'>;
58
+ };
59
+ export interface PushAdapter {
60
+ send(channel: PushChannel, deviceKey: string, payload: {
61
+ title: string;
62
+ body: string;
63
+ }, signal: AbortSignal): Promise<void>;
64
+ }
65
+ export declare function pushSummary(text: string): string;
66
+ //# sourceMappingURL=push-domain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-domain.d.ts","sourceRoot":"","sources":["../../src/notifications/push-domain.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,MAAM,WAAW,UAAU;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE;AACrH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;IAChF,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;IACxE,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,cAAc,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CACrG;AACD,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;IAC/E,OAAO,EAAE,WAAW,GAAG,SAAS,CAAA;CACjC;AACD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;IACvG,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC5G,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CACzG;AACD,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG;IAC3D,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IACrF,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC,CAAA;CACzG,CAAA;AACD,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5H;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIhD"}
@@ -0,0 +1,6 @@
1
+ export function pushSummary(text) {
2
+ return text.replace(/```[\s\S]*?```/g, ' [代码或内容详见会话] ')
3
+ .replace(/!?\[([^\]]*)\]\([^)]*\)/g, '$1').replace(/<[^>]+>/g, '')
4
+ .replace(/^[\s#>*-]+/gm, '').replace(/\s+/g, ' ').trim().slice(0, 500);
5
+ }
6
+ //# sourceMappingURL=push-domain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-domain.js","sourceRoot":"","sources":["../../src/notifications/push-domain.ts"],"names":[],"mappings":"AAyBA,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,eAAe,CAAC;SACpD,OAAO,CAAC,0BAA0B,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACjE,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AAC1E,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { Session, SessionEvent } from '@deepseek-ai/dsh-session';
2
+ import type { PartnerState } from '../domain.js';
3
+ import type { PartnerStore } from '../store.js';
4
+ import type { PushEvent } from './push-domain.js';
5
+ import type { PushService } from './push-service.js';
6
+ export declare function pushEventsFromChanges(next: PartnerState, previous: PartnerState): PushEvent[];
7
+ export declare class PushObserver {
8
+ private readonly store;
9
+ private readonly push;
10
+ private readonly report;
11
+ private readonly stop;
12
+ private closed;
13
+ private readonly pending;
14
+ constructor(store: PartnerStore, push: PushService, report: () => void);
15
+ private submit;
16
+ observeSession(session: Session, event: SessionEvent): void;
17
+ close(): Promise<void>;
18
+ }
19
+ //# sourceMappingURL=push-observer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-observer.d.ts","sourceRoot":"","sources":["../../src/notifications/push-observer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAI/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAGpD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,GAAG,SAAS,EAAE,CA8B7F;AAED,qBAAa,YAAY;IAIX,OAAO,CAAC,QAAQ,CAAC,KAAK;IAAgB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAe,OAAO,CAAC,QAAQ,CAAC,MAAM;IAH7G,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAY;IACjC,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;gBACtB,KAAK,EAAE,YAAY,EAAmB,IAAI,EAAE,WAAW,EAAmB,MAAM,EAAE,MAAM,IAAI;IAMzH,OAAO,CAAC,MAAM;IAKd,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI;IAuBrD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAC7B"}
@@ -0,0 +1,96 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { completedTurnEvents } from '../agent-runtime.js';
3
+ import { channelReplyPartsAfter, isAutonomousDeliveryTurn, isRequirementDeliveryReceipt } from '../channels/delivery-policy.js';
4
+ import { continuationFinalReply } from '../scheduler/final-reply.js';
5
+ const digest = (value) => createHash('sha256').update(value).digest('hex').slice(0, 24);
6
+ export function pushEventsFromChanges(next, previous) {
7
+ const events = [];
8
+ const names = new Map(next.companions.map(c => [c.id, c.name]));
9
+ for (const item of next.requirements ?? []) {
10
+ if (!item.ownerCompanionId || !names.has(item.ownerCompanionId))
11
+ continue;
12
+ const old = previous.requirements?.find(r => r.id === item.id);
13
+ if (item.status === 'done' && item.summary && (old?.status !== 'done' || old.summary !== item.summary)) {
14
+ events.push({ id: `requirement:${item.id}:${digest(item.summary)}`, companionId: item.ownerCompanionId,
15
+ title: `${names.get(item.ownerCompanionId)} · 需求完成`, text: `${item.title}\n${item.summary}`, createdAt: item.updatedAt, outcome: 'completed' });
16
+ }
17
+ else if (item.stageReport?.summary && old?.stageReport?.key !== item.stageReport.key
18
+ && next.tasks.some(t => t.requirementId === item.id && t.status === 'blocked')) {
19
+ events.push({ id: `requirement-blocked:${item.id}:${item.stageReport.key}`, companionId: item.ownerCompanionId,
20
+ title: `${names.get(item.ownerCompanionId)} · 需要处理`, text: item.stageReport.summary, createdAt: item.stageReport.createdAt, outcome: 'problem' });
21
+ }
22
+ }
23
+ for (const entry of next.schedules) {
24
+ const wake = entry.continuation;
25
+ if (!wake?.finalReply || wake.board || !['completed', 'blocked'].includes(wake.state) || previous.schedules.find(s => s.id === entry.id)?.continuation?.finalReply?.key === wake.finalReply.key)
26
+ continue;
27
+ events.push({ id: `reply:${wake.finalReply.key}`, companionId: entry.companionId,
28
+ title: `${names.get(entry.companionId) ?? '伙伴'} · ${wake.state === 'completed' ? '执行完成' : '需要处理'}`,
29
+ text: wake.finalReply.text, createdAt: Date.now(), outcome: wake.state === 'completed' ? 'completed' : 'problem' });
30
+ }
31
+ for (const run of next.executionRuns) {
32
+ if (run.kind !== 'schedule' || !['completed', 'failed', 'timed-out'].includes(run.status) || previous.executionRuns.find(r => r.id === run.id)?.status === run.status)
33
+ continue;
34
+ const entry = next.schedules.find(s => s.id === run.sourceId);
35
+ if (!entry || entry.continuation || entry.boardTaskId)
36
+ continue;
37
+ events.push({ id: `schedule:${run.id}`, companionId: run.ownerCompanionId, title: `${names.get(run.ownerCompanionId) ?? '伙伴'} · ${entry.title}`,
38
+ text: run.outputSummary || run.error || '定时执行已结束,请查看记录。', createdAt: run.completedAt ?? Date.now(), outcome: run.status === 'completed' ? 'completed' : 'problem' });
39
+ }
40
+ return events;
41
+ }
42
+ export class PushObserver {
43
+ store;
44
+ push;
45
+ report;
46
+ stop;
47
+ closed = false;
48
+ pending = new Set();
49
+ constructor(store, push, report) {
50
+ this.store = store;
51
+ this.push = push;
52
+ this.report = report;
53
+ this.stop = store.subscribe((next, old) => {
54
+ if (!next.pushChannels?.some(c => c.enabled))
55
+ return;
56
+ for (const event of pushEventsFromChanges(next, old))
57
+ this.submit(event);
58
+ }, report);
59
+ }
60
+ submit(event) {
61
+ if (this.closed)
62
+ return;
63
+ const work = this.push.enqueue(event).catch(this.report).finally(() => this.pending.delete(work));
64
+ this.pending.add(work);
65
+ }
66
+ observeSession(session, event) {
67
+ if (this.closed || event.type !== 'turn/end' || event.data.reason.kind !== 'completed')
68
+ return;
69
+ const state = this.store.snapshot();
70
+ const route = state.sessions.find(r => r.sessionId === session.id);
71
+ const companion = state.companions.find(c => c.id === route?.companionId);
72
+ if (!companion || !state.pushChannels?.some(c => c.companionId === companion.id && c.enabled))
73
+ return;
74
+ const history = session.snapshotEvents().filter(e => e.seq < event.seq);
75
+ const turn = completedTurnEvents(history, event);
76
+ const continuation = continuationFinalReply(state.schedules, session.id, history, turn, event);
77
+ if (continuation) {
78
+ const wake = state.schedules.find(s => s.id === continuation.id).continuation;
79
+ this.submit({ id: `reply:${continuation.reply.key}`, companionId: companion.id,
80
+ title: `${companion.name} · ${wake.state === 'completed' ? '执行完成' : '需要处理'}`, text: continuation.reply.text,
81
+ createdAt: Date.now(), outcome: wake.state === 'completed' ? 'completed' : 'problem' });
82
+ return;
83
+ }
84
+ // Requirement delivery has its own single receipt. Internal review/heartbeat
85
+ // turns never become user notifications just because a model turn ended.
86
+ if (turn.some(isRequirementDeliveryReceipt))
87
+ return;
88
+ const parts = channelReplyPartsAfter(turn, -1, isAutonomousDeliveryTurn(turn, history));
89
+ if (!parts.text)
90
+ return;
91
+ this.submit({ id: `reply:${session.id}:${event.data.turn}`, companionId: companion.id,
92
+ title: `${companion.name} · 回复完成`, text: parts.text, createdAt: Date.now(), outcome: 'completed' });
93
+ }
94
+ async close() { this.closed = true; this.stop(); await Promise.all(this.pending); }
95
+ }
96
+ //# sourceMappingURL=push-observer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-observer.js","sourceRoot":"","sources":["../../src/notifications/push-observer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { PartnerStore } from '../store.js';
2
+ import type { PushCredentials } from './push-credentials.js';
3
+ import { type PushAdapter, type PushChannel, type PushChannelView, type PushDelivery, type PushEvent } from './push-domain.js';
4
+ /** Durable outbox independent of chat routing, pairing and conversation speed. */
5
+ export declare class PushService {
6
+ private readonly store;
7
+ private readonly vault;
8
+ private readonly report;
9
+ private readonly adapters;
10
+ private readonly shutdown;
11
+ private timer?;
12
+ private running?;
13
+ private writes;
14
+ constructor(store: PartnerStore, vault: PushCredentials, report: (message: string) => void, adapters?: Readonly<Record<string, PushAdapter>>);
15
+ views(companionId?: string): PushChannelView[];
16
+ require(id: string): PushChannel;
17
+ private serial;
18
+ save(companionId: string, raw: Record<string, unknown>, id?: string): Promise<PushChannelView>;
19
+ remove(id: string): Promise<void>;
20
+ removeOwner(id: string): Promise<void>;
21
+ deliveries(id: string): PushDelivery[];
22
+ clearHistory(id: string): Promise<void>;
23
+ retry(id: string, rowId: string): Promise<void>;
24
+ test(id: string, targetId: string): Promise<void>;
25
+ enqueue(event: PushEvent): Promise<void>;
26
+ start(): Promise<void>;
27
+ private kick;
28
+ flush(): Promise<void>;
29
+ private send;
30
+ private patch;
31
+ close(): Promise<void>;
32
+ }
33
+ //# sourceMappingURL=push-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-service.d.ts","sourceRoot":"","sources":["../../src/notifications/push-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAI/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAC5D,OAAO,EAAe,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAE3I,kFAAkF;AAClF,qBAAa,WAAW;IAKV,OAAO,CAAC,QAAQ,CAAC,KAAK;IAAgB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtE,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAN3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwB;IACjD,OAAO,CAAC,KAAK,CAAC,CAAgC;IAC9C,OAAO,CAAC,OAAO,CAAC,CAAe;IAC/B,OAAO,CAAC,MAAM,CAAsC;gBACvB,KAAK,EAAE,YAAY,EAAmB,KAAK,EAAE,eAAe,EACtE,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EACjC,QAAQ,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAyB;IAE1F,KAAK,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,eAAe,EAAE;IAU9C,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW;IAKhC,OAAO,CAAC,MAAM;IAKd,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAuB9F,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU3B,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAG5C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,EAAE;IAChC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU/C,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,OAAO,CAAC,IAAI;IACN,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAOd,IAAI;YAwBJ,KAAK;IACb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAC7B"}
@@ -0,0 +1,228 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { httpError } from '../api/http.js';
3
+ import { parsePushChannel } from './push-config.js';
4
+ import { barkAdapter, PushSendError } from './bark-adapter.js';
5
+ import { pushSummary } from './push-domain.js';
6
+ /** Durable outbox independent of chat routing, pairing and conversation speed. */
7
+ export class PushService {
8
+ store;
9
+ vault;
10
+ report;
11
+ adapters;
12
+ shutdown = new AbortController();
13
+ timer;
14
+ running;
15
+ writes = Promise.resolve();
16
+ constructor(store, vault, report, adapters = { bark: barkAdapter }) {
17
+ this.store = store;
18
+ this.vault = vault;
19
+ this.report = report;
20
+ this.adapters = adapters;
21
+ }
22
+ views(companionId) {
23
+ const state = this.store.snapshot();
24
+ return (state.pushChannels ?? []).filter(c => !companionId || c.companionId === companionId).map(c => {
25
+ const rows = (state.pushDeliveries ?? []).filter(r => r.channelId === c.id).sort((a, b) => b.updatedAt - a.updatedAt);
26
+ const last = rows[0];
27
+ return { ...c, targets: c.targets.map(({ id, name, enabled }) => ({ id, name, enabled, configured: true })),
28
+ pending: rows.filter(r => ['pending', 'sending'].includes(r.status)).length, failed: rows.filter(r => r.status === 'failed').length,
29
+ ...(last ? { lastDelivery: { status: last.status, updatedAt: last.updatedAt, ...(last.lastError ? { lastError: last.lastError } : {}) } } : {}) };
30
+ });
31
+ }
32
+ require(id) {
33
+ const channel = this.store.snapshot().pushChannels?.find(c => c.id === id);
34
+ if (!channel)
35
+ throw httpError(404, '推送渠道不存在');
36
+ return channel;
37
+ }
38
+ serial(fn) {
39
+ const result = this.writes.then(fn);
40
+ this.writes = result.catch(() => { });
41
+ return result;
42
+ }
43
+ save(companionId, raw, id) {
44
+ return this.serial(async () => {
45
+ const state = this.store.snapshot(), previous = id ? this.require(id) : undefined;
46
+ if (!state.companions.some(c => c.id === companionId) || this.store.isCompanionRemoving(companionId))
47
+ throw httpError(404, '伙伴不存在或正在删除');
48
+ if (previous && previous.companionId !== companionId)
49
+ throw httpError(400, '渠道不属于该伙伴');
50
+ if (previous && raw.revision !== previous.revision)
51
+ throw httpError(409, '渠道已更新,请重新打开配置');
52
+ if (!previous && (state.pushChannels ?? []).filter(c => c.companionId === companionId).length >= 20)
53
+ throw httpError(400, '每位伙伴最多配置 20 个推送服务器');
54
+ const { channel, secrets } = parsePushChannel(raw, companionId, previous);
55
+ try {
56
+ for (const secret of secrets)
57
+ await this.vault.write(secret.id, secret.key);
58
+ await this.store.update(draft => {
59
+ if (!draft.companions.some(c => c.id === companionId) || this.store.isCompanionRemoving(companionId))
60
+ throw httpError(409, '伙伴正在删除');
61
+ if (previous && draft.pushChannels?.find(c => c.id === id)?.revision !== previous.revision)
62
+ throw httpError(409, '渠道已更新,请重新打开配置');
63
+ draft.pushChannels = [...(draft.pushChannels ?? []).filter(c => c.id !== channel.id), channel];
64
+ for (const row of draft.pushDeliveries ?? [])
65
+ if (row.channelId === channel.id && ['pending', 'sending', 'failed'].includes(row.status)) {
66
+ row.status = 'canceled';
67
+ row.updatedAt = Date.now();
68
+ row.lastError = '渠道配置已修改,旧通知已取消,避免发给新目标';
69
+ }
70
+ });
71
+ }
72
+ catch (error) {
73
+ await Promise.all(secrets.map(s => this.vault.delete(s.id).catch(() => { })));
74
+ throw error;
75
+ }
76
+ for (const target of previous?.targets ?? [])
77
+ if (!channel.targets.some(t => t.credentialId === target.credentialId))
78
+ await this.vault.delete(target.credentialId).catch(() => this.report('旧推送凭据清理失败'));
79
+ return this.views(companionId).find(c => c.id === channel.id);
80
+ });
81
+ }
82
+ remove(id) {
83
+ return this.serial(async () => {
84
+ const channel = this.require(id);
85
+ await this.store.update(state => {
86
+ state.pushChannels = (state.pushChannels ?? []).filter(c => c.id !== id);
87
+ state.pushDeliveries = (state.pushDeliveries ?? []).filter(r => r.channelId !== id);
88
+ });
89
+ await Promise.all(channel.targets.map(t => this.vault.delete(t.credentialId).catch(() => this.report('推送凭据清理失败'))));
90
+ });
91
+ }
92
+ async removeOwner(id) {
93
+ for (const channel of this.store.snapshot().pushChannels ?? [])
94
+ if (channel.companionId === id)
95
+ await this.remove(channel.id);
96
+ }
97
+ deliveries(id) { this.require(id); return (this.store.snapshot().pushDeliveries ?? []).filter(r => r.channelId === id).sort((a, b) => b.createdAt - a.createdAt).slice(0, 100); }
98
+ async clearHistory(id) {
99
+ this.require(id);
100
+ await this.store.update(state => { state.pushDeliveries = (state.pushDeliveries ?? []).filter(r => r.channelId !== id || !['accepted', 'canceled'].includes(r.status)); });
101
+ }
102
+ async retry(id, rowId) {
103
+ await this.store.update(state => {
104
+ const channel = state.pushChannels?.find(c => c.id === id);
105
+ const row = state.pushDeliveries?.find(r => r.id === rowId && r.channelId === id);
106
+ if (!row || row.status !== 'failed')
107
+ throw httpError(400, '仅可重试失败的通知');
108
+ if (!channel?.enabled || channel.revision !== row.revision || !channel.targets.some(t => t.id === row.targetId && t.enabled))
109
+ throw httpError(400, '原接收目标已失效,不能重试');
110
+ row.status = 'pending';
111
+ row.attempts = 0;
112
+ row.nextAttemptAt = Date.now();
113
+ row.updatedAt = Date.now();
114
+ row.expiresAt = Date.now() + 86400_000;
115
+ delete row.lastError;
116
+ });
117
+ this.kick();
118
+ }
119
+ async test(id, targetId) {
120
+ const channel = this.require(id), target = channel.targets.find(t => t.id === targetId);
121
+ if (!target)
122
+ throw httpError(404, '发送目标不存在');
123
+ await this.adapters[channel.platform].send(channel, await this.vault.read(target.credentialId), {
124
+ title: 'DSH 伙伴 · Bark 测试', body: `这是一条测试通知,来自“${channel.name}”。能看到此消息说明手机推送可达。`,
125
+ }, this.shutdown.signal);
126
+ }
127
+ async enqueue(event) {
128
+ if (this.shutdown.signal.aborted)
129
+ return;
130
+ const eligible = (this.store.snapshot().pushChannels ?? []).some(c => c.companionId === event.companionId && c.enabled);
131
+ if (!eligible)
132
+ return;
133
+ await this.store.update(state => {
134
+ const rows = state.pushDeliveries ??= [], seen = new Set();
135
+ for (const c of state.pushChannels ?? []) {
136
+ if (!c.enabled || c.companionId !== event.companionId || event.createdAt < c.createdAt || (event.outcome === 'problem' && !c.notifyProblems))
137
+ continue;
138
+ for (const t of c.targets.filter(t => t.enabled)) {
139
+ const recipient = `${c.baseUrl}:${t.fingerprint}`;
140
+ if (seen.has(recipient))
141
+ continue;
142
+ seen.add(recipient);
143
+ const id = createHash('sha256').update(JSON.stringify([event.id, event.companionId, recipient])).digest('hex');
144
+ if (rows.some(r => r.id === id))
145
+ continue;
146
+ while (rows.length >= 1000) {
147
+ const index = rows.findIndex(r => ['accepted', 'canceled'].includes(r.status) && r.createdAt < Date.now() - 7 * 86400_000);
148
+ if (index < 0)
149
+ throw Error('Bark 通知记录已满,请清理发送记录');
150
+ rows.splice(index, 1);
151
+ }
152
+ rows.push({ id, companionId: event.companionId, eventId: event.id, channelId: c.id, targetId: t.id, revision: c.revision,
153
+ title: event.title.slice(0, 120), body: c.content === 'title' ? '请返回 DSH 查看伙伴会话。' : pushSummary(event.text) || '本轮已完成,请查看会话。',
154
+ createdAt: event.createdAt, updatedAt: Date.now(), nextAttemptAt: Date.now(), status: 'pending', attempts: 0 });
155
+ }
156
+ }
157
+ });
158
+ this.kick();
159
+ }
160
+ async start() {
161
+ if (this.store.snapshot().pushDeliveries?.some(r => r.status === 'sending'))
162
+ await this.store.update(state => { for (const row of state.pushDeliveries ?? [])
163
+ if (row.status === 'sending') {
164
+ row.status = 'pending';
165
+ row.nextAttemptAt = Date.now();
166
+ } });
167
+ this.timer = setInterval(() => this.kick(), 15_000);
168
+ this.timer.unref();
169
+ this.kick();
170
+ }
171
+ kick() { if (!this.running && !this.shutdown.signal.aborted) {
172
+ this.running = this.flush().catch(() => this.report('推送队列处理失败,将自动重试')).finally(() => { delete this.running; });
173
+ } }
174
+ async flush() {
175
+ const rows = (this.store.snapshot().pushDeliveries ?? []).filter(r => r.status === 'pending' && r.nextAttemptAt <= Date.now()).slice(0, 30);
176
+ let cursor = 0;
177
+ await Promise.all(Array.from({ length: Math.min(3, rows.length) }, async () => {
178
+ while (!this.shutdown.signal.aborted && cursor < rows.length)
179
+ await this.send(rows[cursor++]);
180
+ }));
181
+ }
182
+ async send(row) {
183
+ if (Date.now() > (row.expiresAt ?? row.createdAt + 86400_000)) {
184
+ await this.patch(row.id, r => { if (r.status === 'pending') {
185
+ r.status = 'failed';
186
+ r.lastError = '通知已超过 24 小时,停止自动补发';
187
+ } });
188
+ return;
189
+ }
190
+ const state = this.store.snapshot(), channel = state.pushChannels?.find(c => c.id === row.channelId), target = channel?.targets.find(t => t.id === row.targetId);
191
+ if (!channel?.enabled || !target?.enabled || channel.revision !== row.revision || !state.companions.some(c => c.id === row.companionId) || this.store.isCompanionRemoving(row.companionId)) {
192
+ await this.patch(row.id, r => { r.status = 'canceled'; r.lastError = '原渠道或接收目标已停用'; });
193
+ return;
194
+ }
195
+ let claimed = false;
196
+ await this.patch(row.id, r => { if (r.status === 'pending' && r.revision === channel.revision) {
197
+ r.status = 'sending';
198
+ r.attempts++;
199
+ claimed = true;
200
+ } });
201
+ if (!claimed)
202
+ return;
203
+ try {
204
+ const key = await this.vault.read(target.credentialId);
205
+ await this.adapters[channel.platform].send(channel, key, row, this.shutdown.signal);
206
+ await this.patch(row.id, r => { if (r.status === 'sending') {
207
+ r.status = 'accepted';
208
+ delete r.lastError;
209
+ } });
210
+ }
211
+ catch (error) {
212
+ await this.patch(row.id, r => {
213
+ if (r.status !== 'sending')
214
+ return;
215
+ const retry = this.shutdown.signal.aborted || (error instanceof PushSendError && error.retryable && r.attempts < 5);
216
+ r.status = retry ? 'pending' : 'failed';
217
+ r.nextAttemptAt = Date.now() + Math.min(300_000, 15_000 * 2 ** (r.attempts - 1));
218
+ r.lastError = error instanceof PushSendError ? error.message : '推送凭据或配置不可用,请检查后重试';
219
+ });
220
+ }
221
+ }
222
+ async patch(id, change) { await this.store.update(state => { const row = state.pushDeliveries?.find(r => r.id === id); if (row) {
223
+ change(row);
224
+ row.updatedAt = Date.now();
225
+ } }); }
226
+ async close() { this.shutdown.abort(); clearInterval(this.timer); await this.running; await this.writes; }
227
+ }
228
+ //# sourceMappingURL=push-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-service.js","sourceRoot":"","sources":["../../src/notifications/push-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { PartnerState } from '../domain.js';
2
+ export declare function validatePushState(state: Partial<PartnerState>): void;
3
+ //# sourceMappingURL=push-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-state.d.ts","sourceRoot":"","sources":["../../src/notifications/push-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAiBpE"}
@@ -0,0 +1,23 @@
1
+ export function validatePushState(state) {
2
+ if (state.pushChannels !== undefined && !Array.isArray(state.pushChannels))
3
+ throw Error('invalid push channels');
4
+ const ids = new Set();
5
+ for (const c of state.pushChannels ?? []) {
6
+ if (!c || typeof c.id !== 'string' || ids.has(c.id) || c.platform !== 'bark' || !state.companions?.some(owner => owner.id === c.companionId)
7
+ || typeof c.name !== 'string' || typeof c.baseUrl !== 'string' || typeof c.enabled !== 'boolean' || !Number.isSafeInteger(c.revision)
8
+ || !Array.isArray(c.targets) || c.targets.length > 50 || !c.targets.length
9
+ || c.targets.some(t => !t || typeof t.id !== 'string' || typeof t.name !== 'string' || typeof t.enabled !== 'boolean' || !/^push-[a-z0-9-]+$/.test(t.credentialId) || !/^[a-f0-9]{64}$/.test(t.fingerprint)))
10
+ throw Error('invalid push channel configuration');
11
+ ids.add(c.id);
12
+ }
13
+ if (state.pushDeliveries !== undefined && (!Array.isArray(state.pushDeliveries) || state.pushDeliveries.length > 1000))
14
+ throw Error('invalid push outbox');
15
+ for (const r of state.pushDeliveries ?? []) {
16
+ if (!r || typeof r.id !== 'string' || typeof r.companionId !== 'string' || typeof r.channelId !== 'string' || typeof r.targetId !== 'string'
17
+ || typeof r.title !== 'string' || typeof r.body !== 'string' || !Number.isFinite(r.createdAt) || !Number.isFinite(r.nextAttemptAt)
18
+ || (r.expiresAt !== undefined && !Number.isFinite(r.expiresAt))
19
+ || !['pending', 'sending', 'accepted', 'failed', 'canceled'].includes(r.status) || !Number.isSafeInteger(r.attempts))
20
+ throw Error('invalid push delivery');
21
+ }
22
+ }
23
+ //# sourceMappingURL=push-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-state.js","sourceRoot":"","sources":["../../src/notifications/push-state.ts"],"names":[],"mappings":"AACA,MAAM,UAAU,iBAAiB,CAAC,KAA4B;IAC5D,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC;QAAE,MAAM,KAAK,CAAC,uBAAuB,CAAC,CAAA;IAChH,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAA;IAC7B,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;QACzC,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,WAAW,CAAC;eACvI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC;eAClI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM;eACvE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;YAAE,MAAM,KAAK,CAAC,oCAAoC,CAAC,CAAA;QACjQ,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IACf,CAAC;IACD,IAAI,KAAK,CAAC,cAAc,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,cAAc,CAAC,MAAM,GAAG,IAAI,CAAC;QAAE,MAAM,KAAK,CAAC,qBAAqB,CAAC,CAAA;IAC1J,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,cAAc,IAAI,EAAE,EAAE,CAAC;QAC3C,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ;eACvI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC;eAC/H,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;eAC5D,CAAC,CAAC,SAAS,EAAC,SAAS,EAAC,UAAU,EAAC,QAAQ,EAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC;YAAE,MAAM,KAAK,CAAC,uBAAuB,CAAC,CAAA;IAC1J,CAAC;AACH,CAAC"}
@@ -1,9 +1,10 @@
1
1
  /** Per concern: bounded reasoning rounds, with an independent final response. */
2
2
  export declare const OBSERVATION_CHECK_ROUNDS = 12;
3
+ export declare const OBSERVATION_PREPARATION_ROUNDS = 8;
3
4
  export declare const OBSERVATION_MODEL_TIMEOUT_MS = 180000;
4
5
  export declare const OBSERVATION_TOOL_TIMEOUT_MS = 60000;
5
- export declare function observationBudget(round: number): {
6
+ export declare function observationBudget(round: number, preparationRounds?: number): {
6
7
  checking: boolean;
7
8
  };
8
- export declare const observationFinalInstruction = "\u68C0\u67E5\u9636\u6BB5\u5DF2\u7ED3\u675F\u3002\u53EA\u57FA\u4E8E\u5DF2\u5B8C\u6574\u8FD4\u56DE\u7684\u8BC1\u636E\u8F93\u51FA\u7EA6\u5B9A JSON\uFF0C\u4E0D\u8C03\u7528\u5DE5\u5177\uFF0C\u4E0D\u8865\u9020\u8BC1\u636E\u3002\u5FC5\u8981\u6B65\u9AA4\u672A\u5B8C\u6210\u7684\u5173\u6CE8\u5FC5\u987B\u6807\u8BB0 blocked\uFF0C\u5E76\u8BF4\u660E\u672A\u5B8C\u6210\u6B65\u9AA4\uFF1B\u5DF2\u6838\u5B9E\u7684\u5173\u6CE8\u53EF\u6B63\u5E38\u8FD4\u56DE\u3002\u672A\u6210\u529F\u5199\u5165\u8BB0\u5F55\u4E0D\u5F97\u58F0\u79F0\u5DF2\u8BB0\u5F55\u3002";
9
+ export declare const observationFinalInstruction = "\u68C0\u67E5\u9636\u6BB5\u5DF2\u7ED3\u675F\u3002\u53EA\u57FA\u4E8E\u5DF2\u5B8C\u6574\u8FD4\u56DE\u7684\u8BC1\u636E\u8F93\u51FA\u7EA6\u5B9A JSON\uFF0C\u4E0D\u8C03\u7528\u5DE5\u5177\uFF0C\u4E0D\u8865\u9020\u8BC1\u636E\u3002\u6BCF\u9879 observations \u53EF\u7528 workflowChecks \u6570\u7EC4\u4E00\u6B21\u767B\u8BB0\u5DF2\u89C4\u5212\u7684\u68C0\u67E5\u6B65\u9AA4\uFF0C\u6BCF\u9879\u4E3A {stepId,status:\"completed\"|\"blocked\",evidence}\uFF1B\u5DF2\u7ECF\u6838\u5B9E\u4F46\u672A\u8C03\u7528 update \u767B\u8BB0\u7684\u6B65\u9AA4\u5728\u6B64\u63D0\u4EA4\u5373\u53EF\uFF0C\u4E0D\u5E94\u4EC5\u56E0\u5C11\u4E00\u6B21\u767B\u8BB0\u8C03\u7528\u5224\u4E3A\u53D7\u963B\u3002\u5FC5\u8981\u6838\u9A8C\u672A\u5B9E\u9645\u5B8C\u6210\u7684\u5173\u6CE8\u4ECD\u987B\u6807\u8BB0 blocked\uFF1Bexecute \u9636\u6BB5\u5C1A\u672A\u6267\u884C\u4E0D\u662F\u68C0\u67E5\u53D7\u963B\u3002\u672A\u6210\u529F\u5199\u5165\u8BB0\u5F55\u4E0D\u5F97\u58F0\u79F0\u5DF2\u8BB0\u5F55\u3002";
9
10
  //# sourceMappingURL=observation-budget.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"observation-budget.d.ts","sourceRoot":"","sources":["../src/observation-budget.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAC1C,eAAO,MAAM,4BAA4B,SAAU,CAAA;AACnD,eAAO,MAAM,2BAA2B,QAAS,CAAA;AACjD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM;;EAE9C;AAED,eAAO,MAAM,2BAA2B,4hBAAyG,CAAA"}
1
+ {"version":3,"file":"observation-budget.d.ts","sourceRoot":"","sources":["../src/observation-budget.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,eAAO,MAAM,wBAAwB,KAAK,CAAA;AAC1C,eAAO,MAAM,8BAA8B,IAAI,CAAA;AAC/C,eAAO,MAAM,4BAA4B,SAAU,CAAA;AACnD,eAAO,MAAM,2BAA2B,QAAS,CAAA;AACjD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,iBAAiB,SAAI;;EAGrE;AAED,eAAO,MAAM,2BAA2B,27BAA2P,CAAA"}
@@ -1,9 +1,11 @@
1
1
  /** Per concern: bounded reasoning rounds, with an independent final response. */
2
2
  export const OBSERVATION_CHECK_ROUNDS = 12;
3
+ export const OBSERVATION_PREPARATION_ROUNDS = 8;
3
4
  export const OBSERVATION_MODEL_TIMEOUT_MS = 180_000;
4
5
  export const OBSERVATION_TOOL_TIMEOUT_MS = 60_000;
5
- export function observationBudget(round) {
6
- return { checking: round < OBSERVATION_CHECK_ROUNDS };
6
+ export function observationBudget(round, preparationRounds = 0) {
7
+ const preparation = Math.max(0, Math.min(OBSERVATION_PREPARATION_ROUNDS, preparationRounds));
8
+ return { checking: round - preparation < OBSERVATION_CHECK_ROUNDS && round < OBSERVATION_CHECK_ROUNDS + OBSERVATION_PREPARATION_ROUNDS };
7
9
  }
8
- export const observationFinalInstruction = '检查阶段已结束。只基于已完整返回的证据输出约定 JSON,不调用工具,不补造证据。必要步骤未完成的关注必须标记 blocked,并说明未完成步骤;已核实的关注可正常返回。未成功写入记录不得声称已记录。';
10
+ export const observationFinalInstruction = '检查阶段已结束。只基于已完整返回的证据输出约定 JSON,不调用工具,不补造证据。每项 observations 可用 workflowChecks 数组一次登记已规划的检查步骤,每项为 {stepId,status:"completed"|"blocked",evidence};已经核实但未调用 update 登记的步骤在此提交即可,不应仅因少一次登记调用判为受阻。必要核验未实际完成的关注仍须标记 blocked;execute 阶段尚未执行不是检查受阻。未成功写入记录不得声称已记录。';
9
11
  //# sourceMappingURL=observation-budget.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"observation-budget.js","sourceRoot":"","sources":["../src/observation-budget.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAA;AAC1C,MAAM,CAAC,MAAM,4BAA4B,GAAG,OAAO,CAAA;AACnD,MAAM,CAAC,MAAM,2BAA2B,GAAG,MAAM,CAAA;AACjD,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,EAAE,QAAQ,EAAE,KAAK,GAAG,wBAAwB,EAAE,CAAA;AACvD,CAAC;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAG,sGAAsG,CAAA"}
1
+ {"version":3,"file":"observation-budget.js","sourceRoot":"","sources":["../src/observation-budget.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAA;AAC1C,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAA;AAC/C,MAAM,CAAC,MAAM,4BAA4B,GAAG,OAAO,CAAA;AACnD,MAAM,CAAC,MAAM,2BAA2B,GAAG,MAAM,CAAA;AACjD,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,iBAAiB,GAAG,CAAC;IACpE,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,8BAA8B,EAAE,iBAAiB,CAAC,CAAC,CAAA;IAC5F,OAAO,EAAE,QAAQ,EAAE,KAAK,GAAG,WAAW,GAAG,wBAAwB,IAAI,KAAK,GAAG,wBAAwB,GAAG,8BAA8B,EAAE,CAAA;AAC1I,CAAC;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAG,wPAAwP,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"observation-executor.d.ts","sourceRoot":"","sources":["../src/observation-executor.ts"],"names":[],"mappings":"AACA,6FAA6F;AAC7F,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC;;;;;cAOrC,MAAM;kBAAY,MAAM;;;EAqBhE"}
1
+ {"version":3,"file":"observation-executor.d.ts","sourceRoot":"","sources":["../src/observation-executor.ts"],"names":[],"mappings":"AACA,6FAA6F;AAC7F,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC;;;;;cAOrC,MAAM;kBAAY,MAAM;;;EAyBhE"}