@khorsheed/dsh-reader 0.2.0

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 (58) hide show
  1. package/README.en.md +90 -0
  2. package/README.i18n.yaml +6 -0
  3. package/README.md +90 -0
  4. package/cordis.patch.yml +13 -0
  5. package/lib/client.js +15119 -0
  6. package/lib/index.js +3660 -0
  7. package/lib/invariant.js +38 -0
  8. package/lib/typert.host.d.ts +3 -0
  9. package/lib/typert.host.js +1738 -0
  10. package/lib/typert.remote-client.d.ts +82 -0
  11. package/lib/typert.remote-client.js +1115 -0
  12. package/lib/types/arxiv.d.ts +47 -0
  13. package/lib/types/arxiv.js +76 -0
  14. package/lib/types/client/ReaderPane.d.ts +71 -0
  15. package/lib/types/client/ReaderPane.js +3135 -0
  16. package/lib/types/client/contract.d.ts +254 -0
  17. package/lib/types/client/contract.js +1 -0
  18. package/lib/types/client/definition.d.ts +27 -0
  19. package/lib/types/client/definition.js +32 -0
  20. package/lib/types/client/extract-article.d.ts +102 -0
  21. package/lib/types/client/extract-article.js +1024 -0
  22. package/lib/types/client/icons.d.ts +27 -0
  23. package/lib/types/client/icons.js +11 -0
  24. package/lib/types/client/index.d.ts +34 -0
  25. package/lib/types/client/index.js +222 -0
  26. package/lib/types/client/locales.d.ts +391 -0
  27. package/lib/types/client/locales.js +382 -0
  28. package/lib/types/client/parse-rss.d.ts +69 -0
  29. package/lib/types/client/parse-rss.js +656 -0
  30. package/lib/types/client/quote.d.ts +89 -0
  31. package/lib/types/client/quote.js +119 -0
  32. package/lib/types/client/selectors.d.ts +167 -0
  33. package/lib/types/client/selectors.js +413 -0
  34. package/lib/types/client/session.d.ts +171 -0
  35. package/lib/types/client/session.js +223 -0
  36. package/lib/types/client/store.d.ts +181 -0
  37. package/lib/types/client/store.js +226 -0
  38. package/lib/types/client/translate.d.ts +379 -0
  39. package/lib/types/client/translate.js +873 -0
  40. package/lib/types/index.d.ts +48 -0
  41. package/lib/types/index.js +25 -0
  42. package/lib/types/invariant.d.ts +29 -0
  43. package/lib/types/invariant.js +38 -0
  44. package/lib/types/link-resolvers.d.ts +107 -0
  45. package/lib/types/link-resolvers.js +299 -0
  46. package/lib/types/remote.d.ts +224 -0
  47. package/lib/types/remote.js +275 -0
  48. package/lib/types/schedule.d.ts +78 -0
  49. package/lib/types/schedule.js +114 -0
  50. package/lib/types/service.d.ts +633 -0
  51. package/lib/types/service.js +1697 -0
  52. package/lib/types/store.d.ts +224 -0
  53. package/lib/types/store.js +916 -0
  54. package/lib/types/types.d.ts +710 -0
  55. package/lib/types/types.js +182 -0
  56. package/locale/en.json +6 -0
  57. package/locale/zh.json +6 -0
  58. package/package.json +128 -0
