/** * dsh-widgets — the DSH SCHEDULED-TASK fold (the 日历 / 倒计时 cards' second source). * * WHERE THIS DATA COMES FROM. DSH ships a durable reminder subsystem * (`@deepseek-ai/dsh-schedule`): the agent's `schedule_create/list/delete/update` * tools write it, and the official client reads it through the Remote face — * `ctx.remote.schedule.catalog()` plus the `schedule/changed` event. That face is * what this module talks to. There is no host ROUTE for it (which is why it is not * one of the `manifest.source` adapters: those poll a URL), and no projection * either (26 keys, none of them schedule) — the Remote face is the only door, and * it is already open to a third-party plugin because `ctx.get('remote')` resolves * to the same service instance the official packages use. * * WHY THE FOLD LIVES HERE. The wire type is a union of six rule shapes with their * own field names (`after_seconds`, `scheduledAt` as an RFC 3339 UTC STRING, …). * A card must not import the upstream package and must not re-derive any of it, so * the union is flattened ONCE, here, into `ScheduleEntryInfo` — the same discipline * as the model-selection / permission folds in `data/session-stats.ts`. * * THE DEGRADATION SWITCH. The schedule bundle is OPTIONAL in a DSH install (the * official release Web composition does not include it), so `remote.schedule` can * simply be absent. That is not an error and not an empty agenda: it is * `status: 'unavailable'`, and every card that reads this must then DEGRADE — the * calendar falls back to a plain month grid, the countdown prints `—` — instead of * claiming the user has no reminders. */ import type { ScheduleEntryInfo, ScheduleSnapshot } from '../lib/contract/types'; /** The two members of the client Remote face this plugin uses. */ export interface ScheduleRemoteFace { /** `@Remote('catalog')`: every retained task, across all sessions. */ catalog?: () => Promise; /** The Remote event subscription (`remote.$on`), not the cordis one. */ $on?: (eventName: string, listener: () => void) => (() => void) | void; } /** The `remote` service, as much of it as this plugin looks at. * * `schedule` is the scheduled-task face; `commands` is the slash-command seam a * one-click action card fires (`contextCompact` → `/compact`). Both are NAMESPACE * reads, which is the whole reason they need a context that declared the * dependency — see the resolution note in `client/index.ts`. */ export interface RemoteServiceLike { schedule?: ScheduleRemoteFace; commands?: { execute?: (agent: unknown, line: string) => Promise; }; } /** A missing or failed face. One shared frozen value: a card can compare by identity. */ export declare const SCHEDULE_UNAVAILABLE: ScheduleSnapshot; /** * Flatten the catalog payload into the cards' shape. * * Entries without a decodable `scheduledAt` are DROPPED rather than dated to `0`: * a task the cards cannot place in time would otherwise pin the calendar's "next" * at 1970, which is worse than not showing it. An unreadable payload folds to an * empty list (the face answered, it just had nothing usable), never to * `unavailable` — those two states mean different things to a card. */ export declare function normalizeScheduleCatalog(value: unknown): ScheduleEntryInfo[]; /** * Read the whole catalog once. * * Never throws and never rejects: the collector folds the answer straight into the * bridge, and a rejection there would take the collector's effect (and with it * every card's data) down. A missing face, a transport failure and a host error * branch all answer `unavailable`. */ export declare function readScheduleCatalog(face: ScheduleRemoteFace | undefined): Promise; /** Subscribe to `schedule/changed`; returns a disposer that is always callable. */ export declare function subscribeScheduleChanged(face: ScheduleRemoteFace | undefined, listener: () => void): () => void; /** * The next task that will actually fire: active, strictly in the future, soonest * first. `null` when there is none — which is a real answer ("no upcoming task"), * distinct from the unavailable face (see the module docs). */ export declare function nextActiveEntry(entries: readonly ScheduleEntryInfo[], now: number): ScheduleEntryInfo | null;