吸收数字员工通知权限引导
This commit is contained in:
@@ -19,6 +19,9 @@ import type {
|
||||
PlanStepDispatchPolicyPullResult,
|
||||
ReadyStepDispatchResult,
|
||||
RiskApprovalPolicy,
|
||||
DesktopNotificationSettingsOpenResult,
|
||||
DesktopNotificationShowResult,
|
||||
DesktopNotificationStatus,
|
||||
NotificationPreferences,
|
||||
NotificationUpdatesPullResult,
|
||||
UserNotification,
|
||||
@@ -569,7 +572,7 @@ export function getEventLog(params: {
|
||||
// Notifications
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export { type ApprovalSubscriptionPreferences, type NotificationPreferences, type NotificationUpdatesPullResult, type PlanStepDispatchPolicy, type RiskApprovalPolicy, type UserNotification };
|
||||
export { type ApprovalSubscriptionPreferences, type DesktopNotificationSettingsOpenResult, type DesktopNotificationShowResult, type DesktopNotificationStatus, type NotificationPreferences, type NotificationUpdatesPullResult, type PlanStepDispatchPolicy, type RiskApprovalPolicy, type UserNotification };
|
||||
|
||||
export function getNotifications(
|
||||
status: string = 'unread',
|
||||
@@ -604,13 +607,24 @@ export function pullNotificationUpdates(): Promise<NotificationUpdatesPullResult
|
||||
});
|
||||
}
|
||||
|
||||
export function showDesktopNotification(input: Pick<UserNotification, 'notification_id' | 'title' | 'body' | 'level' | 'kind' | 'status'>): Promise<{ ok: boolean; shown?: boolean; reason?: string | null; error?: string | null }> {
|
||||
return apiFetch<{ ok: boolean; shown?: boolean; reason?: string | null; error?: string | null }>('/api/notifications/desktop', {
|
||||
export function showDesktopNotification(input: Pick<UserNotification, 'notification_id' | 'title' | 'body' | 'level' | 'kind' | 'status'>): Promise<DesktopNotificationShowResult> {
|
||||
return apiFetch<DesktopNotificationShowResult>('/api/notifications/desktop', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
}
|
||||
|
||||
export function getDesktopNotificationStatus(): Promise<DesktopNotificationStatus> {
|
||||
return apiFetch<DesktopNotificationStatus>('/api/notifications/desktop/status');
|
||||
}
|
||||
|
||||
export function openDesktopNotificationSettings(): Promise<DesktopNotificationSettingsOpenResult> {
|
||||
return apiFetch<DesktopNotificationSettingsOpenResult>('/api/notifications/desktop/settings/open', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
}
|
||||
|
||||
export function getApprovalSubscriptionPreferences(): Promise<ApprovalSubscriptionPreferences> {
|
||||
return apiFetch<ApprovalSubscriptionPreferences>('/api/approval/subscriptions');
|
||||
}
|
||||
|
||||
@@ -68,6 +68,8 @@ declare global {
|
||||
pullNotificationUpdates?: () => Promise<{ ok?: boolean; applied?: number; ignored?: number; skipped?: boolean; error?: string | null }>;
|
||||
submitNotificationAction?: (input: Record<string, unknown>) => Promise<{ ok?: boolean; error?: string | null }>;
|
||||
showDesktopNotification?: (input: Record<string, unknown>) => Promise<{ ok?: boolean; shown?: boolean; reason?: string | null; error?: string | null }>;
|
||||
getDesktopNotificationStatus?: () => Promise<{ supported?: boolean; platform?: string; can_open_settings?: boolean; reason?: string | null }>;
|
||||
openDesktopNotificationSettings?: () => Promise<{ success?: boolean; platform?: string; reason?: string | null; error?: string | null }>;
|
||||
evaluateRiskPolicy?: (input: QimingclawRiskPolicyInput) => Promise<QimingclawRiskPolicyResult>;
|
||||
pullRouteDecisionPolicy?: () => Promise<RouteDecisionPolicyPullResult>;
|
||||
evaluateRouteDecisionPolicy?: (input: QimingclawRouteDecisionPolicyInput) => Promise<QimingclawRouteDecisionPolicyResult>;
|
||||
@@ -1046,6 +1048,12 @@ export async function handleQimingclawDigitalApi<T>(
|
||||
if (method === 'POST' && pathname === '/api/notifications/desktop') {
|
||||
return await showBridgeDesktopNotification(parseOptionalJsonBody(options.body)) as T;
|
||||
}
|
||||
if (method === 'GET' && pathname === '/api/notifications/desktop/status') {
|
||||
return await readBridgeDesktopNotificationStatus() as T;
|
||||
}
|
||||
if (method === 'POST' && pathname === '/api/notifications/desktop/settings/open') {
|
||||
return await openBridgeDesktopNotificationSettings() as T;
|
||||
}
|
||||
if (method === 'GET' && pathname === '/api/notifications/unread-count') {
|
||||
const snapshot = await readQimingclawSnapshot();
|
||||
return { count: buildNotifications(snapshot, notificationAdapterState(snapshot)).filter((notification) => notification.status === 'unread').length } as T;
|
||||
@@ -1368,6 +1376,52 @@ async function showBridgeDesktopNotification(input: Record<string, unknown>): Pr
|
||||
}
|
||||
}
|
||||
|
||||
async function readBridgeDesktopNotificationStatus(): Promise<{ supported: boolean; platform: string; can_open_settings: boolean; reason?: string | null }> {
|
||||
const bridge = window.QimingClawBridge?.digital;
|
||||
if (!bridge?.getDesktopNotificationStatus) {
|
||||
return {
|
||||
supported: false,
|
||||
platform: 'unknown',
|
||||
can_open_settings: false,
|
||||
reason: 'qimingclaw_bridge_unavailable',
|
||||
};
|
||||
}
|
||||
try {
|
||||
const result = await bridge.getDesktopNotificationStatus();
|
||||
return {
|
||||
supported: result?.supported === true,
|
||||
platform: stringValue(result?.platform) || 'unknown',
|
||||
can_open_settings: result?.can_open_settings === true,
|
||||
reason: stringValue(result?.reason) || null,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
supported: false,
|
||||
platform: 'unknown',
|
||||
can_open_settings: false,
|
||||
reason: error instanceof Error ? error.message : String(error),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function openBridgeDesktopNotificationSettings(): Promise<{ success: boolean; platform?: string | null; reason?: string | null; error?: string | null }> {
|
||||
const bridge = window.QimingClawBridge?.digital;
|
||||
if (!bridge?.openDesktopNotificationSettings) {
|
||||
return { success: false, reason: 'qimingclaw_bridge_unavailable' };
|
||||
}
|
||||
try {
|
||||
const result = await bridge.openDesktopNotificationSettings();
|
||||
return {
|
||||
success: result?.success === true,
|
||||
platform: stringValue(result?.platform) || null,
|
||||
reason: stringValue(result?.reason) || null,
|
||||
error: stringValue(result?.error) || null,
|
||||
};
|
||||
} catch (error) {
|
||||
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
||||
}
|
||||
}
|
||||
|
||||
async function resolveApprovedRouteInterventions(snapshot: QimingclawSnapshot | null): Promise<void> {
|
||||
const timeline = await readRouteInterventions(120);
|
||||
const approved = timeline.interventions.filter((item) => (
|
||||
|
||||
Reference in New Issue
Block a user