@@ -0,0 +1,224 @@
1
+ /**
2
+ * The reader Remote: the browser-facing wire face, and nothing else.
3
+ *
4
+ * Every method is a one-line delegation to {@link ReaderService}; the value it
5
+ * returns is the BARE domain value. The wire layer wraps that in the protocol's
6
+ * own result envelope, so a domain refusal is a value inside that envelope —
7
+ * never a second `{ ok }` object nested inside the first (which is how the
8
+ * discarded scaffold managed to answer `{ ok: true }` twice and throw it away).
9
+ *
10
+ * @module @khorsheed/dsh-reader/remote
11
+ */
12
+ import type { Context } from '@deepseek-ai/cordis';
13
+ import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
14
+ import type { ReaderAddFailure, ReaderAddOutcome, ReaderAddRefusal, ReaderAnnotationOutcome, ReaderBackfillCandidate, ReaderEntryBodyView, ReaderEntryFetchState, ReaderBody, ReaderCapabilities, ReaderEntryTranslationView, ReaderMutationOutcome, ReaderRecentEntry, ReaderRefreshResult, ReaderSentenceLearn, ReaderSourceSummary, ReaderStorageStats, ReaderTag } from './types.ts';
15
+ declare module '@deepseek-ai/cordis' {
16
+ interface Context {
17
+ readerRemote: ReaderRemoteService;
18
+ }
19
+ }
20
+ /** Reserved for future config-driven knobs; the service owns today's config. */
21
+ export interface ReaderRemoteConfig {
22
+ }
23
+ /** The wire namespace is `reader`: the browser calls `remote.reader.*`. */
24
+ export declare class ReaderRemoteService extends TypertRemoteService<ReaderRemoteConfig> {
25
+ static inject: string[];
26
+ constructor(ctx: Context, _config?: ReaderRemoteConfig);
27
+ /** The service core this face delegates to. */
28
+ private get core();
29
+ /** Capability handshake: what the browser may rely on in this composition. */
30
+ capabilities(): Promise<ReaderCapabilities>;
31
+ /** The configured sources, without payloads. */
32
+ listSources(): Promise<{
33
+ sources: ReaderSourceSummary[];
34
+ }>;
35
+ /** Add a source; the host decides whether the URL is a feed or an article. */
36
+ addSource(request: {
37
+ url: string;
38
+ label?: string;
39
+ }): Promise<ReaderAddOutcome | ReaderAddRefusal | ReaderAddFailure>;
40
+ /** Change a source's label/enabled flag, or the global refresh time. */
41
+ updateSource(request: {
42
+ id: string;
43
+ enabled?: boolean;
44
+ label?: string;
45
+ url?: string;
46
+ timeOfDay?: string;
47
+ }): Promise<ReaderMutationOutcome>;
48
+ /** Drop a source; its entries' translations go with it (their bodies stay for the budget). */
49
+ removeSource(request: {
50
+ id: string;
51
+ entryIds?: readonly string[];
52
+ }): Promise<ReaderMutationOutcome>;
53
+ /** Fetch the named sources (or every enabled one) now. */
54
+ refresh(request: {
55
+ ids?: string[];
56
+ }): Promise<{
57
+ results: ReaderRefreshResult[];
58
+ }>;
59
+ /** Hand back raw payloads for the browser to parse. */
60
+ getBodies(request: {
61
+ ids: string[];
62
+ }): Promise<{
63
+ bodies: ReaderBody[];
64
+ }>;
65
+ /** What the detail view should render for one entry, and whether a fetch is worth offering. */
66
+ getEntryBody(request: {
67
+ entryId: string;
68
+ url: string;
69
+ feedHtml?: string;
70
+ }): Promise<ReaderEntryBodyView>;
71
+ /** Fetch one entry's article (the network half; the browser extracts). */
72
+ fetchEntryBody(request: {
73
+ entryId: string;
74
+ url: string;
75
+ }): Promise<{
76
+ entryId: string;
77
+ url?: string;
78
+ raw?: string;
79
+ rawFile?: string;
80
+ truncated?: boolean;
81
+ error?: string;
82
+ }>;
83
+ /** Cache the markup the browser extracted for one entry. */
84
+ storeEntryBody(request: {
85
+ entryId: string;
86
+ url: string;
87
+ html: string;
88
+ truncated?: boolean;
89
+ scriptFigures?: number;
90
+ bodyHash?: string;
91
+ /** The article's own title, as extracted — the saved link's card upgrade. */
92
+ title?: string;
93
+ /** A short excerpt (abstract / first paragraph), with the title. */
94
+ excerpt?: string;
95
+ }): Promise<ReaderEntryBodyView>;
96
+ /** What the plugin holds per entry: a body, a stored raw payload, or a failure. */
97
+ entryFetchStates(request: {
98
+ entryIds: readonly string[];
99
+ }): Promise<{
100
+ states: Record<string, ReaderEntryFetchState>;
101
+ }>;
102
+ /** A stored raw payload, so the browser can extract it later. */
103
+ getRawBody(request: {
104
+ entryId: string;
105
+ }): Promise<{
106
+ entryId: string;
107
+ raw?: string;
108
+ url?: string;
109
+ truncated?: boolean;
110
+ error?: string;
111
+ }>;
112
+ /** Which entries still need their full text (the automatic backfill's work list). */
113
+ listBackfillCandidates(request: {
114
+ entries: readonly {
115
+ entryId: string;
116
+ url: string;
117
+ label: string;
118
+ hasBody: boolean;
119
+ }[];
120
+ limit?: number;
121
+ }): Promise<{
122
+ candidates: ReaderBackfillCandidate[];
123
+ }>;
124
+ /** One entry's exact-fit translation record (segment map resolved), when usable. */
125
+ getEntryTranslation(request: {
126
+ entryId: string;
127
+ }): Promise<{
128
+ translation?: ReaderEntryTranslationView;
129
+ }>;
130
+ /** Translations for exactly the asked sentence hashes of one pair — never the whole table. */
131
+ getSentenceTranslations(request: {
132
+ pair: string;
133
+ hashes: readonly string[];
134
+ }): Promise<{
135
+ translations: Record<string, string>;
136
+ }>;
137
+ /** Persist what one translation run learned (and refresh what it reused), in one batch. */
138
+ rememberSentences(request: {
139
+ pair: string;
140
+ entries: readonly ReaderSentenceLearn[];
141
+ recalled?: readonly ReaderSentenceLearn[];
142
+ entryId?: string;
143
+ bodyHash?: string;
144
+ }): Promise<{
145
+ stored: number;
146
+ }>;
147
+ /** Per-tier cache usage, aggregated on the host (the tables never cross). */
148
+ getStorageStats(): Promise<ReaderStorageStats>;
149
+ /** Forget every translation: the global memory and every entry map. */
150
+ clearTranslations(): Promise<{
151
+ clearedEntries: number;
152
+ clearedMemory: boolean;
153
+ }>;
154
+ /** The tag vocabulary, with how many entries carry each tag. */
155
+ listTags(): Promise<{
156
+ tags: ReaderTag[];
157
+ counts: Record<string, number>;
158
+ }>;
159
+ /** Create a tag, or return the existing one with the same name. */
160
+ createTag(request: {
161
+ name: string;
162
+ }): Promise<ReaderTag | ReaderAnnotationOutcome>;
163
+ /** Rename a tag without touching the entries that carry it. */
164
+ renameTag(request: {
165
+ id: string;
166
+ name: string;
167
+ }): Promise<ReaderAnnotationOutcome>;
168
+ /** Delete a tag and remove it from every entry. */
169
+ deleteTag(request: {
170
+ id: string;
171
+ }): Promise<ReaderAnnotationOutcome>;
172
+ /** Add or remove one tag on one entry. */
173
+ tagEntry(request: {
174
+ entryId: string;
175
+ tagId: string;
176
+ on: boolean;
177
+ }): Promise<ReaderAnnotationOutcome>;
178
+ /** The tags on one entry. */
179
+ entryTags(request: {
180
+ entryId: string;
181
+ }): Promise<{
182
+ tags: ReaderTag[];
183
+ }>;
184
+ /** Read or set how long a fetched body is served (and the translation budget). */
185
+ getCachePolicy(): Promise<{
186
+ ttlHours: number;
187
+ maxEntries: number;
188
+ translationBudgetChars: number;
189
+ }>;
190
+ setCachePolicy(request: {
191
+ ttlHours: number;
192
+ maxEntries?: number;
193
+ translationBudgetChars?: number;
194
+ }): Promise<ReaderAnnotationOutcome>;
195
+ /** Drop tags nothing references any more. */
196
+ pruneTags(): Promise<{
197
+ removed: number;
198
+ }>;
199
+ /** Record that the reader opened one entry (the recent page's write half). */
200
+ recordRead(request: {
201
+ entryId: string;
202
+ sourceId: string;
203
+ title: string;
204
+ url?: string;
205
+ }): Promise<{
206
+ entries: number;
207
+ }>;
208
+ /** The entries the reader opened, newest first. */
209
+ listRecent(): Promise<{
210
+ entries: ReaderRecentEntry[];
211
+ }>;
212
+ /** Forget every recent entry. */
213
+ clearRecent(): Promise<{
214
+ removed: number;
215
+ }>;
216
+ /** Forward a ref block to the side-chat service when one is composed. */
217
+ quoteToSideChat(request: {
218
+ contextKey: string;
219
+ label: string;
220
+ text: string;
221
+ }): Promise<'ok' | 'unavailable'>;
222
+ }
223
+ export default ReaderRemoteService;
224
+ //# sourceMappingURL=remote.d.ts.map
@@ -0,0 +1,275 @@
1
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
2
+ var useValue = arguments.length > 2;
3
+ for (var i = 0; i < initializers.length; i++) {
4
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
5
+ }
6
+ return useValue ? value : void 0;
7
+ };
8
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
+ var _, done = false;
14
+ for (var i = decorators.length - 1; i >= 0; i--) {
15
+ var context = {};
16
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
+ if (kind === "accessor") {
21
+ if (result === void 0) continue;
22
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
+ if (_ = accept(result.get)) descriptor.get = _;
24
+ if (_ = accept(result.set)) descriptor.set = _;
25
+ if (_ = accept(result.init)) initializers.unshift(_);
26
+ }
27
+ else if (_ = accept(result)) {
28
+ if (kind === "field") initializers.unshift(_);
29
+ else descriptor[key] = _;
30
+ }
31
+ }
32
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
+ done = true;
34
+ };
35
+ import { Remote, TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
36
+ /** The wire namespace is `reader`: the browser calls `remote.reader.*`. */
37
+ let ReaderRemoteService = (() => {
38
+ let _classSuper = TypertRemoteService;
39
+ let _instanceExtraInitializers = [];
40
+ let _capabilities_decorators;
41
+ let _listSources_decorators;
42
+ let _addSource_decorators;
43
+ let _updateSource_decorators;
44
+ let _removeSource_decorators;
45
+ let _refresh_decorators;
46
+ let _getBodies_decorators;
47
+ let _getEntryBody_decorators;
48
+ let _fetchEntryBody_decorators;
49
+ let _storeEntryBody_decorators;
50
+ let _entryFetchStates_decorators;
51
+ let _getRawBody_decorators;
52
+ let _listBackfillCandidates_decorators;
53
+ let _getEntryTranslation_decorators;
54
+ let _getSentenceTranslations_decorators;
55
+ let _rememberSentences_decorators;
56
+ let _getStorageStats_decorators;
57
+ let _clearTranslations_decorators;
58
+ let _listTags_decorators;
59
+ let _createTag_decorators;
60
+ let _renameTag_decorators;
61
+ let _deleteTag_decorators;
62
+ let _tagEntry_decorators;
63
+ let _entryTags_decorators;
64
+ let _getCachePolicy_decorators;
65
+ let _setCachePolicy_decorators;
66
+ let _pruneTags_decorators;
67
+ let _recordRead_decorators;
68
+ let _listRecent_decorators;
69
+ let _clearRecent_decorators;
70
+ let _quoteToSideChat_decorators;
71
+ return class ReaderRemoteService extends _classSuper {
72
+ static {
73
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
74
+ _capabilities_decorators = [Remote('capabilities')];
75
+ _listSources_decorators = [Remote('listSources')];
76
+ _addSource_decorators = [Remote('addSource')];
77
+ _updateSource_decorators = [Remote('updateSource')];
78
+ _removeSource_decorators = [Remote('removeSource')];
79
+ _refresh_decorators = [Remote('refresh')];
80
+ _getBodies_decorators = [Remote('getBodies')];
81
+ _getEntryBody_decorators = [Remote('getEntryBody')];
82
+ _fetchEntryBody_decorators = [Remote('fetchEntryBody')];
83
+ _storeEntryBody_decorators = [Remote('storeEntryBody')];
84
+ _entryFetchStates_decorators = [Remote('entryFetchStates')];
85
+ _getRawBody_decorators = [Remote('getRawBody')];
86
+ _listBackfillCandidates_decorators = [Remote('listBackfillCandidates')];
87
+ _getEntryTranslation_decorators = [Remote('getEntryTranslation')];
88
+ _getSentenceTranslations_decorators = [Remote('getSentenceTranslations')];
89
+ _rememberSentences_decorators = [Remote('rememberSentences')];
90
+ _getStorageStats_decorators = [Remote('getStorageStats')];
91
+ _clearTranslations_decorators = [Remote('clearTranslations')];
92
+ _listTags_decorators = [Remote('listTags')];
93
+ _createTag_decorators = [Remote('createTag')];
94
+ _renameTag_decorators = [Remote('renameTag')];
95
+ _deleteTag_decorators = [Remote('deleteTag')];
96
+ _tagEntry_decorators = [Remote('tagEntry')];
97
+ _entryTags_decorators = [Remote('entryTags')];
98
+ _getCachePolicy_decorators = [Remote('getCachePolicy')];
99
+ _setCachePolicy_decorators = [Remote('setCachePolicy')];
100
+ _pruneTags_decorators = [Remote('pruneTags')];
101
+ _recordRead_decorators = [Remote('recordRead')];
102
+ _listRecent_decorators = [Remote('listRecent')];
103
+ _clearRecent_decorators = [Remote('clearRecent')];
104
+ _quoteToSideChat_decorators = [Remote('quoteToSideChat')];
105
+ __esDecorate(this, null, _capabilities_decorators, { kind: "method", name: "capabilities", static: false, private: false, access: { has: obj => "capabilities" in obj, get: obj => obj.capabilities }, metadata: _metadata }, null, _instanceExtraInitializers);
106
+ __esDecorate(this, null, _listSources_decorators, { kind: "method", name: "listSources", static: false, private: false, access: { has: obj => "listSources" in obj, get: obj => obj.listSources }, metadata: _metadata }, null, _instanceExtraInitializers);
107
+ __esDecorate(this, null, _addSource_decorators, { kind: "method", name: "addSource", static: false, private: false, access: { has: obj => "addSource" in obj, get: obj => obj.addSource }, metadata: _metadata }, null, _instanceExtraInitializers);
108
+ __esDecorate(this, null, _updateSource_decorators, { kind: "method", name: "updateSource", static: false, private: false, access: { has: obj => "updateSource" in obj, get: obj => obj.updateSource }, metadata: _metadata }, null, _instanceExtraInitializers);
109
+ __esDecorate(this, null, _removeSource_decorators, { kind: "method", name: "removeSource", static: false, private: false, access: { has: obj => "removeSource" in obj, get: obj => obj.removeSource }, metadata: _metadata }, null, _instanceExtraInitializers);
110
+ __esDecorate(this, null, _refresh_decorators, { kind: "method", name: "refresh", static: false, private: false, access: { has: obj => "refresh" in obj, get: obj => obj.refresh }, metadata: _metadata }, null, _instanceExtraInitializers);
111
+ __esDecorate(this, null, _getBodies_decorators, { kind: "method", name: "getBodies", static: false, private: false, access: { has: obj => "getBodies" in obj, get: obj => obj.getBodies }, metadata: _metadata }, null, _instanceExtraInitializers);
112
+ __esDecorate(this, null, _getEntryBody_decorators, { kind: "method", name: "getEntryBody", static: false, private: false, access: { has: obj => "getEntryBody" in obj, get: obj => obj.getEntryBody }, metadata: _metadata }, null, _instanceExtraInitializers);
113
+ __esDecorate(this, null, _fetchEntryBody_decorators, { kind: "method", name: "fetchEntryBody", static: false, private: false, access: { has: obj => "fetchEntryBody" in obj, get: obj => obj.fetchEntryBody }, metadata: _metadata }, null, _instanceExtraInitializers);
114
+ __esDecorate(this, null, _storeEntryBody_decorators, { kind: "method", name: "storeEntryBody", static: false, private: false, access: { has: obj => "storeEntryBody" in obj, get: obj => obj.storeEntryBody }, metadata: _metadata }, null, _instanceExtraInitializers);
115
+ __esDecorate(this, null, _entryFetchStates_decorators, { kind: "method", name: "entryFetchStates", static: false, private: false, access: { has: obj => "entryFetchStates" in obj, get: obj => obj.entryFetchStates }, metadata: _metadata }, null, _instanceExtraInitializers);
116
+ __esDecorate(this, null, _getRawBody_decorators, { kind: "method", name: "getRawBody", static: false, private: false, access: { has: obj => "getRawBody" in obj, get: obj => obj.getRawBody }, metadata: _metadata }, null, _instanceExtraInitializers);
117
+ __esDecorate(this, null, _listBackfillCandidates_decorators, { kind: "method", name: "listBackfillCandidates", static: false, private: false, access: { has: obj => "listBackfillCandidates" in obj, get: obj => obj.listBackfillCandidates }, metadata: _metadata }, null, _instanceExtraInitializers);
118
+ __esDecorate(this, null, _getEntryTranslation_decorators, { kind: "method", name: "getEntryTranslation", static: false, private: false, access: { has: obj => "getEntryTranslation" in obj, get: obj => obj.getEntryTranslation }, metadata: _metadata }, null, _instanceExtraInitializers);
119
+ __esDecorate(this, null, _getSentenceTranslations_decorators, { kind: "method", name: "getSentenceTranslations", static: false, private: false, access: { has: obj => "getSentenceTranslations" in obj, get: obj => obj.getSentenceTranslations }, metadata: _metadata }, null, _instanceExtraInitializers);
120
+ __esDecorate(this, null, _rememberSentences_decorators, { kind: "method", name: "rememberSentences", static: false, private: false, access: { has: obj => "rememberSentences" in obj, get: obj => obj.rememberSentences }, metadata: _metadata }, null, _instanceExtraInitializers);
121
+ __esDecorate(this, null, _getStorageStats_decorators, { kind: "method", name: "getStorageStats", static: false, private: false, access: { has: obj => "getStorageStats" in obj, get: obj => obj.getStorageStats }, metadata: _metadata }, null, _instanceExtraInitializers);
122
+ __esDecorate(this, null, _clearTranslations_decorators, { kind: "method", name: "clearTranslations", static: false, private: false, access: { has: obj => "clearTranslations" in obj, get: obj => obj.clearTranslations }, metadata: _metadata }, null, _instanceExtraInitializers);
123
+ __esDecorate(this, null, _listTags_decorators, { kind: "method", name: "listTags", static: false, private: false, access: { has: obj => "listTags" in obj, get: obj => obj.listTags }, metadata: _metadata }, null, _instanceExtraInitializers);
124
+ __esDecorate(this, null, _createTag_decorators, { kind: "method", name: "createTag", static: false, private: false, access: { has: obj => "createTag" in obj, get: obj => obj.createTag }, metadata: _metadata }, null, _instanceExtraInitializers);
125
+ __esDecorate(this, null, _renameTag_decorators, { kind: "method", name: "renameTag", static: false, private: false, access: { has: obj => "renameTag" in obj, get: obj => obj.renameTag }, metadata: _metadata }, null, _instanceExtraInitializers);
126
+ __esDecorate(this, null, _deleteTag_decorators, { kind: "method", name: "deleteTag", static: false, private: false, access: { has: obj => "deleteTag" in obj, get: obj => obj.deleteTag }, metadata: _metadata }, null, _instanceExtraInitializers);
127
+ __esDecorate(this, null, _tagEntry_decorators, { kind: "method", name: "tagEntry", static: false, private: false, access: { has: obj => "tagEntry" in obj, get: obj => obj.tagEntry }, metadata: _metadata }, null, _instanceExtraInitializers);
128
+ __esDecorate(this, null, _entryTags_decorators, { kind: "method", name: "entryTags", static: false, private: false, access: { has: obj => "entryTags" in obj, get: obj => obj.entryTags }, metadata: _metadata }, null, _instanceExtraInitializers);
129
+ __esDecorate(this, null, _getCachePolicy_decorators, { kind: "method", name: "getCachePolicy", static: false, private: false, access: { has: obj => "getCachePolicy" in obj, get: obj => obj.getCachePolicy }, metadata: _metadata }, null, _instanceExtraInitializers);
130
+ __esDecorate(this, null, _setCachePolicy_decorators, { kind: "method", name: "setCachePolicy", static: false, private: false, access: { has: obj => "setCachePolicy" in obj, get: obj => obj.setCachePolicy }, metadata: _metadata }, null, _instanceExtraInitializers);
131
+ __esDecorate(this, null, _pruneTags_decorators, { kind: "method", name: "pruneTags", static: false, private: false, access: { has: obj => "pruneTags" in obj, get: obj => obj.pruneTags }, metadata: _metadata }, null, _instanceExtraInitializers);
132
+ __esDecorate(this, null, _recordRead_decorators, { kind: "method", name: "recordRead", static: false, private: false, access: { has: obj => "recordRead" in obj, get: obj => obj.recordRead }, metadata: _metadata }, null, _instanceExtraInitializers);
133
+ __esDecorate(this, null, _listRecent_decorators, { kind: "method", name: "listRecent", static: false, private: false, access: { has: obj => "listRecent" in obj, get: obj => obj.listRecent }, metadata: _metadata }, null, _instanceExtraInitializers);
134
+ __esDecorate(this, null, _clearRecent_decorators, { kind: "method", name: "clearRecent", static: false, private: false, access: { has: obj => "clearRecent" in obj, get: obj => obj.clearRecent }, metadata: _metadata }, null, _instanceExtraInitializers);
135
+ __esDecorate(this, null, _quoteToSideChat_decorators, { kind: "method", name: "quoteToSideChat", static: false, private: false, access: { has: obj => "quoteToSideChat" in obj, get: obj => obj.quoteToSideChat }, metadata: _metadata }, null, _instanceExtraInitializers);
136
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
137
+ }
138
+ static inject = ['reader'];
139
+ constructor(ctx, _config = {}) {
140
+ super(ctx, 'readerRemote', { namespace: 'reader' });
141
+ __runInitializers(this, _instanceExtraInitializers);
142
+ }
143
+ /** The service core this face delegates to. */
144
+ get core() {
145
+ return this.ctx.reader;
146
+ }
147
+ /** Capability handshake: what the browser may rely on in this composition. */
148
+ capabilities() {
149
+ return this.core.capabilities();
150
+ }
151
+ /** The configured sources, without payloads. */
152
+ async listSources() {
153
+ return this.core.listSources();
154
+ }
155
+ /** Add a source; the host decides whether the URL is a feed or an article. */
156
+ addSource(request) {
157
+ return this.core.addSource(request);
158
+ }
159
+ /** Change a source's label/enabled flag, or the global refresh time. */
160
+ updateSource(request) {
161
+ return this.core.updateSource(request);
162
+ }
163
+ /** Drop a source; its entries' translations go with it (their bodies stay for the budget). */
164
+ removeSource(request) {
165
+ return this.core.removeSource(request);
166
+ }
167
+ /** Fetch the named sources (or every enabled one) now. */
168
+ async refresh(request) {
169
+ return this.core.refresh(request);
170
+ }
171
+ /** Hand back raw payloads for the browser to parse. */
172
+ async getBodies(request) {
173
+ return this.core.getBodies(request);
174
+ }
175
+ /* ------------------------------------------- entry bodies and reader tags */
176
+ /** What the detail view should render for one entry, and whether a fetch is worth offering. */
177
+ getEntryBody(request) {
178
+ return this.core.getEntryBody(request);
179
+ }
180
+ /** Fetch one entry's article (the network half; the browser extracts). */
181
+ fetchEntryBody(request) {
182
+ return this.core.fetchEntryBody(request);
183
+ }
184
+ /** Cache the markup the browser extracted for one entry. */
185
+ storeEntryBody(request) {
186
+ return this.core.storeEntryBody(request);
187
+ }
188
+ /** What the plugin holds per entry: a body, a stored raw payload, or a failure. */
189
+ entryFetchStates(request) {
190
+ return this.core.entryFetchStates(request);
191
+ }
192
+ /** A stored raw payload, so the browser can extract it later. */
193
+ getRawBody(request) {
194
+ return this.core.getRawBody(request);
195
+ }
196
+ /** Which entries still need their full text (the automatic backfill's work list). */
197
+ listBackfillCandidates(request) {
198
+ return this.core.listBackfillCandidates(request);
199
+ }
200
+ /* -------------------------------------------------- translation memory */
201
+ /** One entry's exact-fit translation record (segment map resolved), when usable. */
202
+ getEntryTranslation(request) {
203
+ return this.core.getEntryTranslation(request);
204
+ }
205
+ /** Translations for exactly the asked sentence hashes of one pair — never the whole table. */
206
+ getSentenceTranslations(request) {
207
+ return this.core.getSentenceTranslations(request);
208
+ }
209
+ /** Persist what one translation run learned (and refresh what it reused), in one batch. */
210
+ rememberSentences(request) {
211
+ return this.core.rememberSentences(request);
212
+ }
213
+ /** Per-tier cache usage, aggregated on the host (the tables never cross). */
214
+ getStorageStats() {
215
+ return this.core.getStorageStats();
216
+ }
217
+ /** Forget every translation: the global memory and every entry map. */
218
+ clearTranslations() {
219
+ return this.core.clearTranslations();
220
+ }
221
+ /** The tag vocabulary, with how many entries carry each tag. */
222
+ listTags() {
223
+ return this.core.listTags();
224
+ }
225
+ /** Create a tag, or return the existing one with the same name. */
226
+ createTag(request) {
227
+ return this.core.createTag(request);
228
+ }
229
+ /** Rename a tag without touching the entries that carry it. */
230
+ renameTag(request) {
231
+ return this.core.renameTag(request);
232
+ }
233
+ /** Delete a tag and remove it from every entry. */
234
+ deleteTag(request) {
235
+ return this.core.deleteTag(request);
236
+ }
237
+ /** Add or remove one tag on one entry. */
238
+ tagEntry(request) {
239
+ return this.core.tagEntry(request);
240
+ }
241
+ /** The tags on one entry. */
242
+ entryTags(request) {
243
+ return this.core.entryTags(request);
244
+ }
245
+ /** Read or set how long a fetched body is served (and the translation budget). */
246
+ getCachePolicy() {
247
+ return this.core.getCachePolicy();
248
+ }
249
+ setCachePolicy(request) {
250
+ return this.core.setCachePolicy(request);
251
+ }
252
+ /** Drop tags nothing references any more. */
253
+ pruneTags() {
254
+ return this.core.pruneTags();
255
+ }
256
+ /** Record that the reader opened one entry (the recent page's write half). */
257
+ recordRead(request) {
258
+ return this.core.recordRead(request);
259
+ }
260
+ /** The entries the reader opened, newest first. */
261
+ listRecent() {
262
+ return this.core.listRecent();
263
+ }
264
+ /** Forget every recent entry. */
265
+ clearRecent() {
266
+ return this.core.clearRecent();
267
+ }
268
+ /** Forward a ref block to the side-chat service when one is composed. */
269
+ quoteToSideChat(request) {
270
+ return this.core.quoteToSideChat(request);
271
+ }
272
+ };
273
+ })();
274
+ export { ReaderRemoteService };
275
+ export default ReaderRemoteService;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * The daily-refresh clock: pure date math, deliberately separated from the
3
+ * service that arms it.
4
+ *
5
+ * There is no host scheduler to hang a "refresh every morning" job on — the
6
+ * host's `ctx.timer` is fiber-scoped `timeout`/`interval`/`throttle`/`debounce`
7
+ * only, and `dsh-schedule` is agent-session reminders rather than a service a
8
+ * plugin may schedule against. So the plugin owns a `setTimeout` and the only
9
+ * interesting part is deciding *when* — which is what lives here, as functions
10
+ * that take a `now` and are therefore testable without a clock.
11
+ *
12
+ * @module @khorsheed/dsh-reader/schedule
13
+ */
14
+ /** Local time of day as `HH:MM`. */
15
+ export type TimeOfDay = string;
16
+ /** Milliseconds in one day. */
17
+ declare const DAY_MS: number;
18
+ /**
19
+ * Parse an `HH:MM` string into hours and minutes.
20
+ *
21
+ * A malformed value falls back to the caller's default rather than throwing: a
22
+ * hand-edited state file must not be able to break the refresh loop.
23
+ *
24
+ * @param value - the configured time of day.
25
+ * @param fallback - the value to use when `value` is unusable.
26
+ * @returns the parsed hour and minute.
27
+ */
28
+ export declare function parseTimeOfDay(value: string | undefined, fallback: TimeOfDay): {
29
+ hour: number;
30
+ minute: number;
31
+ };
32
+ /**
33
+ * The next wall-clock occurrence of `timeOfDay` strictly after `now`.
34
+ *
35
+ * Computed through the local-time constructor rather than by adding a fixed
36
+ * day length, so a DST shift moves the refresh to the same wall-clock time
37
+ * instead of drifting an hour.
38
+ *
39
+ * @param now - the reference instant.
40
+ * @param timeOfDay - the configured local time.
41
+ * @returns the next occurrence.
42
+ */
43
+ export declare function nextOccurrence(now: Date, timeOfDay: TimeOfDay): Date;
44
+ /**
45
+ * The most recent occurrence of `timeOfDay` at or before `now` — the deadline
46
+ * a catch-up refresh compares against.
47
+ *
48
+ * @param now - the reference instant.
49
+ * @param timeOfDay - the configured local time.
50
+ * @returns the most recent occurrence.
51
+ */
52
+ export declare function previousOccurrence(now: Date, timeOfDay: TimeOfDay): Date;
53
+ /** Delay to the next occurrence, clamped to Node's timer ceiling. */
54
+ export declare const MAX_TIMEOUT_MS = 2147483647;
55
+ /**
56
+ * Whether a boot should refresh immediately because the last run missed its
57
+ * slot — the thing that makes "daily refresh" true on a machine that was
58
+ * asleep or whose process restarted.
59
+ *
60
+ * @param lastRun - the last completed refresh, if any.
61
+ * @param now - the current instant.
62
+ * @param timeOfDay - the configured local time.
63
+ * @param enabled - whether the schedule is on at all.
64
+ * @returns true when a catch-up run is due.
65
+ */
66
+ export declare function isCatchUpDue(lastRun: Date | undefined, now: Date, timeOfDay: TimeOfDay, enabled: boolean): boolean;
67
+ /**
68
+ * The timer delay for the next occurrence, capped so a scheduler survives
69
+ * dates beyond the 32-bit millisecond limit.
70
+ *
71
+ * @param now - the reference instant.
72
+ * @param timeOfDay - the configured local time.
73
+ * @returns the delay in milliseconds.
74
+ */
75
+ export declare function delayUntilNext(now: Date, timeOfDay: TimeOfDay): number;
76
+ /** Exposed for tests that want to assert a day's worth of arithmetic. */
77
+ export { DAY_MS };
78
+ //# sourceMappingURL=schedule.d.ts.map