@omelhorsite/sdk 0.2.0 → 0.4.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 +112 -130
- package/dist/index.js +4800 -610
- package/dist/types/client.d.ts +60 -3
- package/dist/types/http.d.ts +444 -19
- package/dist/types/index.d.ts +5 -1
- package/dist/types/internal/attachments.d.ts +17 -0
- package/dist/types/internal/helpers.d.ts +9 -0
- package/dist/types/listing.d.ts +90 -0
- package/dist/types/resources/account.d.ts +71 -5
- package/dist/types/resources/admin/authorizedApplications.d.ts +133 -0
- package/dist/types/resources/admin/chests.d.ts +51 -0
- package/dist/types/resources/admin/eventAlerts.d.ts +60 -0
- package/dist/types/resources/admin/identities.d.ts +99 -0
- package/dist/types/resources/admin/index.d.ts +77 -0
- package/dist/types/resources/admin/jobs.d.ts +97 -0
- package/dist/types/resources/admin/myOauthApplications.d.ts +282 -0
- package/dist/types/resources/admin/notepads.d.ts +49 -0
- package/dist/types/resources/admin/oauthApplications.d.ts +309 -0
- package/dist/types/resources/admin/quotas.d.ts +114 -0
- package/dist/types/resources/admin/shortLinks.d.ts +201 -0
- package/dist/types/resources/admin/types.d.ts +222 -0
- package/dist/types/resources/admin/vocalSeparations.d.ts +98 -0
- package/dist/types/resources/admin.d.ts +1841 -0
- package/dist/types/resources/auth/index.d.ts +39 -0
- package/dist/types/resources/auth/passkeys.d.ts +652 -0
- package/dist/types/resources/auth/sessions.d.ts +844 -0
- package/dist/types/resources/chests.d.ts +54 -3
- package/dist/types/resources/content/analysis.d.ts +62 -0
- package/dist/types/resources/content/blogs.d.ts +471 -0
- package/dist/types/resources/content/feedbacks.d.ts +263 -0
- package/dist/types/resources/content/index.d.ts +52 -0
- package/dist/types/resources/content/intel/articles.d.ts +230 -0
- package/dist/types/resources/content/intel/config.d.ts +135 -0
- package/dist/types/resources/content/intel/index.d.ts +53 -0
- package/dist/types/resources/content/intel/items.d.ts +91 -0
- package/dist/types/resources/content/intel/reports.d.ts +108 -0
- package/dist/types/resources/content/intel/scripts.d.ts +152 -0
- package/dist/types/resources/content/intel/sources.d.ts +236 -0
- package/dist/types/resources/content/intel/stats.d.ts +105 -0
- package/dist/types/resources/content/intel/types.d.ts +86 -0
- package/dist/types/resources/content/jokes.d.ts +93 -0
- package/dist/types/resources/content/notifications.d.ts +147 -0
- package/dist/types/resources/content/serviceUsages.d.ts +73 -0
- package/dist/types/resources/content/servicesStatus.d.ts +194 -0
- package/dist/types/resources/content/siteConfig.d.ts +43 -0
- package/dist/types/resources/content/spaceInvaders.d.ts +154 -0
- package/dist/types/resources/content.d.ts +2775 -0
- package/dist/types/resources/dynamicQrs.d.ts +39 -3
- package/dist/types/resources/forms.d.ts +176 -35
- package/dist/types/resources/index.d.ts +19 -8
- package/dist/types/resources/ipLookup.d.ts +20 -4
- package/dist/types/resources/jobs.d.ts +69 -25
- package/dist/types/resources/library/annotations.d.ts +162 -0
- package/dist/types/resources/library/books.d.ts +534 -0
- package/dist/types/resources/library/chat.d.ts +259 -0
- package/dist/types/resources/library/index.d.ts +39 -0
- package/dist/types/resources/library/shelves.d.ts +237 -0
- package/dist/types/resources/library/types.d.ts +120 -0
- package/dist/types/resources/library.d.ts +1433 -0
- package/dist/types/resources/linkTrees.d.ts +142 -30
- package/dist/types/resources/media.d.ts +351 -0
- package/dist/types/resources/movies/addons.d.ts +388 -0
- package/dist/types/resources/movies/collections.d.ts +352 -0
- package/dist/types/resources/movies/index.d.ts +29 -0
- package/dist/types/resources/movies/types.d.ts +50 -0
- package/dist/types/resources/movies/watchProgress.d.ts +277 -0
- package/dist/types/resources/movies.d.ts +1160 -0
- package/dist/types/resources/music/artists.d.ts +1068 -0
- package/dist/types/resources/music/imports.d.ts +941 -0
- package/dist/types/resources/music/index.d.ts +61 -0
- package/dist/types/resources/music/playlists.d.ts +1027 -0
- package/dist/types/resources/music/social.d.ts +1132 -0
- package/dist/types/resources/music/songs.d.ts +1167 -0
- package/dist/types/resources/notepads.d.ts +4 -1
- package/dist/types/resources/quotas.d.ts +7 -1
- package/dist/types/resources/realtime.d.ts +855 -0
- package/dist/types/resources/shortLinks.d.ts +49 -5
- package/dist/types/resources/social/groupChats.d.ts +458 -0
- package/dist/types/resources/social/index.d.ts +19 -0
- package/dist/types/resources/social/messages.d.ts +424 -0
- package/dist/types/resources/social/relationships.d.ts +322 -0
- package/dist/types/resources/social/types.d.ts +37 -0
- package/dist/types/resources/social.d.ts +1348 -0
- package/dist/types/resources/storage/upload.d.ts +158 -11
- package/dist/types/resources/storage.d.ts +111 -27
- package/dist/types/resources/tickets.d.ts +101 -13
- package/dist/types/resources/tools/backgroundRemoval.d.ts +18 -3
- package/dist/types/resources/tools/captions.d.ts +448 -21
- package/dist/types/resources/tools/downloader.d.ts +21 -0
- package/dist/types/resources/tools/index.d.ts +57 -15
- package/dist/types/resources/tools/jumpstyle.d.ts +50 -17
- package/dist/types/resources/tools/transcription.d.ts +35 -13
- package/dist/types/resources/tools/upscale.d.ts +23 -3
- package/dist/types/resources/tools/vocalSeparation.d.ts +30 -13
- package/dist/types/types.d.ts +249 -17
- package/package.json +2 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** The `intel` namespace and everything under it. */
|
|
2
|
+
import { type ApiClient, Resource } from "../../../http";
|
|
3
|
+
import { IntelArticlesNamespace } from "./articles";
|
|
4
|
+
import { IntelConfigNamespace } from "./config";
|
|
5
|
+
import { IntelItemsNamespace } from "./items";
|
|
6
|
+
import { IntelReportsNamespace } from "./reports";
|
|
7
|
+
import { IntelScriptsNamespace } from "./scripts";
|
|
8
|
+
import { IntelSourcesNamespace } from "./sources";
|
|
9
|
+
import { IntelStatsNamespace } from "./stats";
|
|
10
|
+
export * from "./articles";
|
|
11
|
+
export * from "./config";
|
|
12
|
+
export * from "./items";
|
|
13
|
+
export * from "./reports";
|
|
14
|
+
export * from "./scripts";
|
|
15
|
+
export * from "./sources";
|
|
16
|
+
export * from "./stats";
|
|
17
|
+
export * from "./types";
|
|
18
|
+
/**
|
|
19
|
+
* The `intel` namespace, reachable as `oms.content.intel`.
|
|
20
|
+
*
|
|
21
|
+
* A tour of the data model, because the names do not give it away:
|
|
22
|
+
*
|
|
23
|
+
* 1. a {@link IntelScript} knows HOW to fetch one kind of feed;
|
|
24
|
+
* 2. an {@link IntelSource} is that script plus its settings - a feed you
|
|
25
|
+
* actually follow;
|
|
26
|
+
* 3. polling a source writes {@link IntelItem} rows: raw, unprocessed, one per
|
|
27
|
+
* thing the feed published;
|
|
28
|
+
* 4. the analysis pipeline groups items into {@link IntelArticle} stories,
|
|
29
|
+
* scores them against your {@link IntelConfig} rubric, enriches the
|
|
30
|
+
* important ones and links related ones together;
|
|
31
|
+
* 5. {@link IntelReport} digests summarise a closed time window of stories.
|
|
32
|
+
*
|
|
33
|
+
* Only steps 1 and 2 are yours to write. Everything from step 3 on is produced
|
|
34
|
+
* by background jobs and is read-only over HTTP - a delete is the only mutation
|
|
35
|
+
* you get, and it is a hide, not an undo.
|
|
36
|
+
*/
|
|
37
|
+
export declare class IntelNamespace extends Resource {
|
|
38
|
+
/** Stories: the analysed, grouped, scored output. Read plus delete. */
|
|
39
|
+
readonly articles: IntelArticlesNamespace;
|
|
40
|
+
/** Generated digests over closed time windows. Read plus delete. */
|
|
41
|
+
readonly reports: IntelReportsNamespace;
|
|
42
|
+
/** The feeds you follow. Full CRUD, plus a manual run. */
|
|
43
|
+
readonly sources: IntelSourcesNamespace;
|
|
44
|
+
/** The fetchers. Full CRUD over yours; the built-ins are read-only. */
|
|
45
|
+
readonly scripts: IntelScriptsNamespace;
|
|
46
|
+
/** The raw material behind the stories. Read plus delete. */
|
|
47
|
+
readonly items: IntelItemsNamespace;
|
|
48
|
+
/** Your rubric, thresholds and prompt overrides. */
|
|
49
|
+
readonly config: IntelConfigNamespace;
|
|
50
|
+
/** Dashboard counters, in one expensive call. */
|
|
51
|
+
readonly stats: IntelStatsNamespace;
|
|
52
|
+
constructor(http: ApiClient);
|
|
53
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/** Intel items: the raw material behind the stories. */
|
|
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 `Intel::FetchSourceJob`; over HTTP it is read-only plus a
|
|
9
|
+
* delete. Items are the substrate the stories are built from - the story never
|
|
10
|
+
* copies the body, it points here.
|
|
11
|
+
*/
|
|
12
|
+
export interface IntelItem {
|
|
13
|
+
readonly id: Id;
|
|
14
|
+
readonly created_at: Timestamp;
|
|
15
|
+
readonly updated_at: Timestamp;
|
|
16
|
+
/** Which source produced it. */
|
|
17
|
+
readonly intel_source_id: Id;
|
|
18
|
+
/**
|
|
19
|
+
* The script's own id for this item, unique per source. This is the
|
|
20
|
+
* de-duplication key: a second poll that returns the same `external_id` does
|
|
21
|
+
* not create a second row.
|
|
22
|
+
*/
|
|
23
|
+
readonly external_id: string;
|
|
24
|
+
readonly title: string | null;
|
|
25
|
+
/** The body the script extracted. Can be large; a listing carries all of it. */
|
|
26
|
+
readonly content: string | null;
|
|
27
|
+
readonly url: string | null;
|
|
28
|
+
readonly author: string | null;
|
|
29
|
+
/** Publication time as the feed reported it, not as we saw it. */
|
|
30
|
+
readonly published_at: Timestamp | null;
|
|
31
|
+
/** When the poll that produced this item ran. Never null. */
|
|
32
|
+
readonly fetched_at: Timestamp;
|
|
33
|
+
}
|
|
34
|
+
/** Filter columns of `GET /intel_items`, on top of {@link BASE_FILTER_COLUMNS}. */
|
|
35
|
+
export declare const INTEL_ITEM_FILTER_COLUMNS: readonly ["intel_source_id", "external_id", "title", "content", "url"];
|
|
36
|
+
/** Filters for {@link IntelItemsNamespace.list}. */
|
|
37
|
+
export interface ListIntelItemsParams extends ListParams<(typeof INTEL_ITEM_FILTER_COLUMNS)[number]> {
|
|
38
|
+
/** Only items produced by one source. Sent as `exact_search[intel_source_id]`. */
|
|
39
|
+
readonly sourceId?: Id;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* `/intel_items` - the raw material.
|
|
43
|
+
*
|
|
44
|
+
* Read-only plus a delete: `creatable_by?` and `updatable_by?` are hard `false`
|
|
45
|
+
* and the route is `only: [:index, :show, :destroy]`. Items are written by
|
|
46
|
+
* `Intel::FetchSourceJob` and by nothing else.
|
|
47
|
+
*
|
|
48
|
+
* It is here because the stories only carry a citation stub
|
|
49
|
+
* ({@link IntelArticleSourceRef}) and this is the only way to read the body
|
|
50
|
+
* behind one.
|
|
51
|
+
*/
|
|
52
|
+
export declare class IntelItemsNamespace extends Resource {
|
|
53
|
+
/**
|
|
54
|
+
* `GET /intel_items` - raw items, newest first.
|
|
55
|
+
*
|
|
56
|
+
* **Heavy.** Every row carries {@link IntelItem.content} in full - the whole
|
|
57
|
+
* article text a script scraped - and there is no lighter view. The SDK
|
|
58
|
+
* defaults to a page of 25 for that reason; raising it is how you get a
|
|
59
|
+
* multi-megabyte response.
|
|
60
|
+
*
|
|
61
|
+
* Declared filters: `intel_source_id`, `external_id`, `title`, `content`,
|
|
62
|
+
* `url`, plus the inherited three. Note `processed_at` is NOT among them and
|
|
63
|
+
* is not on the payload either, so there is no way to list only the
|
|
64
|
+
* unprocessed items - {@link IntelStats.totals.pending_items} is the only
|
|
65
|
+
* window onto that backlog.
|
|
66
|
+
*
|
|
67
|
+
* The controller sets no ordering; the SDK sends `created_at:desc`.
|
|
68
|
+
*/
|
|
69
|
+
list(params?: ListIntelItemsParams, options?: RequestOptions): Promise<Paginated<IntelItem>>;
|
|
70
|
+
/**
|
|
71
|
+
* `GET /intel_items/:id` - one raw item.
|
|
72
|
+
*
|
|
73
|
+
* There are no `:extended` extras, so this is the same shape a listing row
|
|
74
|
+
* has. Use it to expand one {@link IntelArticleSourceRef} without
|
|
75
|
+
* pulling a page of bodies.
|
|
76
|
+
*
|
|
77
|
+
* @throws {OmsApiError} 404 when the item is not yours.
|
|
78
|
+
*/
|
|
79
|
+
get(id: Id, options?: RequestOptions): Promise<IntelItem>;
|
|
80
|
+
/**
|
|
81
|
+
* `DELETE /intel_items/:id`. `204`, empty body.
|
|
82
|
+
*
|
|
83
|
+
* Rarely what you want. The item's `external_id` uniqueness is what stops the
|
|
84
|
+
* next poll re-fetching it, so deleting one invites it straight back on the
|
|
85
|
+
* following run - and if the story built from it survives, you get a second
|
|
86
|
+
* citation of the same thing. Delete the SOURCE, or leave items alone.
|
|
87
|
+
*
|
|
88
|
+
* @throws {OmsApiError} 404 when the item is not yours.
|
|
89
|
+
*/
|
|
90
|
+
delete(id: Id, options?: RequestOptions): Promise<void>;
|
|
91
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/** Intel reports: generated digests over closed time windows. */
|
|
2
|
+
import { Resource } from "../../../http";
|
|
3
|
+
import type { ListParams } from "../../../listing";
|
|
4
|
+
import type { Id, Json, Paginated, RequestOptions, Timestamp } from "../../../types";
|
|
5
|
+
import type { IntelArticleCategory, IntelReportKind } from "./types";
|
|
6
|
+
/** A story as a report inlines it. Four keys, no summary and no body. */
|
|
7
|
+
export interface IntelReportArticleRef {
|
|
8
|
+
readonly id: Id;
|
|
9
|
+
readonly title: string | null;
|
|
10
|
+
readonly importance: number;
|
|
11
|
+
readonly category: IntelArticleCategory | null;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A generated report over one closed time window.
|
|
15
|
+
*
|
|
16
|
+
* The index shape. `GET /intel_reports/:id` adds three keys - see
|
|
17
|
+
* {@link IntelReportDetail}.
|
|
18
|
+
*
|
|
19
|
+
* There is at most ONE report per `(user, kind, period_end)`: the migration
|
|
20
|
+
* puts a unique index on that triple precisely so a re-run of
|
|
21
|
+
* `GenerateReportJob` cannot mint a duplicate. Windows are the last CLOSED
|
|
22
|
+
* period, computed by `IntelReport.last_window`, so a `"day"` report covers
|
|
23
|
+
* yesterday and never the day in progress.
|
|
24
|
+
*/
|
|
25
|
+
export interface IntelReport {
|
|
26
|
+
readonly id: Id;
|
|
27
|
+
readonly created_at: Timestamp;
|
|
28
|
+
readonly updated_at: Timestamp;
|
|
29
|
+
/** Which window: see {@link INTEL_REPORT_KINDS}. */
|
|
30
|
+
readonly kind: IntelReportKind;
|
|
31
|
+
/** Title the model wrote. Nullable. */
|
|
32
|
+
readonly title: string | null;
|
|
33
|
+
/** Start of the window, inclusive. */
|
|
34
|
+
readonly period_start: Timestamp;
|
|
35
|
+
/** End of the window, exclusive. Also the sort key of the listing. */
|
|
36
|
+
readonly period_end: Timestamp;
|
|
37
|
+
/** LLM that wrote it, as configured at generation time. Nullable. */
|
|
38
|
+
readonly model: string | null;
|
|
39
|
+
}
|
|
40
|
+
/** `GET /intel_reports/:id` - the `:extended` view. */
|
|
41
|
+
export interface IntelReportDetail extends IntelReport {
|
|
42
|
+
/** The report body, usually Markdown. `null` if generation failed halfway. */
|
|
43
|
+
readonly content: string | null;
|
|
44
|
+
/**
|
|
45
|
+
* Whatever the generator chose to record about the run. A free-form JSON
|
|
46
|
+
* object with no schema on either side, defaulting to `{}` - which is why it
|
|
47
|
+
* is typed as a bag rather than as fields. Read it defensively.
|
|
48
|
+
*/
|
|
49
|
+
readonly stats: Record<string, Json> | null;
|
|
50
|
+
/** The stories the report covered, most important first. */
|
|
51
|
+
readonly articles: IntelReportArticleRef[];
|
|
52
|
+
}
|
|
53
|
+
/** Filter columns of `GET /intel_reports`, on top of {@link BASE_FILTER_COLUMNS}. */
|
|
54
|
+
export declare const INTEL_REPORT_FILTER_COLUMNS: readonly ["kind"];
|
|
55
|
+
/** Filters for {@link IntelReportsNamespace.list}. */
|
|
56
|
+
export interface ListIntelReportsParams extends ListParams<(typeof INTEL_REPORT_FILTER_COLUMNS)[number]> {
|
|
57
|
+
/**
|
|
58
|
+
* Narrow to one window, e.g. `"day"`. Sent as `exact_search[kind]`, so it is
|
|
59
|
+
* equality rather than a prefix match - `"6h"` will not also match `"6hx"`.
|
|
60
|
+
*
|
|
61
|
+
* Passing it through {@link ListParams.search} instead would be a
|
|
62
|
+
* partial match and would work too; `kind` is on this controller's
|
|
63
|
+
* `search_params` allowlist. Equality is what you want.
|
|
64
|
+
*/
|
|
65
|
+
readonly kind?: IntelReportKind;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* `GET /intel_reports` - the generated digests.
|
|
69
|
+
*
|
|
70
|
+
* Read-only plus a delete, for the same reason as the stories: reports come
|
|
71
|
+
* from `Intel::GenerateReportJob`. There is no way to ask for one to be
|
|
72
|
+
* generated over HTTP.
|
|
73
|
+
*/
|
|
74
|
+
export declare class IntelReportsNamespace extends Resource {
|
|
75
|
+
/**
|
|
76
|
+
* `GET /intel_reports` - your reports, newest window first.
|
|
77
|
+
*
|
|
78
|
+
* `period_end DESC` is applied by the controller; as with the stories, a
|
|
79
|
+
* `order` of your own becomes the PRIMARY key and this becomes the
|
|
80
|
+
* tie-breaker.
|
|
81
|
+
*
|
|
82
|
+
* `kind` is the only declared filter beyond the inherited three. Use
|
|
83
|
+
* {@link ListIntelReportsParams.kind}, which sends it as an exact match.
|
|
84
|
+
*
|
|
85
|
+
* @throws {OmsApiError} 403 `"Intel access is restricted."` outside the
|
|
86
|
+
* allowlist.
|
|
87
|
+
*/
|
|
88
|
+
list(params?: ListIntelReportsParams, options?: RequestOptions): Promise<Paginated<IntelReport>>;
|
|
89
|
+
/**
|
|
90
|
+
* `GET /intel_reports/:id` - the report with its body and its stories.
|
|
91
|
+
*
|
|
92
|
+
* @throws {OmsApiError} 404 when the report is not yours.
|
|
93
|
+
*/
|
|
94
|
+
get(id: Id, options?: RequestOptions): Promise<IntelReportDetail>;
|
|
95
|
+
/**
|
|
96
|
+
* `DELETE /intel_reports/:id`. `204`, empty body.
|
|
97
|
+
*
|
|
98
|
+
* The stories it cited are untouched - only the join rows go.
|
|
99
|
+
*
|
|
100
|
+
* A deleted report can come back: `GenerateReportJob` is keyed by the unique
|
|
101
|
+
* `(user, kind, period_end)` index, and deleting the row frees that key, so
|
|
102
|
+
* the next dispatcher pass over the same window will regenerate it. Delete a
|
|
103
|
+
* report to re-run it, not to suppress it.
|
|
104
|
+
*
|
|
105
|
+
* @throws {OmsApiError} 404 when the report is not yours.
|
|
106
|
+
*/
|
|
107
|
+
delete(id: Id, options?: RequestOptions): Promise<void>;
|
|
108
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/** Intel scripts: the fetchers. */
|
|
2
|
+
import { Resource } from "../../../http";
|
|
3
|
+
import type { ListParams } from "../../../listing";
|
|
4
|
+
import type { Id, Paginated, RequestOptions, Timestamp } from "../../../types";
|
|
5
|
+
/** Largest script body the server will store. */
|
|
6
|
+
export declare const INTEL_SCRIPT_MAX_CODE_BYTES: number;
|
|
7
|
+
/**
|
|
8
|
+
* A TypeScript fetcher that knows how to pull items out of one kind of feed.
|
|
9
|
+
*
|
|
10
|
+
* Runs in the `intel-runner` sidecar, inside a V8 isolate with nothing but the
|
|
11
|
+
* injected `ctx`. Two populations share this table:
|
|
12
|
+
*
|
|
13
|
+
* - **built-ins** (`builtin: true`, `user_id: null`, `slug` set) are managed by
|
|
14
|
+
* `Intel::BuiltinScripts`, visible to everyone, and immutable over HTTP;
|
|
15
|
+
* - **user scripts** (`builtin: false`, `user_id` set, `slug: null`) are yours.
|
|
16
|
+
*
|
|
17
|
+
* `viewable_by` is `builtin OR mine`, so a listing mixes the two. Check
|
|
18
|
+
* {@link builtin} before offering an edit affordance - see
|
|
19
|
+
* {@link IntelScriptsNamespace.update} for what happens if you do not.
|
|
20
|
+
*/
|
|
21
|
+
export interface IntelScript {
|
|
22
|
+
readonly id: Id;
|
|
23
|
+
readonly created_at: Timestamp;
|
|
24
|
+
readonly updated_at: Timestamp;
|
|
25
|
+
/** Up to 120 characters, whitespace-trimmed by the model. */
|
|
26
|
+
readonly name: string;
|
|
27
|
+
/** Stable handle, e.g. `"rss"`. Non-null for built-ins ONLY; always `null` for yours. */
|
|
28
|
+
readonly slug: string | null;
|
|
29
|
+
readonly description: string | null;
|
|
30
|
+
/** `true` for a platform script. Immutable, and not yours to delete. */
|
|
31
|
+
readonly builtin: boolean;
|
|
32
|
+
/** Owner. `null` exactly when {@link builtin} is `true`. */
|
|
33
|
+
readonly user_id: Id | null;
|
|
34
|
+
/**
|
|
35
|
+
* The source code - **only on the `:extended` view**.
|
|
36
|
+
*
|
|
37
|
+
* Only the `:extended` view carries `code`, so `get()`, `create()` and
|
|
38
|
+
* `update()` carry it and `list()` does not. That is a
|
|
39
|
+
* deliberate weight decision (a listing of 64 KiB bodies), not an oversight,
|
|
40
|
+
* and it is why this key is optional. A row from `list()` has it `undefined`;
|
|
41
|
+
* fetch the script by id when you actually need the body.
|
|
42
|
+
*/
|
|
43
|
+
readonly code?: string;
|
|
44
|
+
}
|
|
45
|
+
/** Filter columns of `GET /intel_scripts`, on top of {@link BASE_FILTER_COLUMNS}. */
|
|
46
|
+
export declare const INTEL_SCRIPT_FILTER_COLUMNS: readonly ["name", "builtin", "slug"];
|
|
47
|
+
/** Filters for {@link IntelScriptsNamespace.list}. */
|
|
48
|
+
export interface ListIntelScriptsParams extends ListParams<(typeof INTEL_SCRIPT_FILTER_COLUMNS)[number]> {
|
|
49
|
+
/**
|
|
50
|
+
* `true` for the platform scripts, `false` for yours. Omit for both - the
|
|
51
|
+
* listing scope is `builtin OR mine`, so both populations are mixed by
|
|
52
|
+
* default.
|
|
53
|
+
*/
|
|
54
|
+
readonly builtin?: boolean;
|
|
55
|
+
}
|
|
56
|
+
/** Arguments for {@link IntelScriptsNamespace.create}. */
|
|
57
|
+
export interface CreateIntelScriptInput {
|
|
58
|
+
/** Up to 120 characters. */
|
|
59
|
+
readonly name: string;
|
|
60
|
+
/** The body. Up to {@link INTEL_SCRIPT_MAX_CODE_BYTES}. */
|
|
61
|
+
readonly code: string;
|
|
62
|
+
readonly description?: string;
|
|
63
|
+
}
|
|
64
|
+
/** Arguments for {@link IntelScriptsNamespace.update}. */
|
|
65
|
+
export interface UpdateIntelScriptInput {
|
|
66
|
+
readonly name?: string;
|
|
67
|
+
readonly code?: string;
|
|
68
|
+
readonly description?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* `/intel_scripts` - the fetchers. Full CRUD over YOUR scripts, read-only over
|
|
72
|
+
* the platform's.
|
|
73
|
+
*/
|
|
74
|
+
export declare class IntelScriptsNamespace extends Resource {
|
|
75
|
+
/**
|
|
76
|
+
* `GET /intel_scripts` - the built-ins plus yours, mixed.
|
|
77
|
+
*
|
|
78
|
+
* **No `code`.** The body is on the `:extended` view only, so every row here
|
|
79
|
+
* has `code: undefined`. See {@link IntelScript.code}.
|
|
80
|
+
*
|
|
81
|
+
* Declared filters: `name`, `builtin`, `slug`, plus the inherited three.
|
|
82
|
+
* The controller sets no ordering, so the SDK sends `created_at:desc`.
|
|
83
|
+
*
|
|
84
|
+
* @throws {OmsApiError} 403 outside the allowlist.
|
|
85
|
+
*/
|
|
86
|
+
list(params?: ListIntelScriptsParams, options?: RequestOptions): Promise<Paginated<IntelScript>>;
|
|
87
|
+
/**
|
|
88
|
+
* `GET /intel_scripts/:id` - the script WITH its body.
|
|
89
|
+
*
|
|
90
|
+
* This is the only read that carries {@link IntelScript.code}. Works for a
|
|
91
|
+
* built-in too: they are visible to everyone, so this is how you read one
|
|
92
|
+
* before forking it.
|
|
93
|
+
*
|
|
94
|
+
* @throws {OmsApiError} 404 when the id is neither a built-in nor yours.
|
|
95
|
+
*/
|
|
96
|
+
get(id: Id, options?: RequestOptions): Promise<IntelScript>;
|
|
97
|
+
/**
|
|
98
|
+
* `POST /intel_scripts` - saves a fetcher. `201`, with `code`.
|
|
99
|
+
*
|
|
100
|
+
* The controller transpiles the body in the `intel-runner` sidecar BEFORE
|
|
101
|
+
* saving, so a syntax error surfaces here rather than at the first poll:
|
|
102
|
+
* `400 "Invalid script: <the compiler's message>"`.
|
|
103
|
+
*
|
|
104
|
+
* **The check is best-effort and fails OPEN.** `check_script!` rescues
|
|
105
|
+
* `Intel::RunnerClient::Error` and returns `nil`, so when the runner is down
|
|
106
|
+
* or unreachable the script saves unchecked and a `201` means only "stored".
|
|
107
|
+
* There is nothing on the response that distinguishes a checked save from an
|
|
108
|
+
* unchecked one. Treat a successful create as "it parses, probably", and
|
|
109
|
+
* confirm with {@link IntelSourcesNamespace.run} on a throwaway source.
|
|
110
|
+
*
|
|
111
|
+
* The check is a transpile, not an execution: it proves the code parses, not
|
|
112
|
+
* that it fetches anything.
|
|
113
|
+
*
|
|
114
|
+
* The created script is always yours - `builtin` is not on `create_params`,
|
|
115
|
+
* so it cannot be set - and up to
|
|
116
|
+
* {@link INTEL_SCRIPT_MAX_CODE_BYTES} long.
|
|
117
|
+
*
|
|
118
|
+
* Not retried by default: a replay creates a second script.
|
|
119
|
+
*/
|
|
120
|
+
create(input: CreateIntelScriptInput, options?: RequestOptions): Promise<IntelScript>;
|
|
121
|
+
/**
|
|
122
|
+
* `PATCH /intel_scripts/:id` - edits one of YOUR scripts. Answers with `code`.
|
|
123
|
+
*
|
|
124
|
+
* Same best-effort transpile check as {@link create}, and only when `code` is
|
|
125
|
+
* present in the body.
|
|
126
|
+
*
|
|
127
|
+
* **A built-in answers `401`, not `403`.** The body is
|
|
128
|
+
* `"You are not authorized to update this resource"` under a 401 status. That
|
|
129
|
+
* is an authorisation refusal wearing an authentication status code: do NOT
|
|
130
|
+
* let a generic 401 handler log the user out over it. Check
|
|
131
|
+
* {@link IntelScript.builtin} first and fork instead of editing.
|
|
132
|
+
*
|
|
133
|
+
* A live edit takes effect on the next poll of every source using this
|
|
134
|
+
* script; there is no versioning and no rollback.
|
|
135
|
+
*
|
|
136
|
+
* @throws {OmsApiError} 404 when the id is not visible to you; 401 for a
|
|
137
|
+
* built-in; 400 for a syntax error or an over-long body.
|
|
138
|
+
*/
|
|
139
|
+
update(id: Id, input: UpdateIntelScriptInput, options?: RequestOptions): Promise<IntelScript>;
|
|
140
|
+
/**
|
|
141
|
+
* `DELETE /intel_scripts/:id`. `204`, empty body.
|
|
142
|
+
*
|
|
143
|
+
* Refuses while any source still uses it, with
|
|
144
|
+
* `400 "Cannot delete record because dependent intel sources exist"`. Delete
|
|
145
|
+
* or repoint the sources first - {@link IntelSourcesNamespace.list} with
|
|
146
|
+
* `scriptId` finds them in one call.
|
|
147
|
+
*
|
|
148
|
+
* A built-in answers `401` with `"You are not authorized to destroy this
|
|
149
|
+
* resource"`, for the reason spelled out on {@link update}.
|
|
150
|
+
*/
|
|
151
|
+
delete(id: Id, options?: RequestOptions): Promise<void>;
|
|
152
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/** Intel sources: the feeds you follow. */
|
|
2
|
+
import { Resource } from "../../../http";
|
|
3
|
+
import type { ListParams } from "../../../listing";
|
|
4
|
+
import type { Id, Json, Paginated, RequestOptions, Timestamp } from "../../../types";
|
|
5
|
+
/** The three values a source's health can take. */
|
|
6
|
+
export declare const INTEL_SOURCE_HEALTHS: readonly ["unknown", "ok", "error"];
|
|
7
|
+
/** Health of a source's last run. `"unknown"` until it has ever run. */
|
|
8
|
+
export type IntelSourceHealth = (typeof INTEL_SOURCE_HEALTHS)[number];
|
|
9
|
+
/**
|
|
10
|
+
* Consecutive failures after which a source flips `enabled` to `false` by
|
|
11
|
+
* itself.
|
|
12
|
+
*
|
|
13
|
+
* Nothing turns it back on: a source that hit this stays off until someone
|
|
14
|
+
* `update()`s `enabled` back to `true`. That is what
|
|
15
|
+
* {@link IntelSource.consecutive_failures} is for - watch it, do not wait for
|
|
16
|
+
* an alert.
|
|
17
|
+
*/
|
|
18
|
+
export declare const INTEL_SOURCE_DISABLE_AFTER_FAILURES = 20;
|
|
19
|
+
/**
|
|
20
|
+
* A configured feed: a script plus the settings that script needs.
|
|
21
|
+
*
|
|
22
|
+
* A source is polled by `PollDispatcherJob` once every
|
|
23
|
+
* {@link poll_interval_minutes}, and each poll writes {@link IntelItem} rows
|
|
24
|
+
* that the analysis pipeline later turns into stories.
|
|
25
|
+
*/
|
|
26
|
+
export interface IntelSource {
|
|
27
|
+
readonly id: Id;
|
|
28
|
+
readonly created_at: Timestamp;
|
|
29
|
+
readonly updated_at: Timestamp;
|
|
30
|
+
/** Up to 200 characters, whitespace-trimmed by the model, unique per user. */
|
|
31
|
+
readonly name: string;
|
|
32
|
+
/**
|
|
33
|
+
* The script's own settings - a URL, a channel, a CSS selector. There is no
|
|
34
|
+
* schema: the backend permits `config: {}`, meaning an arbitrary object, and
|
|
35
|
+
* the SCRIPT decides what it reads out of it. What belongs in here is
|
|
36
|
+
* documented by the script, not by this API.
|
|
37
|
+
*/
|
|
38
|
+
readonly config: Record<string, Json>;
|
|
39
|
+
/** Which {@link IntelScript} fetches this source. */
|
|
40
|
+
readonly intel_script_id: Id;
|
|
41
|
+
/** Minutes between polls. Validated `in: 5..1440`. */
|
|
42
|
+
readonly poll_interval_minutes: number;
|
|
43
|
+
/**
|
|
44
|
+
* Whether the dispatcher will poll it.
|
|
45
|
+
*
|
|
46
|
+
* Can flip to `false` WITHOUT anyone asking: see
|
|
47
|
+
* {@link INTEL_SOURCE_DISABLE_AFTER_FAILURES}.
|
|
48
|
+
*/
|
|
49
|
+
readonly enabled: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Incremental cursor the script returned last time - a timestamp, an etag, a
|
|
52
|
+
* last-seen id, whatever that script uses. Opaque to everything but the
|
|
53
|
+
* script. Writable, so clearing it is how you force a full re-fetch.
|
|
54
|
+
*/
|
|
55
|
+
readonly cursor: string | null;
|
|
56
|
+
/** Result of the last run. `"unknown"` until it has run once. */
|
|
57
|
+
readonly health: IntelSourceHealth;
|
|
58
|
+
/** Failure message from the last failed run, truncated to 1000 characters. */
|
|
59
|
+
readonly last_error: string | null;
|
|
60
|
+
/** When the source last ran, successfully or not. */
|
|
61
|
+
readonly last_run_at: Timestamp | null;
|
|
62
|
+
/** When it last SUCCEEDED. A gap between the two is the thing to alert on. */
|
|
63
|
+
readonly last_success_at: Timestamp | null;
|
|
64
|
+
/** Reset to 0 on any success. See {@link INTEL_SOURCE_DISABLE_AFTER_FAILURES}. */
|
|
65
|
+
readonly consecutive_failures: number;
|
|
66
|
+
}
|
|
67
|
+
/** Filter columns of `GET /intel_sources`, on top of {@link BASE_FILTER_COLUMNS}. */
|
|
68
|
+
export declare const INTEL_SOURCE_FILTER_COLUMNS: readonly ["name", "health", "enabled", "intel_script_id"];
|
|
69
|
+
/** Filters for {@link IntelSourcesNamespace.list}. */
|
|
70
|
+
export interface ListIntelSourcesParams extends ListParams<(typeof INTEL_SOURCE_FILTER_COLUMNS)[number]> {
|
|
71
|
+
/** Only healthy / only broken feeds. Sent as `exact_search[health]`. */
|
|
72
|
+
readonly health?: IntelSourceHealth;
|
|
73
|
+
/** Only enabled, or only the ones that switched themselves off. */
|
|
74
|
+
readonly enabled?: boolean;
|
|
75
|
+
/** Every source driven by one script. */
|
|
76
|
+
readonly scriptId?: Id;
|
|
77
|
+
}
|
|
78
|
+
/** Arguments for {@link IntelSourcesNamespace.create}. */
|
|
79
|
+
export interface CreateIntelSourceInput {
|
|
80
|
+
/** Up to 200 characters, and unique among YOUR sources - a clash is a 400. */
|
|
81
|
+
readonly name: string;
|
|
82
|
+
/**
|
|
83
|
+
* The script that fetches it. Must be a built-in or one of yours;
|
|
84
|
+
* `script_visible_to_owner` rejects anything else with
|
|
85
|
+
* `400 "Intel script is not accessible"` rather than a 404, so this also
|
|
86
|
+
* tells you the id exists. Do not use it as an existence oracle.
|
|
87
|
+
*/
|
|
88
|
+
readonly intelScriptId: Id;
|
|
89
|
+
/** Whatever that script reads. Free-form; the API validates nothing in it. */
|
|
90
|
+
readonly config?: Record<string, Json>;
|
|
91
|
+
/** 5-1440. Defaults to 15 server-side. */
|
|
92
|
+
readonly pollIntervalMinutes?: number;
|
|
93
|
+
/** Defaults to `true`. Create it disabled if you want to configure first. */
|
|
94
|
+
readonly enabled?: boolean;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Arguments for {@link IntelSourcesNamespace.update}.
|
|
98
|
+
*
|
|
99
|
+
* One key wider than the create form: `cursor` is updatable and not creatable.
|
|
100
|
+
*/
|
|
101
|
+
export interface UpdateIntelSourceInput {
|
|
102
|
+
readonly name?: string;
|
|
103
|
+
readonly intelScriptId?: Id;
|
|
104
|
+
/**
|
|
105
|
+
* REPLACES the whole object; there is no merge. `assign_attributes` writes
|
|
106
|
+
* the JSON column wholesale, so sending `{ url: "..." }` to a source that
|
|
107
|
+
* also had a `selector` drops the selector. Read the source, spread, write.
|
|
108
|
+
*/
|
|
109
|
+
readonly config?: Record<string, Json>;
|
|
110
|
+
readonly pollIntervalMinutes?: number;
|
|
111
|
+
/** Set back to `true` to revive a source that disabled itself. */
|
|
112
|
+
readonly enabled?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* The incremental cursor. Set it to `null` to force the next poll to start
|
|
115
|
+
* from the beginning - which for most scripts means re-fetching everything.
|
|
116
|
+
*
|
|
117
|
+
* `null` here is a JSON body `null`, not the query-string sentinel: bodies
|
|
118
|
+
* never carry `\b`.
|
|
119
|
+
*/
|
|
120
|
+
readonly cursor?: string | null;
|
|
121
|
+
}
|
|
122
|
+
/** What `POST /intel_sources/:id/run` answers with. The whole body. */
|
|
123
|
+
export interface IntelSourceRunAccepted {
|
|
124
|
+
/** Always `true`. The job was enqueued; nothing has been fetched yet. */
|
|
125
|
+
readonly queued: boolean;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* `/intel_sources` - the feeds you have configured. Full CRUD, plus a manual
|
|
129
|
+
* run.
|
|
130
|
+
*/
|
|
131
|
+
export declare class IntelSourcesNamespace extends Resource {
|
|
132
|
+
/**
|
|
133
|
+
* `GET /intel_sources` - your feeds.
|
|
134
|
+
*
|
|
135
|
+
* Declared filters: `name`, `health`, `enabled`, `intel_script_id`, plus the
|
|
136
|
+
* inherited `id`, `created_at`, `updated_at`. The controller sets NO ordering
|
|
137
|
+
* of its own, so a listing with no `order` is in whatever order Postgres
|
|
138
|
+
* returns rows - which is not stable across pages. The SDK therefore sends
|
|
139
|
+
* `created_at:desc` unless you say otherwise.
|
|
140
|
+
*
|
|
141
|
+
* A good health check in one call: `list({ health: "error" })`.
|
|
142
|
+
*
|
|
143
|
+
* @throws {OmsApiError} 403 outside the allowlist.
|
|
144
|
+
*/
|
|
145
|
+
list(params?: ListIntelSourcesParams, options?: RequestOptions): Promise<Paginated<IntelSource>>;
|
|
146
|
+
/**
|
|
147
|
+
* `GET /intel_sources/:id`.
|
|
148
|
+
*
|
|
149
|
+
* There are no `:extended` extras, so this is exactly the shape a listing
|
|
150
|
+
* row has. Fetching one adds nothing but a round trip;
|
|
151
|
+
* prefer finding it in {@link list} when you already have the page.
|
|
152
|
+
*
|
|
153
|
+
* @throws {OmsApiError} 404 when the source is not yours.
|
|
154
|
+
*/
|
|
155
|
+
get(id: Id, options?: RequestOptions): Promise<IntelSource>;
|
|
156
|
+
/**
|
|
157
|
+
* `POST /intel_sources` - configures a feed. `201`.
|
|
158
|
+
*
|
|
159
|
+
* The source starts `health: "unknown"` and is not polled immediately: the
|
|
160
|
+
* dispatcher picks it up on its next pass, or you can force it with
|
|
161
|
+
* {@link run}.
|
|
162
|
+
*
|
|
163
|
+
* Three ways this fails with a 400 and a bare-string body:
|
|
164
|
+
*
|
|
165
|
+
* - `"Name has already been taken"` - names are unique per user;
|
|
166
|
+
* - `"Intel script is not accessible"` - the script is neither a built-in nor
|
|
167
|
+
* yours. This is a 400 rather than a 404, so it does not tell you whether
|
|
168
|
+
* the id exists;
|
|
169
|
+
* - `"Source limit reached (N)"` - you are at
|
|
170
|
+
* {@link IntelConfig.max_sources}. Raise it with
|
|
171
|
+
* {@link IntelConfigNamespace.update} if the ceiling is yours to raise.
|
|
172
|
+
*
|
|
173
|
+
* Not retried by default: a replayed `POST` after a lost response would fail
|
|
174
|
+
* the uniqueness check rather than duplicate the row, but it would report
|
|
175
|
+
* that failure as if the first attempt had never worked.
|
|
176
|
+
*/
|
|
177
|
+
create(input: CreateIntelSourceInput, options?: RequestOptions): Promise<IntelSource>;
|
|
178
|
+
/**
|
|
179
|
+
* `PATCH /intel_sources/:id`.
|
|
180
|
+
*
|
|
181
|
+
* Note what is NOT writable: `health`, `last_error`, `last_run_at`,
|
|
182
|
+
* `last_success_at` and `consecutive_failures` are not on `update_params`, so
|
|
183
|
+
* you cannot clear a source's failure history by hand. Only a successful run
|
|
184
|
+
* resets it (`register_success!`). Re-enabling a source that disabled itself
|
|
185
|
+
* therefore leaves `consecutive_failures` at 20 until the next success - do
|
|
186
|
+
* not read that field as "currently failing".
|
|
187
|
+
*
|
|
188
|
+
* {@link UpdateIntelSourceInput.config} replaces the whole object.
|
|
189
|
+
*
|
|
190
|
+
* @throws {OmsApiError} 404 when the source is not yours; 400 with the
|
|
191
|
+
* validation sentence otherwise.
|
|
192
|
+
*/
|
|
193
|
+
update(id: Id, input: UpdateIntelSourceInput, options?: RequestOptions): Promise<IntelSource>;
|
|
194
|
+
/**
|
|
195
|
+
* `DELETE /intel_sources/:id`. `204`, empty body.
|
|
196
|
+
*
|
|
197
|
+
* Destructive well beyond the row: `has_many :intel_items, dependent:
|
|
198
|
+
* :destroy` takes every raw item this source ever produced, and the stories
|
|
199
|
+
* built from them lose their citations
|
|
200
|
+
* ({@link IntelArticleDetail.sources} shrinks, {@link IntelArticle.n_sources}
|
|
201
|
+
* with it) while the stories themselves stay. Disabling is almost always what
|
|
202
|
+
* you meant: `update(id, { enabled: false })`.
|
|
203
|
+
*
|
|
204
|
+
* @throws {OmsApiError} 404 when the source is not yours.
|
|
205
|
+
*/
|
|
206
|
+
delete(id: Id, options?: RequestOptions): Promise<void>;
|
|
207
|
+
/**
|
|
208
|
+
* `POST /intel_sources/:id/run` - polls the source now instead of waiting
|
|
209
|
+
* for its interval. `202 {"queued":true}`.
|
|
210
|
+
*
|
|
211
|
+
* **It enqueues; it does not fetch.** The answer arrives before anything has
|
|
212
|
+
* happened, and it says nothing about whether the poll will succeed. To see
|
|
213
|
+
* the outcome, re-read the source and watch {@link IntelSource.last_run_at},
|
|
214
|
+
* {@link IntelSource.health} and {@link IntelSource.last_error}. There is no
|
|
215
|
+
* job id and nothing to wait on.
|
|
216
|
+
*
|
|
217
|
+
* Three sharp edges:
|
|
218
|
+
*
|
|
219
|
+
* - it runs a source even when {@link IntelSource.enabled} is `false`. The
|
|
220
|
+
* action does not look at the flag, so this is also how you test a feed you
|
|
221
|
+
* have deliberately switched off;
|
|
222
|
+
* - it is authorised by VISIBILITY only. The action does its own `find_by`
|
|
223
|
+
* inside `viewable_by` and never calls `updatable_by?` - which happens to
|
|
224
|
+
* be the same set here, since sources are only ever visible to their owner;
|
|
225
|
+
* - it has **no bucket of its own**. It rides the general 600-per-minute
|
|
226
|
+
* ceiling, so a loop can enqueue hundreds of `FetchSourceJob`s into the
|
|
227
|
+
* `syncs` queue in seconds and starve everything else on it. Call it on a
|
|
228
|
+
* user gesture; never in a poll loop.
|
|
229
|
+
*
|
|
230
|
+
* Not retried by default: a replay enqueues a second fetch.
|
|
231
|
+
*
|
|
232
|
+
* @throws {OmsApiError} 404 `"Resource not found"` when the source is not
|
|
233
|
+
* yours.
|
|
234
|
+
*/
|
|
235
|
+
run(id: Id, options?: RequestOptions): Promise<IntelSourceRunAccepted>;
|
|
236
|
+
}
|