@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.
- package/README.md +27 -406
- package/docs/bark-notifications.md +27 -0
- package/docs/concern-workflow.md +39 -0
- package/docs/observation-contract.md +11 -1
- package/docs/pendant-loading.md +30 -0
- package/docs/releases/1.12.0.md +16 -0
- package/docs/releases/1.14.2.md +8 -0
- package/docs/releases/1.15.0.md +15 -0
- package/docs/releases/1.16.0.md +15 -0
- package/docs/releases/1.16.1.md +12 -0
- package/docs/releases/1.16.2.md +12 -0
- package/docs/releases/2.0.0.md +19 -0
- package/docs/releases/2.1.0.md +8 -0
- package/docs/releases/2.2.0.md +8 -0
- package/docs/releases/2.3.0.md +8 -0
- package/docs/releases/2.4.0.md +8 -0
- package/docs/releases/2.5.0.md +8 -0
- package/docs/releases/2.8.0.md +6 -0
- package/docs/releases/2.8.3.md +20 -0
- package/docs/releases/2.8.4.md +35 -0
- package/docs/releases/README.md +14 -0
- package/lib/agent-runtime.d.ts +1 -0
- package/lib/agent-runtime.d.ts.map +1 -1
- package/lib/agent-runtime.js +23 -8
- package/lib/agent-runtime.js.map +1 -1
- package/lib/api/features/pendant-api.d.ts.map +1 -1
- package/lib/api/features/pendant-api.js +11 -2
- package/lib/api/features/pendant-api.js.map +1 -1
- package/lib/api/features/push-api.d.ts +4 -0
- package/lib/api/features/push-api.d.ts.map +1 -0
- package/lib/api/features/push-api.js +47 -0
- package/lib/api/features/push-api.js.map +1 -0
- package/lib/api.d.ts +3 -0
- package/lib/api.d.ts.map +1 -1
- package/lib/api.js +18 -1
- package/lib/api.js.map +1 -1
- package/lib/autonomy.d.ts.map +1 -1
- package/lib/autonomy.js +8 -5
- package/lib/autonomy.js.map +1 -1
- package/lib/client-api.d.ts +11 -0
- package/lib/client-api.d.ts.map +1 -1
- package/lib/client-api.js.map +1 -1
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +2573 -1855
- package/lib/client.js.map +4 -4
- package/lib/client.pendant.js +4157 -0
- package/lib/collaboration/composition.d.ts.map +1 -1
- package/lib/collaboration/composition.js +1 -0
- package/lib/collaboration/composition.js.map +1 -1
- package/lib/collaboration/ssh-task-access.d.ts +33 -0
- package/lib/collaboration/ssh-task-access.d.ts.map +1 -0
- package/lib/collaboration/ssh-task-access.js +26 -0
- package/lib/collaboration/ssh-task-access.js.map +1 -0
- package/lib/companions/removal.d.ts.map +1 -1
- package/lib/companions/removal.js +4 -0
- package/lib/companions/removal.js.map +1 -1
- package/lib/concern-domain.d.ts +5 -0
- package/lib/concern-domain.d.ts.map +1 -1
- package/lib/concern-domain.js.map +1 -1
- package/lib/concern-execution-notes.d.ts +2 -0
- package/lib/concern-execution-notes.d.ts.map +1 -1
- package/lib/concern-execution-notes.js +9 -2
- package/lib/concern-execution-notes.js.map +1 -1
- package/lib/concern-execution-receipt.d.ts.map +1 -1
- package/lib/concern-execution-receipt.js +3 -2
- package/lib/concern-execution-receipt.js.map +1 -1
- package/lib/concern-execution.d.ts +3 -1
- package/lib/concern-execution.d.ts.map +1 -1
- package/lib/concern-execution.js +32 -5
- package/lib/concern-execution.js.map +1 -1
- package/lib/concern-knowledge-source.d.ts +23 -0
- package/lib/concern-knowledge-source.d.ts.map +1 -0
- package/lib/concern-knowledge-source.js +30 -0
- package/lib/concern-knowledge-source.js.map +1 -0
- package/lib/concern-note-source.d.ts +2 -1
- package/lib/concern-note-source.d.ts.map +1 -1
- package/lib/concern-note-source.js +6 -2
- package/lib/concern-note-source.js.map +1 -1
- package/lib/concern-store.d.ts +1 -0
- package/lib/concern-store.d.ts.map +1 -1
- package/lib/concern-store.js +29 -2
- package/lib/concern-store.js.map +1 -1
- package/lib/domain.d.ts +2 -0
- package/lib/domain.d.ts.map +1 -1
- package/lib/domain.js.map +1 -1
- package/lib/heartbeat.d.ts.map +1 -1
- package/lib/heartbeat.js +2 -1
- package/lib/heartbeat.js.map +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +18 -1
- package/lib/index.js.map +1 -1
- package/lib/notifications/bark-adapter.d.ts +9 -0
- package/lib/notifications/bark-adapter.d.ts.map +1 -0
- package/lib/notifications/bark-adapter.js +69 -0
- package/lib/notifications/bark-adapter.js.map +1 -0
- package/lib/notifications/push-config.d.ts +10 -0
- package/lib/notifications/push-config.d.ts.map +1 -0
- package/lib/notifications/push-config.js +79 -0
- package/lib/notifications/push-config.js.map +1 -0
- package/lib/notifications/push-credentials.d.ts +9 -0
- package/lib/notifications/push-credentials.d.ts.map +1 -0
- package/lib/notifications/push-credentials.js +16 -0
- package/lib/notifications/push-credentials.js.map +1 -0
- package/lib/notifications/push-domain.d.ts +66 -0
- package/lib/notifications/push-domain.d.ts.map +1 -0
- package/lib/notifications/push-domain.js +6 -0
- package/lib/notifications/push-domain.js.map +1 -0
- package/lib/notifications/push-observer.d.ts +19 -0
- package/lib/notifications/push-observer.d.ts.map +1 -0
- package/lib/notifications/push-observer.js +96 -0
- package/lib/notifications/push-observer.js.map +1 -0
- package/lib/notifications/push-service.d.ts +33 -0
- package/lib/notifications/push-service.d.ts.map +1 -0
- package/lib/notifications/push-service.js +228 -0
- package/lib/notifications/push-service.js.map +1 -0
- package/lib/notifications/push-state.d.ts +3 -0
- package/lib/notifications/push-state.d.ts.map +1 -0
- package/lib/notifications/push-state.js +23 -0
- package/lib/notifications/push-state.js.map +1 -0
- package/lib/observation-budget.d.ts +3 -2
- package/lib/observation-budget.d.ts.map +1 -1
- package/lib/observation-budget.js +5 -3
- package/lib/observation-budget.js.map +1 -1
- package/lib/observation-executor.d.ts.map +1 -1
- package/lib/observation-executor.js +6 -0
- package/lib/observation-executor.js.map +1 -1
- package/lib/observation-loop.d.ts +3 -0
- package/lib/observation-loop.d.ts.map +1 -1
- package/lib/observation-loop.js +154 -18
- package/lib/observation-loop.js.map +1 -1
- package/lib/observation-model-retry.d.ts +20 -0
- package/lib/observation-model-retry.d.ts.map +1 -0
- package/lib/observation-model-retry.js +48 -0
- package/lib/observation-model-retry.js.map +1 -0
- package/lib/observation-progress.d.ts +19 -0
- package/lib/observation-progress.d.ts.map +1 -0
- package/lib/observation-progress.js +77 -0
- package/lib/observation-progress.js.map +1 -0
- package/lib/observation-workflow.d.ts +40 -0
- package/lib/observation-workflow.d.ts.map +1 -0
- package/lib/observation-workflow.js +154 -0
- package/lib/observation-workflow.js.map +1 -0
- package/lib/pendant/badge-art.d.ts +9 -0
- package/lib/pendant/badge-art.d.ts.map +1 -0
- package/lib/pendant/badge-art.js +68 -0
- package/lib/pendant/badge-art.js.map +1 -0
- package/lib/pendant/card-image.d.ts.map +1 -1
- package/lib/pendant/card-image.js +11 -9
- package/lib/pendant/card-image.js.map +1 -1
- package/lib/pendant/renderer-loader.d.ts +9 -0
- package/lib/pendant/renderer-loader.d.ts.map +1 -0
- package/lib/pendant/renderer-loader.js +12 -0
- package/lib/pendant/renderer-loader.js.map +1 -0
- package/lib/pendant/renderer.d.ts +2 -6
- package/lib/pendant/renderer.d.ts.map +1 -1
- package/lib/pendant/renderer.js +1 -67
- package/lib/pendant/renderer.js.map +1 -1
- package/lib/pendant/static-card.d.ts +20 -0
- package/lib/pendant/static-card.d.ts.map +1 -0
- package/lib/pendant/static-card.js +55 -0
- package/lib/pendant/static-card.js.map +1 -0
- package/lib/pendant/widget.d.ts.map +1 -1
- package/lib/pendant/widget.js +9 -5
- package/lib/pendant/widget.js.map +1 -1
- package/lib/pendant-renderer.js +14 -14
- package/lib/recording-snapshot.d.ts.map +1 -1
- package/lib/recording-snapshot.js +12 -2
- package/lib/recording-snapshot.js.map +1 -1
- package/lib/storage/migrate-layout.d.ts.map +1 -1
- package/lib/storage/migrate-layout.js +2 -0
- package/lib/storage/migrate-layout.js.map +1 -1
- package/lib/storage/split-state.js +2 -2
- package/lib/storage/split-state.js.map +1 -1
- package/lib/store.d.ts.map +1 -1
- package/lib/store.js +2 -0
- package/lib/store.js.map +1 -1
- package/lib/ui/capability-editor.d.ts.map +1 -1
- package/lib/ui/capability-editor.js +3 -5
- package/lib/ui/capability-editor.js.map +1 -1
- package/lib/ui/channels-panel.d.ts.map +1 -1
- package/lib/ui/channels-panel.js +7 -1
- package/lib/ui/channels-panel.js.map +1 -1
- package/lib/ui/memory/concern-board.d.ts.map +1 -1
- package/lib/ui/memory/concern-board.js +3 -1
- package/lib/ui/memory/concern-board.js.map +1 -1
- package/lib/ui/memory/concern-execution-status.d.ts +8 -0
- package/lib/ui/memory/concern-execution-status.d.ts.map +1 -0
- package/lib/ui/memory/concern-execution-status.js +31 -0
- package/lib/ui/memory/concern-execution-status.js.map +1 -0
- package/lib/ui/push-channels.d.ts +11 -0
- package/lib/ui/push-channels.d.ts.map +1 -0
- package/lib/ui/push-channels.js +28 -0
- package/lib/ui/push-channels.js.map +1 -0
- package/lib/ui/push-draft.d.ts +30 -0
- package/lib/ui/push-draft.d.ts.map +1 -0
- package/lib/ui/push-draft.js +13 -0
- package/lib/ui/push-draft.js.map +1 -0
- package/lib/ui/push-editor.d.ts +10 -0
- package/lib/ui/push-editor.d.ts.map +1 -0
- package/lib/ui/push-editor.js +99 -0
- package/lib/ui/push-editor.js.map +1 -0
- package/lib/ui/runtime-settings.d.ts +18 -0
- package/lib/ui/runtime-settings.d.ts.map +1 -0
- package/lib/ui/runtime-settings.js +25 -0
- package/lib/ui/runtime-settings.js.map +1 -0
- package/lib/ui/workspace-components.d.ts +7 -1
- package/lib/ui/workspace-components.d.ts.map +1 -1
- package/lib/ui/workspace-components.js +8 -4
- package/lib/ui/workspace-components.js.map +1 -1
- 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":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAIxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAA;AAC/H,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AAIpE,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AAC/F,MAAM,UAAU,qBAAqB,CAAC,IAAkB,EAAE,QAAsB;IAC9E,MAAM,MAAM,GAAgB,EAAE,CAAA;IAC9B,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC/D,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC;YAAE,SAAQ;QACzE,MAAM,GAAG,GAAG,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAA;QAC9D,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACvG,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,eAAe,IAAI,CAAC,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,gBAAgB;gBACpG,KAAK,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAA;QACnJ,CAAC;aAAM,IAAI,IAAI,CAAC,WAAW,EAAE,OAAO,IAAI,GAAG,EAAE,WAAW,EAAE,GAAG,KAAK,IAAI,CAAC,WAAW,CAAC,GAAG;eACjF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,EAAE,CAAC;YACjF,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,uBAAuB,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,gBAAgB;gBAC5G,KAAK,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAA;QACrJ,CAAC;IACH,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,CAAA;QAC/B,IAAI,CAAC,IAAI,EAAE,UAAU,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,WAAW,EAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,KAAK,IAAI,CAAC,UAAU,CAAC,GAAG;YAAE,SAAQ;QACxM,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,SAAS,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9E,KAAK,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,IAAI,MAAM,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE;YAClG,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAA;IACvH,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACrC,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,WAAW,EAAC,QAAQ,EAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,EAAE,MAAM,KAAK,GAAG,CAAC,MAAM;YAAE,SAAQ;QAC7K,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC7D,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,WAAW;YAAE,SAAQ;QAC/D,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,YAAY,GAAG,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,CAAC,gBAAgB,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,IAAI,MAAM,KAAK,CAAC,KAAK,EAAE;YAC7I,IAAI,EAAE,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,KAAK,IAAI,gBAAgB,EAAE,SAAS,EAAE,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAA;IACxK,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,OAAO,YAAY;IAIM;IAAsC;IAAoC;IAHtF,IAAI,CAAY;IACzB,MAAM,GAAG,KAAK,CAAA;IACL,OAAO,GAAG,IAAI,GAAG,EAAiB,CAAA;IACnD,YAA6B,KAAmB,EAAmB,IAAiB,EAAmB,MAAkB;QAA5F,UAAK,GAAL,KAAK,CAAc;QAAmB,SAAI,GAAJ,IAAI,CAAa;QAAmB,WAAM,GAAN,MAAM,CAAY;QACvH,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;YACxC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;gBAAE,OAAM;YACpD,KAAK,MAAM,KAAK,IAAI,qBAAqB,CAAC,IAAI,EAAE,GAAG,CAAC;gBAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC1E,CAAC,EAAE,MAAM,CAAC,CAAA;IACZ,CAAC;IACO,MAAM,CAAC,KAAgB;QAC7B,IAAI,IAAI,CAAC,MAAM;YAAE,OAAM;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;QACjG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACxB,CAAC;IACD,cAAc,CAAC,OAAgB,EAAE,KAAmB;QAClD,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,WAAW;YAAE,OAAM;QAC9F,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAA;QACnC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,CAAC,CAAA;QAClE,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,EAAE,WAAW,CAAC,CAAA;QACzE,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,SAAS,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC;YAAE,OAAM;QACrG,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;QACvE,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QAChD,MAAM,YAAY,GAAG,sBAAsB,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;QAC9F,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,YAAY,CAAC,EAAE,CAAE,CAAC,YAAa,CAAA;YAC/E,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,SAAS,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE;gBAC5E,KAAK,EAAE,GAAG,SAAS,CAAC,IAAI,MAAM,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,YAAY,CAAC,KAAK,CAAC,IAAI;gBAC3G,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;YAAC,OAAM;QACnG,CAAC;QACD,6EAA6E;QAC7E,yEAAyE;QACzE,IAAI,IAAI,CAAC,IAAI,CAAC,4BAA4B,CAAC;YAAE,OAAM;QACnD,MAAM,KAAK,GAAG,sBAAsB,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,wBAAwB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAA;QACvF,IAAI,CAAC,KAAK,CAAC,IAAI;YAAE,OAAM;QACvB,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,SAAS,OAAO,CAAC,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,SAAS,CAAC,EAAE;YACnF,KAAK,EAAE,GAAG,SAAS,CAAC,IAAI,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAA;IACvG,CAAC;IACD,KAAK,CAAC,KAAK,KAAoB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA,CAAC,CAAC;CAClG"}
|
|
@@ -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 @@
|
|
|
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":"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"}
|
|
@@ -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\
|
|
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;;
|
|
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
|
-
|
|
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
|
|
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;
|
|
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;;;
|
|
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"}
|