@omelhorsite/sdk 0.15.1 → 0.17.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.
- package/README.md +26 -3
- package/dist/index.js +385 -146
- package/dist/types/auth/tokens.d.ts +1 -1
- package/dist/types/client.d.ts +3 -0
- package/dist/types/resources/admin/llm.d.ts +9 -1
- package/dist/types/resources/admin/quotas.d.ts +14 -0
- package/dist/types/resources/content/blogs.d.ts +111 -31
- package/dist/types/resources/content/index.d.ts +4 -4
- package/dist/types/resources/content/news/feeds.d.ts +56 -0
- package/dist/types/resources/content/news/index.d.ts +36 -0
- package/dist/types/resources/content/news/items.d.ts +155 -0
- package/dist/types/resources/content/{intel → news}/scripts.d.ts +35 -35
- package/dist/types/resources/content/{intel → news}/sources.d.ts +62 -59
- package/dist/types/resources/content/notifications.d.ts +2 -2
- package/dist/types/resources/cron.d.ts +225 -0
- package/dist/types/resources/index.d.ts +1 -0
- package/dist/types/resources/llm.d.ts +71 -0
- package/dist/types/resources/quotas.d.ts +8 -5
- package/dist/types/resources/search.d.ts +36 -0
- package/package.json +1 -1
- package/dist/types/resources/content/intel/articles.d.ts +0 -230
- package/dist/types/resources/content/intel/config.d.ts +0 -135
- package/dist/types/resources/content/intel/index.d.ts +0 -53
- package/dist/types/resources/content/intel/items.d.ts +0 -91
- package/dist/types/resources/content/intel/reports.d.ts +0 -108
- package/dist/types/resources/content/intel/stats.d.ts +0 -105
- package/dist/types/resources/content/intel/types.d.ts +0 -86
|
@@ -93,7 +93,7 @@ export interface TokenStore {
|
|
|
93
93
|
* narrowest set the product actually uses: every extra scope makes the
|
|
94
94
|
* approval page scarier for no benefit.
|
|
95
95
|
*/
|
|
96
|
-
export declare const OMS_SCOPES: readonly ["openid", "profile", "email", "tools:read", "tools:write", "storage:read", "storage:write", "tickets:write"];
|
|
96
|
+
export declare const OMS_SCOPES: readonly ["openid", "profile", "email", "tools:read", "tools:write", "storage:read", "storage:write", "tickets:write", "llm", "blogs:read", "blogs:write", "news:read", "news:write", "cron:read", "cron:write"];
|
|
97
97
|
/** One of {@link OMS_SCOPES}. */
|
|
98
98
|
export type OmsScope = (typeof OMS_SCOPES)[number];
|
|
99
99
|
/** Refresh this long before the real expiry unless the host says otherwise. */
|
package/dist/types/client.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { PasskeysNamespace } from "./resources/auth/passkeys";
|
|
|
19
19
|
import { AuthSessionsNamespace } from "./resources/auth/sessions";
|
|
20
20
|
import { ChestsNamespace } from "./resources/chests";
|
|
21
21
|
import { ContentNamespace } from "./resources/content";
|
|
22
|
+
import { CronNamespace } from "./resources/cron";
|
|
22
23
|
import { DynamicQrsNamespace } from "./resources/dynamicQrs";
|
|
23
24
|
import { FormsNamespace } from "./resources/forms";
|
|
24
25
|
import { IpLookupNamespace } from "./resources/ipLookup";
|
|
@@ -183,6 +184,8 @@ export declare class Oms {
|
|
|
183
184
|
readonly search: SearchNamespace;
|
|
184
185
|
/** The language models the signed-in person may pick, and their own usage. */
|
|
185
186
|
readonly llm: LlmNamespace;
|
|
187
|
+
/** TypeScript scripts the server runs on a schedule as the signed-in person. */
|
|
188
|
+
readonly cron: CronNamespace;
|
|
186
189
|
/**
|
|
187
190
|
* The WebSocket connection: playback handoff, jams, notifications, job
|
|
188
191
|
* progress. Opens nothing until {@link RealtimeNamespace.connect} is called,
|
|
@@ -117,6 +117,12 @@ export interface LlmModel {
|
|
|
117
117
|
readonly enabled: boolean;
|
|
118
118
|
/** Whether signed-in people may pick it (see `oms.llm.models`). */
|
|
119
119
|
readonly visible_in_chat: boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Who may pick it by name: `0` everyone, `1` trusted accounts, `2`
|
|
122
|
+
* administrators. An account reaches the models at or below its own tier
|
|
123
|
+
* (`oms.admin.quotas.setLlmTier`).
|
|
124
|
+
*/
|
|
125
|
+
readonly tier: number;
|
|
120
126
|
readonly context_window: number | null;
|
|
121
127
|
readonly max_output_tokens: number | null;
|
|
122
128
|
readonly input_price_per_million: number | null;
|
|
@@ -134,6 +140,8 @@ export interface CreateLlmModelInput {
|
|
|
134
140
|
readonly name: string;
|
|
135
141
|
readonly enabled?: boolean;
|
|
136
142
|
readonly visibleInChat?: boolean;
|
|
143
|
+
/** `0` to `2`; see {@link LlmModel.tier}. */
|
|
144
|
+
readonly tier?: number;
|
|
137
145
|
readonly contextWindow?: number | null;
|
|
138
146
|
readonly maxOutputTokens?: number | null;
|
|
139
147
|
readonly inputPricePerMillion?: number | null;
|
|
@@ -145,7 +153,7 @@ export interface CreateLlmModelInput {
|
|
|
145
153
|
/** The provider and the `model_id` are fixed after creation. */
|
|
146
154
|
export type UpdateLlmModelInput = Partial<Omit<CreateLlmModelInput, "llmProviderId" | "modelId">>;
|
|
147
155
|
/** Filter columns of `GET /admin/llm_models`. */
|
|
148
|
-
export declare const ADMIN_LLM_MODEL_FILTER_COLUMNS: readonly ["llm_provider_id", "model_id", "name", "enabled", "visible_in_chat", "free"];
|
|
156
|
+
export declare const ADMIN_LLM_MODEL_FILTER_COLUMNS: readonly ["llm_provider_id", "model_id", "name", "enabled", "visible_in_chat", "tier", "free"];
|
|
149
157
|
export interface ListAdminLlmModelsParams extends ListParams<(typeof ADMIN_LLM_MODEL_FILTER_COLUMNS)[number]> {
|
|
150
158
|
}
|
|
151
159
|
/**
|
|
@@ -54,6 +54,11 @@ export interface AdminUserQuotaEntry {
|
|
|
54
54
|
export interface AdminUserQuotas {
|
|
55
55
|
readonly user_id: Id;
|
|
56
56
|
readonly handle: string;
|
|
57
|
+
/**
|
|
58
|
+
* Which language models the person may pick by name: every model whose
|
|
59
|
+
* `tier` is at or below this. `0` for a new account. See {@link AdminQuotasNamespace.setLlmTier}.
|
|
60
|
+
*/
|
|
61
|
+
readonly llm_tier: number;
|
|
57
62
|
/**
|
|
58
63
|
* **Every** resource in the catalogue, including the storage and music
|
|
59
64
|
* ceilings. Unlike the anonymous answer from `oms.quotas.list()`, nothing is
|
|
@@ -111,4 +116,13 @@ export declare class AdminQuotasNamespace extends Resource {
|
|
|
111
116
|
* @throws {OmsAuthError} 403 for a non-admin.
|
|
112
117
|
*/
|
|
113
118
|
update(user: Id | string, overrides: readonly AdminQuotaOverride[], options?: RequestOptions): Promise<AdminUserQuotas>;
|
|
119
|
+
/**
|
|
120
|
+
* `PUT /admin/users/:user/quotas` with `llm_tier` only - which language
|
|
121
|
+
* models the person may pick by name (`0` everyone's, `1` adds the trusted
|
|
122
|
+
* ones, `2` adds the administrators' ones). Quota overrides are untouched.
|
|
123
|
+
*
|
|
124
|
+
* @throws {OmsApiError} 400 for a tier outside `0..2`; 404 `"User not found"`.
|
|
125
|
+
* @throws {OmsAuthError} 403 for a non-admin.
|
|
126
|
+
*/
|
|
127
|
+
setLlmTier(user: Id | string, tier: number, options?: RequestOptions): Promise<AdminUserQuotas>;
|
|
114
128
|
}
|
|
@@ -13,7 +13,19 @@ export interface BlogAuthor {
|
|
|
13
13
|
readonly name: string;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* Who can read a blog.
|
|
17
|
+
*
|
|
18
|
+
* - `"public"`: listed on the discovery feed and open to everyone;
|
|
19
|
+
* - `"unlisted"`: open to anyone who has the link, never listed;
|
|
20
|
+
* - `"private"`: the owner, administrators and the invited members only.
|
|
21
|
+
* Anonymous readers get `401`, signed-in strangers `403` with
|
|
22
|
+
* `error: "private"`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const BLOG_VISIBILITIES: readonly ["public", "unlisted", "private"];
|
|
25
|
+
export type BlogVisibility = (typeof BLOG_VISIBILITIES)[number];
|
|
26
|
+
/**
|
|
27
|
+
* A blog. A person may own several; the oldest is their default one (the one
|
|
28
|
+
* `mine` answers and posts land in when no blog is named).
|
|
17
29
|
*
|
|
18
30
|
* Deliberately NOT a `BaseRecord`: the payload has `created_at` and NO
|
|
19
31
|
* `updated_at`. Do not reach for one.
|
|
@@ -23,15 +35,23 @@ export interface Blog {
|
|
|
23
35
|
/**
|
|
24
36
|
* URL-safe handle of the blog, and the ONLY way to address it on the read
|
|
25
37
|
* routes. Matches `/\A[a-z0-9][a-z0-9_-]*\z/`, 1-64 characters, unique
|
|
26
|
-
* across the whole table. Defaults to the owner's handle, lowercased
|
|
38
|
+
* across the whole table. Defaults to the owner's handle, lowercased, with
|
|
39
|
+
* a numeric suffix for each further blog created without a slug.
|
|
27
40
|
*/
|
|
28
41
|
readonly slug: string;
|
|
29
42
|
/** Display name. Defaults to `"<name>'s blog"`. Up to 80 characters. */
|
|
30
43
|
readonly name: string;
|
|
31
44
|
/** Up to 240 characters, or `null`. */
|
|
32
45
|
readonly description: string | null;
|
|
33
|
-
/** Who owns it.
|
|
46
|
+
/** Who owns it. */
|
|
34
47
|
readonly user: BlogAuthor;
|
|
48
|
+
readonly visibility: BlogVisibility | string;
|
|
49
|
+
/** Invited members (private blogs). Counted live. */
|
|
50
|
+
readonly members_count: number;
|
|
51
|
+
/** Whether the CALLING user owns it. Per-viewer, like `is_following`. */
|
|
52
|
+
readonly is_owner: boolean;
|
|
53
|
+
/** Whether the CALLING user is an invited member. Per-viewer. */
|
|
54
|
+
readonly is_member: boolean;
|
|
35
55
|
/**
|
|
36
56
|
* Subscribers with a `confirmed_at`, counted live on every render.
|
|
37
57
|
*
|
|
@@ -79,11 +99,14 @@ export interface BlogPostSummary {
|
|
|
79
99
|
readonly reading_minutes: number;
|
|
80
100
|
/** Lowercased, de-duplicated, at most 10. Never `null` in the payload. */
|
|
81
101
|
readonly tags: string[];
|
|
82
|
-
/**
|
|
102
|
+
/** `"user"` when written in the editor, `"api"` when a program posted it with an access token. */
|
|
103
|
+
readonly source: "user" | "api" | string;
|
|
104
|
+
/** The blog it belongs to, trimmed to four fields. */
|
|
83
105
|
readonly blog: {
|
|
84
106
|
readonly id: BlogId;
|
|
85
107
|
readonly slug: string;
|
|
86
108
|
readonly name: string;
|
|
109
|
+
readonly visibility: BlogVisibility | string;
|
|
87
110
|
};
|
|
88
111
|
}
|
|
89
112
|
/** A post with its body: the `:extended` view, returned by every single-post route. */
|
|
@@ -130,6 +153,64 @@ export interface UpdateBlogInput {
|
|
|
130
153
|
readonly name?: string;
|
|
131
154
|
/** Up to 240 characters. */
|
|
132
155
|
readonly description?: string | null;
|
|
156
|
+
readonly visibility?: BlogVisibility;
|
|
157
|
+
}
|
|
158
|
+
/** Arguments for {@link OwnBlogsNamespace.create}. Everything is optional: the defaults are the same as the first blog's. */
|
|
159
|
+
export interface CreateBlogInput {
|
|
160
|
+
readonly slug?: string;
|
|
161
|
+
readonly name?: string;
|
|
162
|
+
readonly description?: string | null;
|
|
163
|
+
/** Defaults to `"public"`. */
|
|
164
|
+
readonly visibility?: BlogVisibility;
|
|
165
|
+
}
|
|
166
|
+
/** An invited member of one of the caller's blogs. Being a member also subscribes the person to the blog's news. */
|
|
167
|
+
export interface BlogMember {
|
|
168
|
+
readonly id: number;
|
|
169
|
+
readonly blog_id: BlogId;
|
|
170
|
+
readonly user: BlogAuthor;
|
|
171
|
+
readonly created_at: Timestamp;
|
|
172
|
+
}
|
|
173
|
+
/** At most this many blogs per account; creating one more answers `400`. */
|
|
174
|
+
export declare const BLOGS_PER_ACCOUNT = 20;
|
|
175
|
+
/**
|
|
176
|
+
* The caller's own blogs, reachable as `oms.content.blogs.own`. Needs the
|
|
177
|
+
* `blogs:read` scope to read and `blogs:write` to change anything.
|
|
178
|
+
*
|
|
179
|
+
* A blog is addressed by its numeric id or its slug on every route here.
|
|
180
|
+
*/
|
|
181
|
+
export declare class OwnBlogsNamespace extends Resource {
|
|
182
|
+
/** `GET /my_blogs` - every blog the caller owns, oldest first. The first one is the default. */
|
|
183
|
+
list(options?: RequestOptions): Promise<Blog[]>;
|
|
184
|
+
/**
|
|
185
|
+
* `GET /my_blogs/:id` - one of the caller's blogs with ALL of its posts,
|
|
186
|
+
* drafts included, newest first.
|
|
187
|
+
*
|
|
188
|
+
* @throws {OmsApiError} 404 `"Blog not found"` for a blog the caller does not own.
|
|
189
|
+
*/
|
|
190
|
+
get(idOrSlug: BlogId | string, options?: RequestOptions): Promise<BlogWithPosts>;
|
|
191
|
+
/**
|
|
192
|
+
* `POST /my_blogs` - a further blog. Without a slug the server takes the
|
|
193
|
+
* handle with a numeric suffix.
|
|
194
|
+
*
|
|
195
|
+
* @throws {OmsApiError} 400 with the validation sentence (taken or
|
|
196
|
+
* malformed slug, unknown visibility) or `"blog limit reached (20)"`.
|
|
197
|
+
*/
|
|
198
|
+
create(input?: CreateBlogInput, options?: RequestOptions): Promise<Blog>;
|
|
199
|
+
/** `PATCH /my_blogs/:id` - name, slug, description or visibility. Re-slugging breaks published links. */
|
|
200
|
+
update(idOrSlug: BlogId | string, input: UpdateBlogInput, options?: RequestOptions): Promise<Blog>;
|
|
201
|
+
/** `DELETE /my_blogs/:id` - the blog and every post, subscriber and member in it. */
|
|
202
|
+
delete(idOrSlug: BlogId | string, options?: RequestOptions): Promise<void>;
|
|
203
|
+
/** `GET /my_blogs/:id/members` - the invited members, oldest first. */
|
|
204
|
+
members(idOrSlug: BlogId | string, options?: RequestOptions): Promise<BlogMember[]>;
|
|
205
|
+
/**
|
|
206
|
+
* `POST /my_blogs/:id/members` - invites a person of the site by handle (a
|
|
207
|
+
* leading `@` is fine). Idempotent: inviting twice answers the same member.
|
|
208
|
+
*
|
|
209
|
+
* @throws {OmsApiError} 404 `"User not found"`; 400 when the handle is the owner's own.
|
|
210
|
+
*/
|
|
211
|
+
addMember(idOrSlug: BlogId | string, handle: string, options?: RequestOptions): Promise<BlogMember>;
|
|
212
|
+
/** `DELETE /my_blogs/:id/members/:member` - by member id or by the member's user id. Their subscription goes too. */
|
|
213
|
+
removeMember(idOrSlug: BlogId | string, memberOrUserId: number | Id, options?: RequestOptions): Promise<void>;
|
|
133
214
|
}
|
|
134
215
|
/** Result of a subscribe call. */
|
|
135
216
|
export interface BlogSubscribeResult {
|
|
@@ -166,6 +247,8 @@ export interface BlogSubscribeResult {
|
|
|
166
247
|
export declare class BlogsNamespace extends Resource {
|
|
167
248
|
/** Posts, blog metadata and publishing. Also mounted as `oms.blogPosts`. */
|
|
168
249
|
readonly posts: BlogPostsNamespace;
|
|
250
|
+
/** The caller's own blogs: create more, change visibility, invite members. */
|
|
251
|
+
readonly own: OwnBlogsNamespace;
|
|
169
252
|
constructor(http: ApiClient);
|
|
170
253
|
/**
|
|
171
254
|
* `GET /blogs` - the discovery feed: the 30 most recent PUBLISHED posts
|
|
@@ -291,6 +374,11 @@ export declare class BlogsNamespace extends Resource {
|
|
|
291
374
|
}
|
|
292
375
|
/** Arguments for {@link BlogPostsNamespace.create}. */
|
|
293
376
|
export interface CreateBlogPostInput {
|
|
377
|
+
/** Which of the caller's blogs gets the post. Omit both for the default (oldest) blog. */
|
|
378
|
+
readonly blogId?: BlogId;
|
|
379
|
+
readonly blogSlug?: string;
|
|
380
|
+
/** Publish at once instead of saving a draft. */
|
|
381
|
+
readonly publish?: boolean;
|
|
294
382
|
/** Required, up to 200 characters. */
|
|
295
383
|
readonly title: string;
|
|
296
384
|
/**
|
|
@@ -379,45 +467,37 @@ export declare class BlogPostsNamespace extends Resource {
|
|
|
379
467
|
get(id: BlogPostId, options?: RequestOptions): Promise<BlogPost>;
|
|
380
468
|
/**
|
|
381
469
|
* `GET /blogs/:blogSlug/posts/:slug` - one post by the pair of slugs, which
|
|
382
|
-
* is the shape a public permalink has.
|
|
383
|
-
*
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
* link gets `401 "Session required to access this resource."` here, while
|
|
388
|
-
* {@link get} hands them the very same published post. Until that is fixed,
|
|
389
|
-
* render public permalinks through {@link get} with the numeric id, or
|
|
390
|
-
* expect signed-in readers only.
|
|
391
|
-
*
|
|
392
|
-
* Both slugs are lowercased server-side before the lookup. The route is
|
|
393
|
-
* declared with `constraints: { blog_slug: /[^\/]+/, slug: /[^\/]+/ }`, so a
|
|
394
|
-
* slug containing a slash cannot reach it at all - not a concern for
|
|
470
|
+
* is the shape a public permalink has. Open to anonymous readers for a
|
|
471
|
+
* published post of a public or unlisted blog.
|
|
472
|
+
*
|
|
473
|
+
* Both slugs are lowercased server-side before the lookup. A slug
|
|
474
|
+
* containing a slash cannot reach the route at all - not a concern for
|
|
395
475
|
* server-minted slugs, which are `[a-z0-9_-]` only.
|
|
396
476
|
*
|
|
397
|
-
* @throws {OmsApiError}
|
|
398
|
-
*
|
|
399
|
-
*
|
|
477
|
+
* @throws {OmsApiError} 404 `"Blog not found"` or `"Post not found"`; 401
|
|
478
|
+
* `"Draft only visible to author"`; for a private blog, 401 without a
|
|
479
|
+
* session and 403 `error: "private"` with one.
|
|
400
480
|
*/
|
|
401
481
|
getBySlugs(blogSlug: string, slug: string, options?: RequestOptions): Promise<BlogPost>;
|
|
402
482
|
/**
|
|
403
|
-
* `POST /blog_posts` - writes a new post
|
|
483
|
+
* `POST /blog_posts` - writes a new post. `201`.
|
|
404
484
|
*
|
|
405
|
-
*
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
* {@link BlogsNamespace.mine}.
|
|
485
|
+
* `blogId` or `blogSlug` picks one of the caller's own blogs; with neither
|
|
486
|
+
* the post lands in the default (oldest) blog, which is created on the spot
|
|
487
|
+
* if the caller has none yet, exactly like {@link BlogsNamespace.mine}.
|
|
409
488
|
*
|
|
410
|
-
* The post starts as a DRAFT
|
|
411
|
-
*
|
|
412
|
-
*
|
|
489
|
+
* The post starts as a DRAFT unless `publish: true` is sent, which stamps
|
|
490
|
+
* `published_at` at once. Later changes to the flag go through
|
|
491
|
+
* {@link setPublished}, not {@link update}. A post written with an access
|
|
492
|
+
* token carries `source: "api"`.
|
|
413
493
|
*
|
|
414
494
|
* Rides the general ceiling: there is no per-user cap on how many posts may
|
|
415
495
|
* be created, and no length cap beyond the model's 200 000 characters of
|
|
416
|
-
* markdown.
|
|
496
|
+
* markdown. Needs the `blogs:write` scope on an OAuth token.
|
|
417
497
|
*
|
|
418
498
|
* @throws {OmsApiError} 401 `"Session required to access this resource."`;
|
|
419
|
-
*
|
|
420
|
-
* in this blog.
|
|
499
|
+
* 404 `"Blog not found"` for a blog the caller does not own; 400 with the
|
|
500
|
+
* validation sentence, most often the slug already existing in this blog.
|
|
421
501
|
*/
|
|
422
502
|
create(input: CreateBlogPostInput, options?: RequestOptions): Promise<BlogPost>;
|
|
423
503
|
/**
|
|
@@ -3,7 +3,7 @@ import { type ApiClient, Resource } from "../../http";
|
|
|
3
3
|
import { AnalysisNamespace } from "./analysis";
|
|
4
4
|
import { BlogsNamespace } from "./blogs";
|
|
5
5
|
import { FeedbacksNamespace } from "./feedbacks";
|
|
6
|
-
import {
|
|
6
|
+
import { NewsNamespace } from "./news/index";
|
|
7
7
|
import { JokesNamespace } from "./jokes";
|
|
8
8
|
import { NotificationsNamespace } from "./notifications";
|
|
9
9
|
import { ServiceUsagesNamespace } from "./serviceUsages";
|
|
@@ -13,7 +13,7 @@ import { SpaceInvadersNamespace } from "./spaceInvaders";
|
|
|
13
13
|
export * from "./analysis";
|
|
14
14
|
export * from "./blogs";
|
|
15
15
|
export * from "./feedbacks";
|
|
16
|
-
export * from "./
|
|
16
|
+
export * from "./news/index";
|
|
17
17
|
export * from "./jokes";
|
|
18
18
|
export * from "./notifications";
|
|
19
19
|
export * from "./serviceUsages";
|
|
@@ -46,7 +46,7 @@ export declare class ContentNamespace extends Resource {
|
|
|
46
46
|
readonly analysis: AnalysisNamespace;
|
|
47
47
|
/** The Space Invaders leaderboard. */
|
|
48
48
|
readonly spaceInvaders: SpaceInvadersNamespace;
|
|
49
|
-
/**
|
|
50
|
-
readonly
|
|
49
|
+
/** News: feeds, sources, scripts and the items they produce. See {@link NewsNamespace}. */
|
|
50
|
+
readonly news: NewsNamespace;
|
|
51
51
|
constructor(http: ApiClient);
|
|
52
52
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** News feeds: the named sets of sources a person follows. */
|
|
2
|
+
import { Resource } from "../../../http";
|
|
3
|
+
import type { ListParams } from "../../../listing";
|
|
4
|
+
import type { Id, Paginated, RequestOptions, Timestamp } from "../../../types";
|
|
5
|
+
/** At most this many feeds per account; one more is a `400`. */
|
|
6
|
+
export declare const NEWS_FEEDS_PER_ACCOUNT = 10;
|
|
7
|
+
/** `retention_days` outside this range is a `400`. */
|
|
8
|
+
export declare const NEWS_FEED_MIN_RETENTION_DAYS = 7;
|
|
9
|
+
export declare const NEWS_FEED_MAX_RETENTION_DAYS = 3650;
|
|
10
|
+
/**
|
|
11
|
+
* A feed: a named set of {@link NewsSource}s and the {@link NewsItem}s they
|
|
12
|
+
* produce. Several per account, unique by name; the oldest is the default
|
|
13
|
+
* one a source lands in when it names no feed.
|
|
14
|
+
*/
|
|
15
|
+
export interface NewsFeed {
|
|
16
|
+
readonly id: Id;
|
|
17
|
+
readonly created_at: Timestamp;
|
|
18
|
+
readonly updated_at: Timestamp;
|
|
19
|
+
/** Up to 80 characters, whitespace-squished, unique per account. */
|
|
20
|
+
readonly name: string;
|
|
21
|
+
/** Up to 500 characters. */
|
|
22
|
+
readonly description: string | null;
|
|
23
|
+
/** Items older than this are pruned. Default 90. */
|
|
24
|
+
readonly retention_days: number;
|
|
25
|
+
/** A disabled feed's sources are not polled. */
|
|
26
|
+
readonly enabled: boolean;
|
|
27
|
+
}
|
|
28
|
+
/** `GET /news_feeds/:id` adds two live counters. */
|
|
29
|
+
export interface NewsFeedDetail extends NewsFeed {
|
|
30
|
+
readonly sources_count: number;
|
|
31
|
+
readonly items_count: number;
|
|
32
|
+
}
|
|
33
|
+
/** Filter columns of `GET /news_feeds`, on top of {@link BASE_FILTER_COLUMNS}. */
|
|
34
|
+
export declare const NEWS_FEED_FILTER_COLUMNS: readonly ["name", "enabled"];
|
|
35
|
+
export interface ListNewsFeedsParams extends ListParams<(typeof NEWS_FEED_FILTER_COLUMNS)[number]> {
|
|
36
|
+
}
|
|
37
|
+
export interface CreateNewsFeedInput {
|
|
38
|
+
readonly name: string;
|
|
39
|
+
readonly description?: string | null;
|
|
40
|
+
readonly retentionDays?: number;
|
|
41
|
+
readonly enabled?: boolean;
|
|
42
|
+
}
|
|
43
|
+
export type UpdateNewsFeedInput = Partial<CreateNewsFeedInput>;
|
|
44
|
+
/** `/news_feeds` - your feeds. Needs `news:read` to read and `news:write` to change. */
|
|
45
|
+
export declare class NewsFeedsNamespace extends Resource {
|
|
46
|
+
/** `GET /news_feeds` - your feeds, oldest first. */
|
|
47
|
+
list(params?: ListNewsFeedsParams, options?: RequestOptions): Promise<Paginated<NewsFeed>>;
|
|
48
|
+
/** `GET /news_feeds/:id` - one feed with its counters. 404 when it is not yours. */
|
|
49
|
+
get(id: Id, options?: RequestOptions): Promise<NewsFeedDetail>;
|
|
50
|
+
/** `POST /news_feeds`. `201`. 400 for a duplicate name or past the cap. */
|
|
51
|
+
create(input: CreateNewsFeedInput, options?: RequestOptions): Promise<NewsFeed>;
|
|
52
|
+
/** `PATCH /news_feeds/:id`. */
|
|
53
|
+
update(id: Id, input: UpdateNewsFeedInput, options?: RequestOptions): Promise<NewsFeed>;
|
|
54
|
+
/** `DELETE /news_feeds/:id` - the feed, its sources and every item. `204`. */
|
|
55
|
+
delete(id: Id, options?: RequestOptions): Promise<void>;
|
|
56
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** The `news` namespace and everything under it. */
|
|
2
|
+
import { type ApiClient, Resource } from "../../../http";
|
|
3
|
+
import { NewsFeedsNamespace } from "./feeds";
|
|
4
|
+
import { NewsItemsNamespace } from "./items";
|
|
5
|
+
import { NewsScriptsNamespace } from "./scripts";
|
|
6
|
+
import { NewsSourcesNamespace } from "./sources";
|
|
7
|
+
export * from "./feeds";
|
|
8
|
+
export * from "./items";
|
|
9
|
+
export * from "./scripts";
|
|
10
|
+
export * from "./sources";
|
|
11
|
+
/**
|
|
12
|
+
* The `news` namespace, reachable as `oms.content.news`: the ingestion side
|
|
13
|
+
* of following the web.
|
|
14
|
+
*
|
|
15
|
+
* 1. a {@link NewsScript} knows HOW to fetch one kind of source (RSS, a
|
|
16
|
+
* Telegram channel, a YouTube channel, a page with a selector);
|
|
17
|
+
* 2. a {@link NewsSource} is that script plus its settings, inside a
|
|
18
|
+
* {@link NewsFeed} - a named set of sources;
|
|
19
|
+
* 3. polling a source writes {@link NewsItem} rows: raw, one per thing the
|
|
20
|
+
* source published, full-text searchable and readable incrementally.
|
|
21
|
+
*
|
|
22
|
+
* Open to every account within its quotas (`news_sources` in
|
|
23
|
+
* `oms.quotas.list()`). Needs the `news:read` and `news:write` scopes on an
|
|
24
|
+
* OAuth token. Ids are strings throughout.
|
|
25
|
+
*/
|
|
26
|
+
export declare class NewsNamespace extends Resource {
|
|
27
|
+
/** Named sets of sources. Full CRUD. */
|
|
28
|
+
readonly feeds: NewsFeedsNamespace;
|
|
29
|
+
/** The sources you follow. Full CRUD, plus a manual run. */
|
|
30
|
+
readonly sources: NewsSourcesNamespace;
|
|
31
|
+
/** The fetchers. Full CRUD over yours; the built-ins are read-only. */
|
|
32
|
+
readonly scripts: NewsScriptsNamespace;
|
|
33
|
+
/** What the sources produced. Read plus delete. */
|
|
34
|
+
readonly items: NewsItemsNamespace;
|
|
35
|
+
constructor(http: ApiClient);
|
|
36
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/** News items: what the sources produced, raw. */
|
|
2
|
+
import { Resource } from "../../../http";
|
|
3
|
+
import type { ListParams } from "../../../listing";
|
|
4
|
+
import type { Id, Paginated, RequestOptions, Timestamp } from "../../../types";
|
|
5
|
+
/**
|
|
6
|
+
* A raw item, exactly as a script returned it.
|
|
7
|
+
*
|
|
8
|
+
* Written only by the ingest job; over HTTP it is read-only plus a delete.
|
|
9
|
+
* Items are the substrate everything downstream (a report, a story, a cron
|
|
10
|
+
* script) is built from - nothing copies the body, it points here.
|
|
11
|
+
*/
|
|
12
|
+
export interface NewsItem {
|
|
13
|
+
readonly id: Id;
|
|
14
|
+
readonly created_at: Timestamp;
|
|
15
|
+
readonly updated_at: Timestamp;
|
|
16
|
+
/** The feed the source belonged to when the item was written. */
|
|
17
|
+
readonly news_feed_id: Id;
|
|
18
|
+
/** Which source produced it. */
|
|
19
|
+
readonly news_source_id: Id;
|
|
20
|
+
/**
|
|
21
|
+
* The script's own id for this item, unique per source. This is the
|
|
22
|
+
* de-duplication key: a second poll that returns the same `external_id` does
|
|
23
|
+
* not create a second row.
|
|
24
|
+
*/
|
|
25
|
+
readonly external_id: string;
|
|
26
|
+
readonly title: string | null;
|
|
27
|
+
/** The body the script extracted. Can be large; a listing carries all of it. */
|
|
28
|
+
readonly content: string | null;
|
|
29
|
+
readonly url: string | null;
|
|
30
|
+
readonly author: string | null;
|
|
31
|
+
/** Publication time as the feed reported it, not as we saw it. */
|
|
32
|
+
readonly published_at: Timestamp | null;
|
|
33
|
+
/** When the poll that produced this item ran. Never null. */
|
|
34
|
+
readonly fetched_at: Timestamp;
|
|
35
|
+
/**
|
|
36
|
+
* Set when the item is a VIDEO the script discovered (YouTube, RTP Play):
|
|
37
|
+
* the server downloads the audio, transcribes it and splits it into news
|
|
38
|
+
* items. The video row itself stays as it is; the news it yields are child
|
|
39
|
+
* items pointing back via {@link parent_id}.
|
|
40
|
+
*/
|
|
41
|
+
readonly media_url: string | null;
|
|
42
|
+
/**
|
|
43
|
+
* Transcription state of a video row: `pending` → `processing` →
|
|
44
|
+
* `transcribed` (the `content` now holds the `[m:ss] text` transcript) →
|
|
45
|
+
* `done`, or `failed` with {@link media_error}. `null` on non-video items.
|
|
46
|
+
*/
|
|
47
|
+
readonly media_status: NewsMediaStatus | null;
|
|
48
|
+
readonly media_error: string | null;
|
|
49
|
+
/** On a news item cut from a video: the video (parent) item's id. */
|
|
50
|
+
readonly parent_id: Id | null;
|
|
51
|
+
/** On a news item cut from a video: where in the video it starts, in seconds. */
|
|
52
|
+
readonly media_offset_s: number | null;
|
|
53
|
+
}
|
|
54
|
+
/** Lifecycle of a video item's transcription. */
|
|
55
|
+
export type NewsMediaStatus = "pending" | "processing" | "transcribed" | "done" | "failed";
|
|
56
|
+
/** Filter columns of `GET /news_items`, on top of {@link BASE_FILTER_COLUMNS}. */
|
|
57
|
+
export declare const NEWS_ITEM_FILTER_COLUMNS: readonly ["news_feed_id", "news_source_id", "external_id", "title", "content", "url", "media_status", "parent_id"];
|
|
58
|
+
/** Filters for {@link NewsItemsNamespace.list}. */
|
|
59
|
+
export interface ListNewsItemsParams extends ListParams<(typeof NEWS_ITEM_FILTER_COLUMNS)[number]> {
|
|
60
|
+
/** Only items of one feed. Sent as `exact_search[news_feed_id]`. */
|
|
61
|
+
readonly feedId?: Id;
|
|
62
|
+
/** Only items produced by one source. Sent as `exact_search[news_source_id]`. */
|
|
63
|
+
readonly sourceId?: Id;
|
|
64
|
+
/**
|
|
65
|
+
* Full-text search over title and body, in Portuguese (stemmed, so
|
|
66
|
+
* `mesquitas` finds `mesquita`). Web-search syntax: quotes for a phrase,
|
|
67
|
+
* `-` to exclude, `or` between words. Results come by relevance when this
|
|
68
|
+
* is set, whatever `order` says.
|
|
69
|
+
*/
|
|
70
|
+
readonly query?: string;
|
|
71
|
+
/** Only items written at or after this instant (ISO 8601). The incremental read a script wants. */
|
|
72
|
+
readonly since?: string;
|
|
73
|
+
/** Only items written at or before this instant (ISO 8601). */
|
|
74
|
+
readonly until?: string;
|
|
75
|
+
}
|
|
76
|
+
/** Parameters of {@link NewsItemsNamespace.similar}: an anchor plus optional narrowing. */
|
|
77
|
+
export type SimilarNewsItemsParams = ({
|
|
78
|
+
/** Free text to compare against. */
|
|
79
|
+
readonly text: string;
|
|
80
|
+
readonly itemId?: undefined;
|
|
81
|
+
} | {
|
|
82
|
+
/** One of your items to compare against. It never comes back in the results. */
|
|
83
|
+
readonly itemId: Id;
|
|
84
|
+
readonly text?: undefined;
|
|
85
|
+
}) & {
|
|
86
|
+
/** Only items of one feed. */
|
|
87
|
+
readonly feedId?: Id;
|
|
88
|
+
/** 1..50, default 10. */
|
|
89
|
+
readonly limit?: number;
|
|
90
|
+
/** Only items written at or after this instant (ISO 8601). */
|
|
91
|
+
readonly since?: string | Date;
|
|
92
|
+
/** Cosine distance ceiling, 0..1, default 0.35. Lower is stricter. */
|
|
93
|
+
readonly maxDistance?: number;
|
|
94
|
+
};
|
|
95
|
+
/** A hit of {@link NewsItemsNamespace.similar}: the item plus how far it sits from the anchor. */
|
|
96
|
+
export type SimilarNewsItem = NewsItem & {
|
|
97
|
+
/** Cosine distance to the anchor: `0` is the same text, `1` unrelated. */
|
|
98
|
+
readonly distance: number;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* `/news_items` - the raw material.
|
|
102
|
+
*
|
|
103
|
+
* Read-only plus a delete: items are written by the ingest job and by
|
|
104
|
+
* nothing else.
|
|
105
|
+
*/
|
|
106
|
+
export declare class NewsItemsNamespace extends Resource {
|
|
107
|
+
/**
|
|
108
|
+
* `GET /news_items` - raw items, newest first.
|
|
109
|
+
*
|
|
110
|
+
* **Heavy.** Every row carries {@link NewsItem.content} in full - the whole
|
|
111
|
+
* article text a script scraped - and there is no lighter view. The SDK
|
|
112
|
+
* defaults to a page of 25 for that reason; raising it is how you get a
|
|
113
|
+
* multi-megabyte response.
|
|
114
|
+
*
|
|
115
|
+
* For an incremental reader, remember the newest `created_at` you saw and
|
|
116
|
+
* pass it back as `since` with `order: "created_at:asc"`.
|
|
117
|
+
*
|
|
118
|
+
* The controller sets no ordering; the SDK sends `created_at:desc`.
|
|
119
|
+
*
|
|
120
|
+
* @throws {OmsApiError} 400 when `since` or `until` is not ISO 8601.
|
|
121
|
+
*/
|
|
122
|
+
list(params?: ListNewsItemsParams, options?: RequestOptions): Promise<Paginated<NewsItem>>;
|
|
123
|
+
/**
|
|
124
|
+
* `GET /news_items/:id` - one raw item. Same shape a listing row has.
|
|
125
|
+
*
|
|
126
|
+
* @throws {OmsApiError} 404 when the item is not yours.
|
|
127
|
+
*/
|
|
128
|
+
get(id: Id, options?: RequestOptions): Promise<NewsItem>;
|
|
129
|
+
/**
|
|
130
|
+
* `GET /news_items/similar` - your items closest in meaning to a text or to
|
|
131
|
+
* one of your items, nearest first, no paging.
|
|
132
|
+
*
|
|
133
|
+
* Meaning, not words: "mesquita de Lisboa" finds an item about the mosque
|
|
134
|
+
* that never uses the word. Every item gets its vector shortly after it is
|
|
135
|
+
* written, so a fresh one may still be missing from the results; videos
|
|
136
|
+
* have none (the news cut from them do).
|
|
137
|
+
*
|
|
138
|
+
* @throws {OmsApiError} 400 when neither `text` nor `itemId` is given, `limit`
|
|
139
|
+
* is outside 1..50, `maxDistance` outside 0..1, or `since` is not ISO 8601.
|
|
140
|
+
* @throws {OmsApiError} 404 when `itemId` is not yours.
|
|
141
|
+
* @throws {OmsApiError} 422 when that item has no vector yet.
|
|
142
|
+
* @throws {OmsApiError} 502 when `text` cannot be embedded right now.
|
|
143
|
+
*/
|
|
144
|
+
similar(params: SimilarNewsItemsParams, options?: RequestOptions): Promise<SimilarNewsItem[]>;
|
|
145
|
+
/**
|
|
146
|
+
* `DELETE /news_items/:id`. `204`, empty body.
|
|
147
|
+
*
|
|
148
|
+
* Rarely what you want. The item's `external_id` uniqueness is what stops the
|
|
149
|
+
* next poll re-fetching it, so deleting one invites it straight back on the
|
|
150
|
+
* following run. Delete the SOURCE, or leave items alone.
|
|
151
|
+
*
|
|
152
|
+
* @throws {OmsApiError} 404 when the item is not yours.
|
|
153
|
+
*/
|
|
154
|
+
delete(id: Id, options?: RequestOptions): Promise<void>;
|
|
155
|
+
}
|