@larc-iu/plaid-client 0.2.0-alpha.3 → 0.2.0-alpha.32
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 +39 -0
- package/package.json +13 -6
- package/src/apiAnnotations.d.ts +508 -0
- package/src/apiAnnotations.js +543 -0
- package/src/apiDocuments.d.ts +569 -0
- package/src/apiDocuments.js +551 -0
- package/src/apiLayers.d.ts +369 -0
- package/src/apiLayers.js +222 -0
- package/src/apiMessages.d.ts +293 -0
- package/src/apiMessages.js +265 -0
- package/src/apiPeople.d.ts +626 -0
- package/src/apiPeople.js +698 -0
- package/src/apiProject.d.ts +761 -0
- package/src/apiProject.js +774 -0
- package/src/apiServer.d.ts +457 -0
- package/src/apiServer.js +424 -0
- package/src/apiVocab.d.ts +456 -0
- package/src/apiVocab.js +425 -0
- package/src/batch.d.ts +54 -0
- package/src/batch.js +323 -0
- package/src/batchRef.d.ts +30 -0
- package/src/batchRef.js +128 -0
- package/src/client.d.ts +1321 -0
- package/src/client.js +743 -0
- package/src/codepoint.d.ts +94 -0
- package/src/codepoint.js +131 -1
- package/src/constraints.d.ts +85 -0
- package/src/constraints.js +112 -0
- package/src/created.d.ts +2 -0
- package/src/created.js +29 -0
- package/src/documentLock.d.ts +172 -0
- package/src/documentLock.js +384 -0
- package/src/entryForms.d.ts +68 -0
- package/src/entryForms.js +164 -0
- package/src/events.d.ts +60 -0
- package/src/events.js +271 -0
- package/src/families.d.ts +349 -0
- package/src/families.js +396 -0
- package/src/http.d.ts +233 -0
- package/src/http.js +809 -93
- package/src/ids.d.ts +26 -0
- package/src/ids.js +96 -0
- package/src/index.d.ts +101 -0
- package/src/index.js +183 -2105
- package/src/metadataOps.d.ts +15 -0
- package/src/metadataOps.js +124 -0
- package/src/operations.d.ts +36 -0
- package/src/operations.js +164 -0
- package/src/pagination.d.ts +49 -0
- package/src/pagination.js +20 -53
- package/src/provenance.d.ts +243 -0
- package/src/provenance.js +458 -36
- package/src/replayed.d.ts +3 -0
- package/src/replayed.js +31 -0
- package/src/requester.d.ts +60 -0
- package/src/requester.js +74 -0
- package/src/roles.d.ts +104 -0
- package/src/roles.js +64 -2
- package/src/serviceSchema.d.ts +337 -0
- package/src/serviceSchema.js +177 -60
- package/src/services.d.ts +319 -0
- package/src/services.js +742 -58
- package/src/sse.d.ts +30 -0
- package/src/sse.js +80 -3
- package/src/testing.d.ts +128 -0
- package/src/testing.js +379 -0
- package/src/textEdits.d.ts +59 -0
- package/src/textEdits.js +234 -0
- package/src/transforms.d.ts +25 -0
- package/src/transforms.js +11 -1
- package/src/types.d.ts +867 -0
- package/src/types.js +663 -0
- package/index.d.ts +0 -532
package/src/requester.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Who asked for a service run, named in what the run leaves behind.
|
|
2
|
+
//
|
|
3
|
+
// A plain service writes with its own token, so the History entry of a run
|
|
4
|
+
// reads "by <operator> (via <token>)" and the person who pressed the button is
|
|
5
|
+
// recorded nowhere. Core tells every service who asked (`requesterId` in the
|
|
6
|
+
// request data), and every app's services put that person in the History
|
|
7
|
+
// label and in what they store:
|
|
8
|
+
//
|
|
9
|
+
// AnCast adjudication against lunch, requested by second
|
|
10
|
+
//
|
|
11
|
+
// This is the JS twin of `plaid_client.workflows.requester`, for a service
|
|
12
|
+
// authored with `serve`. The wording and the stored key are the same.
|
|
13
|
+
//
|
|
14
|
+
// The name is the requester's display name, which any signed-in user may
|
|
15
|
+
// read. When it cannot be read the id stands in for it, and with no requester
|
|
16
|
+
// at all the label is left as it was and nothing is stored.
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The person who asked for one service run. Both fields are null when nobody
|
|
20
|
+
* asked.
|
|
21
|
+
* @typedef {object} Requester
|
|
22
|
+
* @property {string | null} id
|
|
23
|
+
* @property {string | null} name
|
|
24
|
+
* @property {(text: string) => string} label `"<text>, requested by <name>"`,
|
|
25
|
+
* or `text` when nobody asked.
|
|
26
|
+
* @property {() => ({id: string, name: string | null} | null)} record
|
|
27
|
+
* `{ id, name }` for a stored report, or null when nobody asked.
|
|
28
|
+
* @property {(detail?: Record<string, any>) => Record<string, any>} detail A
|
|
29
|
+
* machine stamp's `provDetail` with `requestedBy: <id>` added.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/** The key a run's stored record names its requester under. */
|
|
33
|
+
export const REQUESTED_BY = /** @type {const} */ ("requestedBy");
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The person who asked for one run: `id` is their account (their email),
|
|
37
|
+
* `name` how they are shown. Both are null when nobody asked.
|
|
38
|
+
* @param {string | null} [id]
|
|
39
|
+
* @param {string | null} [name]
|
|
40
|
+
* @returns {Requester}
|
|
41
|
+
*/
|
|
42
|
+
export function makeRequester(id = null, name = null) {
|
|
43
|
+
return {
|
|
44
|
+
id,
|
|
45
|
+
name,
|
|
46
|
+
/** A History label with the requester named, or `text` when nobody asked. */
|
|
47
|
+
label: (text) => (name ? `${text}, requested by ${name}` : text),
|
|
48
|
+
/** `{ id, name }` for a stored report, or null when nobody asked. */
|
|
49
|
+
record: () => (id ? { id, name } : null),
|
|
50
|
+
/** A machine stamp's `provDetail` with the requester's id added. */
|
|
51
|
+
detail: (detail = {}) => ({ ...(detail || {}), ...(id ? { [REQUESTED_BY]: id } : {}) }),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The requester of one request, from the `requesterId` core put in its data,
|
|
57
|
+
* with their display name read through `client`.
|
|
58
|
+
* @param {{users: {get(id: string): Promise<any>}}} client - A PlaidClient (only `users.get` is used)
|
|
59
|
+
* @param {any} data - The request data a `serve` handler receives
|
|
60
|
+
* @returns {Promise<Requester>}
|
|
61
|
+
*/
|
|
62
|
+
export async function requesterOf(client, data) {
|
|
63
|
+
const id = data && typeof data === "object" ? data.requesterId || null : null;
|
|
64
|
+
if (!id) return makeRequester();
|
|
65
|
+
let name = null;
|
|
66
|
+
try {
|
|
67
|
+
name = (await client.users.get(id))?.displayName || null;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
// The id is always there to fall back on, so a failed read costs the
|
|
70
|
+
// label nothing but the nicer name.
|
|
71
|
+
console.warn(`Could not read the requester ${id}: ${error?.message || error}`);
|
|
72
|
+
}
|
|
73
|
+
return makeRequester(id, name || id);
|
|
74
|
+
}
|
package/src/roles.d.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a project records research telemetry: `config.plaid.research.telemetry`
|
|
3
|
+
* is exactly true.
|
|
4
|
+
* @param {object} [config] a project's `config` object
|
|
5
|
+
* @returns {boolean}
|
|
6
|
+
*/
|
|
7
|
+
export function readResearchTelemetry(config?: object): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* The role recorded on a layer's `config`, or null if none.
|
|
10
|
+
* @param {object} [config] a layer's `config` object
|
|
11
|
+
* @returns {string|null}
|
|
12
|
+
*/
|
|
13
|
+
export function readRole(config?: object): string | null;
|
|
14
|
+
/**
|
|
15
|
+
* The ignored-tokens rule on a word layer's `config` (see
|
|
16
|
+
* `IGNORED_TOKENS_KEY`), or null if none. The one reader of the key in JS.
|
|
17
|
+
* @param {object} [config] a token layer's `config` object
|
|
18
|
+
* @returns {{type: string, whitelist?: string[], blacklist?: string[]}|null}
|
|
19
|
+
*/
|
|
20
|
+
export function readIgnoredTokens(config?: object): {
|
|
21
|
+
type: string;
|
|
22
|
+
whitelist?: string[];
|
|
23
|
+
blacklist?: string[];
|
|
24
|
+
} | null;
|
|
25
|
+
/**
|
|
26
|
+
* The first layer in `layers` carrying the given role, or null. The single
|
|
27
|
+
* "find a layer by its role" primitive — apps build their named finders
|
|
28
|
+
* (findWordTokenLayer, etc.) on top of this.
|
|
29
|
+
* @template {{config?: object}} T
|
|
30
|
+
* @param {T[] | undefined} layers
|
|
31
|
+
* @param {string} role
|
|
32
|
+
* @returns {T | null}
|
|
33
|
+
*/
|
|
34
|
+
export function findByRole<T extends {
|
|
35
|
+
config?: object;
|
|
36
|
+
}>(layers: T[] | undefined, role: string): T | null;
|
|
37
|
+
/**
|
|
38
|
+
* Shared layer-role vocabulary for cross-app interoperability.
|
|
39
|
+
*
|
|
40
|
+
* Apps that share a Plaid project agree on the *substrate* — the text and token
|
|
41
|
+
* layers — by tagging each shared layer with a ROLE under the reserved `plaid`
|
|
42
|
+
* config namespace (`config.plaid.role`, a scalar). Annotations stay private to
|
|
43
|
+
* each app under that app's own namespace. See the Plaid manual, "Layer
|
|
44
|
+
* Interoperability". The role inventory is small and fixed:
|
|
45
|
+
*
|
|
46
|
+
* baseline the primary text layer
|
|
47
|
+
* sentence sentence token layer
|
|
48
|
+
* word orthographic-word token layer (CoNLL-U "token")
|
|
49
|
+
* syntactic-word grammatical words below the word (CoNLL-U "word" / MWT splits)
|
|
50
|
+
* morpheme morpheme token layer
|
|
51
|
+
* time-alignment media-timeline token layer
|
|
52
|
+
*
|
|
53
|
+
* Only these values are understood across apps; an app may store any string but
|
|
54
|
+
* loses interoperability for unknown values.
|
|
55
|
+
*/
|
|
56
|
+
/** The reserved config namespace for cross-app conventions. */
|
|
57
|
+
export const PLAID_NAMESPACE: "plaid";
|
|
58
|
+
/** The config key, under `plaid`, holding a layer's role. */
|
|
59
|
+
export const ROLE_KEY: "role";
|
|
60
|
+
/** The fixed role inventory. */
|
|
61
|
+
/**
|
|
62
|
+
* Layer config key naming the metadata keys a token born of a SPLIT inherits
|
|
63
|
+
* from the token it came from. Plaid honors it without knowing what the keys
|
|
64
|
+
* mean; see the manual's `Metadata Preserved Across a Split`. An app declares
|
|
65
|
+
* it so that a split in ANY app, including one that has never heard of these
|
|
66
|
+
* keys, does not silently drop them.
|
|
67
|
+
*/
|
|
68
|
+
export const PRESERVE_ON_SPLIT_KEY: "preserveOnSplit";
|
|
69
|
+
/**
|
|
70
|
+
* Layer config key (true): a space typed inside a token of the text's words
|
|
71
|
+
* splits it, the token going on the half sharing more letters with it.
|
|
72
|
+
* Declared on a word layer another app shares, it holds for the whole text.
|
|
73
|
+
* See the manual's `Changing a text's body`.
|
|
74
|
+
*/
|
|
75
|
+
export const SPLIT_ON_SPACE_KEY: "splitOnSpace";
|
|
76
|
+
/**
|
|
77
|
+
* Word layer config key holding the ignored-tokens rule,
|
|
78
|
+
* `{type, whitelist, blacklist}`: under `type: 'unicodePunctuation'` a word made
|
|
79
|
+
* only of punctuation is ignored and each one-character entry of `whitelist` is
|
|
80
|
+
* a letter, under `type: 'blacklist'` the entries of `blacklist` are the words
|
|
81
|
+
* ignored and its one-character entries the only characters that part words.
|
|
82
|
+
* Plaid's text rules and the built-in tokenizer read it. See the manual's
|
|
83
|
+
* `Changing a text's body`.
|
|
84
|
+
*/
|
|
85
|
+
export const IGNORED_TOKENS_KEY: "ignoredTokens";
|
|
86
|
+
/**
|
|
87
|
+
* Project config key (false to hide): whether the project's tartan shows beside
|
|
88
|
+
* its name. Absent means shown.
|
|
89
|
+
*/
|
|
90
|
+
export const TARTAN_KEY: "tartan";
|
|
91
|
+
/**
|
|
92
|
+
* Project config key holding the research settings, `{telemetry}`. Client
|
|
93
|
+
* events are recorded only while `telemetry` is true. See the manual's
|
|
94
|
+
* `Research telemetry`.
|
|
95
|
+
*/
|
|
96
|
+
export const RESEARCH_KEY: "research";
|
|
97
|
+
export const ROLES: Readonly<{
|
|
98
|
+
BASELINE: "baseline";
|
|
99
|
+
SENTENCE: "sentence";
|
|
100
|
+
WORD: "word";
|
|
101
|
+
SYNTACTIC_WORD: "syntactic-word";
|
|
102
|
+
MORPHEME: "morpheme";
|
|
103
|
+
TIME_ALIGNMENT: "time-alignment";
|
|
104
|
+
}>;
|
package/src/roles.js
CHANGED
|
@@ -25,6 +25,57 @@ export const PLAID_NAMESPACE = 'plaid';
|
|
|
25
25
|
export const ROLE_KEY = 'role';
|
|
26
26
|
|
|
27
27
|
/** The fixed role inventory. */
|
|
28
|
+
/**
|
|
29
|
+
* Layer config key naming the metadata keys a token born of a SPLIT inherits
|
|
30
|
+
* from the token it came from. Plaid honors it without knowing what the keys
|
|
31
|
+
* mean; see the manual's `Metadata Preserved Across a Split`. An app declares
|
|
32
|
+
* it so that a split in ANY app, including one that has never heard of these
|
|
33
|
+
* keys, does not silently drop them.
|
|
34
|
+
*/
|
|
35
|
+
export const PRESERVE_ON_SPLIT_KEY = 'preserveOnSplit';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Layer config key (true): a space typed inside a token of the text's words
|
|
39
|
+
* splits it, the token going on the half sharing more letters with it.
|
|
40
|
+
* Declared on a word layer another app shares, it holds for the whole text.
|
|
41
|
+
* See the manual's `Changing a text's body`.
|
|
42
|
+
*/
|
|
43
|
+
export const SPLIT_ON_SPACE_KEY = 'splitOnSpace';
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Word layer config key holding the ignored-tokens rule,
|
|
47
|
+
* `{type, whitelist, blacklist}`: under `type: 'unicodePunctuation'` a word made
|
|
48
|
+
* only of punctuation is ignored and each one-character entry of `whitelist` is
|
|
49
|
+
* a letter, under `type: 'blacklist'` the entries of `blacklist` are the words
|
|
50
|
+
* ignored and its one-character entries the only characters that part words.
|
|
51
|
+
* Plaid's text rules and the built-in tokenizer read it. See the manual's
|
|
52
|
+
* `Changing a text's body`.
|
|
53
|
+
*/
|
|
54
|
+
export const IGNORED_TOKENS_KEY = 'ignoredTokens';
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Project config key (false to hide): whether the project's tartan shows beside
|
|
58
|
+
* its name. Absent means shown.
|
|
59
|
+
*/
|
|
60
|
+
export const TARTAN_KEY = 'tartan';
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Project config key holding the research settings, `{telemetry}`. Client
|
|
64
|
+
* events are recorded only while `telemetry` is true. See the manual's
|
|
65
|
+
* `Research telemetry`.
|
|
66
|
+
*/
|
|
67
|
+
export const RESEARCH_KEY = 'research';
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Whether a project records research telemetry: `config.plaid.research.telemetry`
|
|
71
|
+
* is exactly true.
|
|
72
|
+
* @param {object} [config] a project's `config` object
|
|
73
|
+
* @returns {boolean}
|
|
74
|
+
*/
|
|
75
|
+
export function readResearchTelemetry(config) {
|
|
76
|
+
return config?.[PLAID_NAMESPACE]?.[RESEARCH_KEY]?.telemetry === true;
|
|
77
|
+
}
|
|
78
|
+
|
|
28
79
|
export const ROLES = Object.freeze({
|
|
29
80
|
BASELINE: 'baseline',
|
|
30
81
|
SENTENCE: 'sentence',
|
|
@@ -44,13 +95,24 @@ export function readRole(config) {
|
|
|
44
95
|
return v == null ? null : v;
|
|
45
96
|
}
|
|
46
97
|
|
|
98
|
+
/**
|
|
99
|
+
* The ignored-tokens rule on a word layer's `config` (see
|
|
100
|
+
* `IGNORED_TOKENS_KEY`), or null if none. The one reader of the key in JS.
|
|
101
|
+
* @param {object} [config] a token layer's `config` object
|
|
102
|
+
* @returns {{type: string, whitelist?: string[], blacklist?: string[]}|null}
|
|
103
|
+
*/
|
|
104
|
+
export function readIgnoredTokens(config) {
|
|
105
|
+
return config?.[PLAID_NAMESPACE]?.[IGNORED_TOKENS_KEY] ?? null;
|
|
106
|
+
}
|
|
107
|
+
|
|
47
108
|
/**
|
|
48
109
|
* The first layer in `layers` carrying the given role, or null. The single
|
|
49
110
|
* "find a layer by its role" primitive — apps build their named finders
|
|
50
111
|
* (findWordTokenLayer, etc.) on top of this.
|
|
51
|
-
* @
|
|
112
|
+
* @template {{config?: object}} T
|
|
113
|
+
* @param {T[] | undefined} layers
|
|
52
114
|
* @param {string} role
|
|
53
|
-
* @returns {
|
|
115
|
+
* @returns {T | null}
|
|
54
116
|
*/
|
|
55
117
|
export function findByRole(layers, role) {
|
|
56
118
|
return (layers || []).find(l => readRole(l?.config) === role) || null;
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One choice for an `enum` or `multiselect` service parameter.
|
|
3
|
+
* @typedef {{value: string, label: string}} ServiceParamOption
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* A single user-controllable argument a service advertises.
|
|
7
|
+
* @typedef {object} ServiceParam
|
|
8
|
+
* @property {string} key Key the value is sent under in the request payload.
|
|
9
|
+
* @property {string} label
|
|
10
|
+
* @property {"string" | "number" | "boolean" | "enum" | "multiselect" | "field"} type
|
|
11
|
+
* @property {string} [description]
|
|
12
|
+
* @property {any} [default]
|
|
13
|
+
* @property {boolean} [required]
|
|
14
|
+
* @property {ServiceParamOption[]} [options] Required for `enum` and `multiselect`.
|
|
15
|
+
* @property {number} [min] `number` only.
|
|
16
|
+
* @property {number} [max] `number` only.
|
|
17
|
+
* @property {number} [step] `number` only.
|
|
18
|
+
* @property {boolean} [slider] `number` only: render as a slider to drag
|
|
19
|
+
* rather than a box to type in.
|
|
20
|
+
* @property {string} [placeholder] `string` only.
|
|
21
|
+
* @property {boolean} [multiline] `string` only.
|
|
22
|
+
* @property {"Sentence" | "Word" | "Morpheme"} [scope] `field` only: the
|
|
23
|
+
* scope of the project's annotation fields the value names one of. A
|
|
24
|
+
* `field` value is a string everywhere else.
|
|
25
|
+
* @property {string} [role] `field` only: the lexicon role whose paired field,
|
|
26
|
+
* or the sentence role whose field, fills the parameter when nothing else
|
|
27
|
+
* does.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* A service's standardized self-description (lives in `extras`).
|
|
31
|
+
* @typedef {object} ServiceExtras
|
|
32
|
+
* @property {number} [schemaVersion]
|
|
33
|
+
* @property {string[]} [tasks] Tasks this service serves, from the TASKS vocabulary.
|
|
34
|
+
* @property {string} [summary] Rich human description (Markdown), beyond the
|
|
35
|
+
* short `description`.
|
|
36
|
+
* @property {ServiceParam[]} [parameters] Ordered parameter schema, rendered
|
|
37
|
+
* into a form by the UI.
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* What a service says about itself when it registers.
|
|
41
|
+
* @typedef {object} ServiceInfo
|
|
42
|
+
* @property {string} serviceId
|
|
43
|
+
* @property {string} serviceName
|
|
44
|
+
* @property {string} description
|
|
45
|
+
* @property {ServiceExtras & Record<string, any>} [extras]
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* A service as `messages.discoverServices` lists it.
|
|
49
|
+
* @typedef {object} DiscoveredService
|
|
50
|
+
* @property {string} serviceId
|
|
51
|
+
* @property {string} serviceName
|
|
52
|
+
* @property {string} description
|
|
53
|
+
* @property {ServiceExtras & Record<string, any>} extras
|
|
54
|
+
* @property {boolean} online True while the service holds an open request
|
|
55
|
+
* channel, false for a previously seen offline service.
|
|
56
|
+
* @property {string | null} [lastSeenAt] ISO-8601 stamp of when the service
|
|
57
|
+
* was last seen alive, or null when never stored.
|
|
58
|
+
* @property {string} [runnerName] Online services only: the display name of
|
|
59
|
+
* the account that runs the service.
|
|
60
|
+
* @property {boolean} [runByYou] Online services only: the caller runs it.
|
|
61
|
+
* @property {boolean} [servesYou] Online services only: it would take the
|
|
62
|
+
* caller's requests on this project. A delegating service serves members
|
|
63
|
+
* other than its runner only where the runner is a maintainer or an admin.
|
|
64
|
+
*/
|
|
65
|
+
/**
|
|
66
|
+
* Does `service` serve `task`, as its declared `extras.tasks` says?
|
|
67
|
+
* @param {{serviceId?: string, extras?: {tasks?: string[]}}} service
|
|
68
|
+
* @param {string} task one of TASKS
|
|
69
|
+
* @returns {boolean}
|
|
70
|
+
*/
|
|
71
|
+
export function servesTask(service: {
|
|
72
|
+
serviceId?: string;
|
|
73
|
+
extras?: {
|
|
74
|
+
tasks?: string[];
|
|
75
|
+
};
|
|
76
|
+
}, task: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* The discovered services that serve `task`.
|
|
79
|
+
* @param {DiscoveredService[] | undefined} services result of client.messages.discoverServices()
|
|
80
|
+
* @param {string} task one of TASKS
|
|
81
|
+
* @returns {DiscoveredService[]}
|
|
82
|
+
*/
|
|
83
|
+
export function filterServicesByTask(services: DiscoveredService[] | undefined, task: string): DiscoveredService[];
|
|
84
|
+
/**
|
|
85
|
+
* The parameter schema a service declares (ordered array), or [].
|
|
86
|
+
* @param {{extras?: {parameters?: ServiceParam[]}}} service
|
|
87
|
+
* @returns {ServiceParam[]}
|
|
88
|
+
*/
|
|
89
|
+
export function getParamSchema(service: {
|
|
90
|
+
extras?: {
|
|
91
|
+
parameters?: ServiceParam[];
|
|
92
|
+
};
|
|
93
|
+
}): ServiceParam[];
|
|
94
|
+
/**
|
|
95
|
+
* A service's human summary: the rich `extras.summary`, else the short
|
|
96
|
+
* `description`, else ''.
|
|
97
|
+
* @param {{description?: string, extras?: {summary?: string}}} service
|
|
98
|
+
* @returns {string}
|
|
99
|
+
*/
|
|
100
|
+
export function getServiceSummary(service: {
|
|
101
|
+
description?: string;
|
|
102
|
+
extras?: {
|
|
103
|
+
summary?: string;
|
|
104
|
+
};
|
|
105
|
+
}): string;
|
|
106
|
+
/**
|
|
107
|
+
* Default values keyed by param key — the initial form state.
|
|
108
|
+
* @param {ServiceParam[]} schema getParamSchema(service)
|
|
109
|
+
* @returns {Record<string, any>} { [key]: defaultValue }
|
|
110
|
+
*/
|
|
111
|
+
export function buildDefaultValues(schema: ServiceParam[]): Record<string, any>;
|
|
112
|
+
export function coerceParamValues(schema: any, raw: any): {
|
|
113
|
+
values: {};
|
|
114
|
+
errors: {};
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Service self-description: tasks, summary, and a parameter schema.
|
|
118
|
+
*
|
|
119
|
+
* The service framework's transport carries an opaque `extras` JSON map on every
|
|
120
|
+
* registered service (see services.js). This module standardizes what a service
|
|
121
|
+
* advertises in that map so apps can, at a fixed integration point (a "task"
|
|
122
|
+
* like tokenize / parse / transcribe):
|
|
123
|
+
*
|
|
124
|
+
* 1. SELECT one of several services that serve the task,
|
|
125
|
+
* 2. let the user SPECIFY arguments the service declares, and
|
|
126
|
+
* 3. show the user a service-provided SUMMARY.
|
|
127
|
+
*
|
|
128
|
+
* Shape of a service's `extras` (camelCase here; Python services author the
|
|
129
|
+
* snake_case equivalent and the client transform converts it — see the Plaid
|
|
130
|
+
* manual, "Describing a service"):
|
|
131
|
+
*
|
|
132
|
+
* {
|
|
133
|
+
* schemaVersion: 1,
|
|
134
|
+
* tasks: ["tokenize"], // controlled vocab (TASKS)
|
|
135
|
+
* summary: "## markdown …", // rich human description
|
|
136
|
+
* parameters: [ // ordered; rendered into a form
|
|
137
|
+
* { key, label, type, description?, default?, required?,
|
|
138
|
+
* options?: [{value, label}], // enum / multiselect
|
|
139
|
+
* min?, max?, step?, slider?, // number (slider: drag, don't type)
|
|
140
|
+
* placeholder?, multiline?, // string
|
|
141
|
+
* scope?, role? } // field: 'Sentence' | 'Word' | 'Morpheme'
|
|
142
|
+
* ]
|
|
143
|
+
* }
|
|
144
|
+
*
|
|
145
|
+
* A `field` parameter names one of the project's annotation fields at its
|
|
146
|
+
* `scope`. A UI that knows the project offers those fields to choose from; to
|
|
147
|
+
* everything here, and to a UI that does not, it is a string. Its optional
|
|
148
|
+
* `role` names a lexicon role ("gloss") or, at Sentence scope, a sentence
|
|
149
|
+
* field's role ("translation", "literalTranslation", "note"): a UI that knows
|
|
150
|
+
* the project fills the parameter with the one field at `scope` whose stored
|
|
151
|
+
* Lexicon field holds that role, or whose stored role it is. A field is never
|
|
152
|
+
* chosen by its name.
|
|
153
|
+
*
|
|
154
|
+
* A parameter's `key` is a string VALUE, so it passes over the wire verbatim;
|
|
155
|
+
* the UI sends `{ [param.key]: value }` in the request data. Declare each `key`
|
|
156
|
+
* in your service's own convention (Python: snake_case; JS: camelCase) and read
|
|
157
|
+
* it back under that same key — request data is recased symmetrically, so a
|
|
158
|
+
* snake_case key round-trips unchanged to a JS UI and back.
|
|
159
|
+
*/
|
|
160
|
+
/**
|
|
161
|
+
* The controlled task vocabulary — the fixed integration-point goals.
|
|
162
|
+
*
|
|
163
|
+
* Whatever the task, a service should stamp everything it creates with the
|
|
164
|
+
* provenance convention (see ./provenance.js: stampInferred(serviceSource(id)))
|
|
165
|
+
* so UIs can distinguish machine output until a human verifies it, and should
|
|
166
|
+
* honor the write contract: never destroy human-made or verified material
|
|
167
|
+
* without an explicit `overwrite` parameter. See the manual, "Provenance".
|
|
168
|
+
*/
|
|
169
|
+
export const TASKS: Readonly<{
|
|
170
|
+
TOKENIZE: "tokenize";
|
|
171
|
+
PARSE: "parse";
|
|
172
|
+
TRANSCRIBE: "transcribe";
|
|
173
|
+
/** Create vocab links for unlinked tokens. */
|
|
174
|
+
LINK_VOCAB: "link-vocab";
|
|
175
|
+
/** Propose an interlinear analysis (morpheme segmentation + glosses) for words. */
|
|
176
|
+
ANALYZE: "analyze";
|
|
177
|
+
/**
|
|
178
|
+
* Draft a meaning representation graph over the sentences of a document,
|
|
179
|
+
* for correction by hand. The request names a `scope` ('document' or
|
|
180
|
+
* 'sentence'), a `sentence` number when the scope is one sentence, and
|
|
181
|
+
* `overwrite`. See plaid-umr's drafting services.
|
|
182
|
+
*
|
|
183
|
+
* Apart from `analyze` on purpose. A task is the CONTRACT a spot offers a
|
|
184
|
+
* service against, and these two share almost none of it: an analyze
|
|
185
|
+
* request names the three token layers plus the language and metalanguage,
|
|
186
|
+
* and writes morphemes and glosses. Both claimed `analyze` for
|
|
187
|
+
* a while, so every app offering an analyze spot offered the other app's
|
|
188
|
+
* services, which could not answer the request they would have been given.
|
|
189
|
+
*/
|
|
190
|
+
DRAFT_GRAPH: "draft-graph";
|
|
191
|
+
/** Propose a free translation for each sentence. */
|
|
192
|
+
TRANSLATE: "translate";
|
|
193
|
+
/**
|
|
194
|
+
* Propose time-aligned speech regions for a recording.
|
|
195
|
+
*
|
|
196
|
+
* The odd one out: a detect-speech service RETURNS its regions and writes
|
|
197
|
+
* nothing, because a time-aligned segment is a stretch of the baseline and
|
|
198
|
+
* cannot exist without text. The response carries
|
|
199
|
+
* `{segments: [{timeBegin, timeEnd, speaker?}]}` (seconds), and the app
|
|
200
|
+
* holds them as proposals until a person types into one.
|
|
201
|
+
*/
|
|
202
|
+
DETECT_SPEECH: "detect-speech";
|
|
203
|
+
/** A conversational assistant over a project (chat turns; see plaid-agent). */
|
|
204
|
+
ASSIST: "assist";
|
|
205
|
+
/**
|
|
206
|
+
* Score one document's annotation against another document's of the same
|
|
207
|
+
* text (two annotators' copies), writing a report on the scored document's
|
|
208
|
+
* metadata and never an annotation. The request names the other document
|
|
209
|
+
* as `against`. See plaid-umr's AnCast service.
|
|
210
|
+
*/
|
|
211
|
+
COMPARE: "compare";
|
|
212
|
+
}>;
|
|
213
|
+
/**
|
|
214
|
+
* One choice for an `enum` or `multiselect` service parameter.
|
|
215
|
+
*/
|
|
216
|
+
export type ServiceParamOption = {
|
|
217
|
+
value: string;
|
|
218
|
+
label: string;
|
|
219
|
+
};
|
|
220
|
+
/**
|
|
221
|
+
* A single user-controllable argument a service advertises.
|
|
222
|
+
*/
|
|
223
|
+
export type ServiceParam = {
|
|
224
|
+
/**
|
|
225
|
+
* Key the value is sent under in the request payload.
|
|
226
|
+
*/
|
|
227
|
+
key: string;
|
|
228
|
+
label: string;
|
|
229
|
+
type: "string" | "number" | "boolean" | "enum" | "multiselect" | "field";
|
|
230
|
+
description?: string;
|
|
231
|
+
default?: any;
|
|
232
|
+
required?: boolean;
|
|
233
|
+
/**
|
|
234
|
+
* Required for `enum` and `multiselect`.
|
|
235
|
+
*/
|
|
236
|
+
options?: ServiceParamOption[];
|
|
237
|
+
/**
|
|
238
|
+
* `number` only.
|
|
239
|
+
*/
|
|
240
|
+
min?: number;
|
|
241
|
+
/**
|
|
242
|
+
* `number` only.
|
|
243
|
+
*/
|
|
244
|
+
max?: number;
|
|
245
|
+
/**
|
|
246
|
+
* `number` only.
|
|
247
|
+
*/
|
|
248
|
+
step?: number;
|
|
249
|
+
/**
|
|
250
|
+
* `number` only: render as a slider to drag
|
|
251
|
+
* rather than a box to type in.
|
|
252
|
+
*/
|
|
253
|
+
slider?: boolean;
|
|
254
|
+
/**
|
|
255
|
+
* `string` only.
|
|
256
|
+
*/
|
|
257
|
+
placeholder?: string;
|
|
258
|
+
/**
|
|
259
|
+
* `string` only.
|
|
260
|
+
*/
|
|
261
|
+
multiline?: boolean;
|
|
262
|
+
/**
|
|
263
|
+
* `field` only: the
|
|
264
|
+
* scope of the project's annotation fields the value names one of. A
|
|
265
|
+
* `field` value is a string everywhere else.
|
|
266
|
+
*/
|
|
267
|
+
scope?: "Sentence" | "Word" | "Morpheme";
|
|
268
|
+
/**
|
|
269
|
+
* `field` only: the lexicon role whose paired field,
|
|
270
|
+
* or the sentence role whose field, fills the parameter when nothing else
|
|
271
|
+
* does.
|
|
272
|
+
*/
|
|
273
|
+
role?: string;
|
|
274
|
+
};
|
|
275
|
+
/**
|
|
276
|
+
* A service's standardized self-description (lives in `extras`).
|
|
277
|
+
*/
|
|
278
|
+
export type ServiceExtras = {
|
|
279
|
+
schemaVersion?: number;
|
|
280
|
+
/**
|
|
281
|
+
* Tasks this service serves, from the TASKS vocabulary.
|
|
282
|
+
*/
|
|
283
|
+
tasks?: string[];
|
|
284
|
+
/**
|
|
285
|
+
* Rich human description (Markdown), beyond the
|
|
286
|
+
* short `description`.
|
|
287
|
+
*/
|
|
288
|
+
summary?: string;
|
|
289
|
+
/**
|
|
290
|
+
* Ordered parameter schema, rendered
|
|
291
|
+
* into a form by the UI.
|
|
292
|
+
*/
|
|
293
|
+
parameters?: ServiceParam[];
|
|
294
|
+
};
|
|
295
|
+
/**
|
|
296
|
+
* What a service says about itself when it registers.
|
|
297
|
+
*/
|
|
298
|
+
export type ServiceInfo = {
|
|
299
|
+
serviceId: string;
|
|
300
|
+
serviceName: string;
|
|
301
|
+
description: string;
|
|
302
|
+
extras?: ServiceExtras & Record<string, any>;
|
|
303
|
+
};
|
|
304
|
+
/**
|
|
305
|
+
* A service as `messages.discoverServices` lists it.
|
|
306
|
+
*/
|
|
307
|
+
export type DiscoveredService = {
|
|
308
|
+
serviceId: string;
|
|
309
|
+
serviceName: string;
|
|
310
|
+
description: string;
|
|
311
|
+
extras: ServiceExtras & Record<string, any>;
|
|
312
|
+
/**
|
|
313
|
+
* True while the service holds an open request
|
|
314
|
+
* channel, false for a previously seen offline service.
|
|
315
|
+
*/
|
|
316
|
+
online: boolean;
|
|
317
|
+
/**
|
|
318
|
+
* ISO-8601 stamp of when the service
|
|
319
|
+
* was last seen alive, or null when never stored.
|
|
320
|
+
*/
|
|
321
|
+
lastSeenAt?: string | null;
|
|
322
|
+
/**
|
|
323
|
+
* Online services only: the display name of
|
|
324
|
+
* the account that runs the service.
|
|
325
|
+
*/
|
|
326
|
+
runnerName?: string;
|
|
327
|
+
/**
|
|
328
|
+
* Online services only: the caller runs it.
|
|
329
|
+
*/
|
|
330
|
+
runByYou?: boolean;
|
|
331
|
+
/**
|
|
332
|
+
* Online services only: it would take the
|
|
333
|
+
* caller's requests on this project. A delegating service serves members
|
|
334
|
+
* other than its runner only where the runner is a maintainer or an admin.
|
|
335
|
+
*/
|
|
336
|
+
servesYou?: boolean;
|
|
337
|
+
};
|