@iyulab/lowline-form 0.9.0 → 0.11.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 +17 -1
- package/dist/bundle/lowline-form.bundle.js +14 -10
- package/dist/client.d.ts +21 -2
- package/dist/client.js +6 -3
- package/dist/draft.d.ts +7 -3
- package/dist/draft.js +7 -3
- package/dist/headless.d.ts +1 -1
- package/dist/lowline-form.d.ts +5 -3
- package/dist/lowline-form.js +5 -4
- package/dist/session.d.ts +6 -2
- package/dist/session.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# `<lowline-form>`
|
|
2
2
|
|
|
3
3
|
A formdown form whose decided fields are suggested from the records people confirmed, talking to a Lowline host's
|
|
4
|
-
routes (
|
|
4
|
+
routes — the contract at the end of this page, which a host implements over the engine (the .NET reference host is
|
|
5
|
+
[`samples/aspnet`](../../samples/aspnet)).
|
|
5
6
|
|
|
6
7
|
```html
|
|
7
8
|
<lowline-form src="/lowline" form="intake" record="r-17"></lowline-form>
|
|
@@ -43,3 +44,18 @@ npm ci
|
|
|
43
44
|
npm test
|
|
44
45
|
npm run bundle # one file with Lit and formdown inside, in dist/bundle
|
|
45
46
|
```
|
|
47
|
+
|
|
48
|
+
## The routes a host serves
|
|
49
|
+
|
|
50
|
+
Under the prefix the host mounted them at (`src`):
|
|
51
|
+
|
|
52
|
+
| Route | Takes | Answers |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| `POST {form}/propose` | `{ "id", "values" }` — the record so far | per open decided field: the suggestion, what it rests on, its `promise`, or why there is none |
|
|
55
|
+
| `POST {form}/settle` | `{ "id", "saved", "draft" }` — no `saved` with `Saved` | `{ "id", "settledAt" }`; 400 for a value the form cannot hold, and nothing is learned |
|
|
56
|
+
| `GET {form}/report` | — | per decided field: the thresholds chosen, how many records they were chosen on (`chosenOn`), and what the replay of the records saw at them |
|
|
57
|
+
| `POST {form}/fill` | `{ "values", "text", "attachments" }` — `attachments`, optional: what the person showed, each `{ "mediaType", "data" (base64), "name" }`; `text` may be empty when something is shown | the model's values as suggestions; 400 for data that is not base64; 404 saying so without a model |
|
|
58
|
+
| `POST {form}/judge` | `{ "id", "values" }` | the model's judgements for the fields the records could not answer; 404 saying so without a model |
|
|
59
|
+
|
|
60
|
+
A form not defined is 404. Each request's memory space and allowed choices come from the host, never from the request
|
|
61
|
+
body. The shapes are the engine's own wire shapes: in .NET, `LowlineJson` serializes them.
|
|
@@ -31,8 +31,8 @@ var e = class {
|
|
|
31
31
|
inBatch(e) {
|
|
32
32
|
this.batch = e;
|
|
33
33
|
}
|
|
34
|
-
report(e, { layer: t, promise: n }) {
|
|
35
|
-
t ? e.layer = t : delete e.layer, n === void 0 ? delete e.promise : e.promise = n;
|
|
34
|
+
report(e, { layer: t, promise: n, score: r }) {
|
|
35
|
+
t ? e.layer = t : delete e.layer, n === void 0 ? delete e.promise : e.promise = n, r === void 0 ? delete e.score : e.score = r;
|
|
36
36
|
}
|
|
37
37
|
decline(e) {
|
|
38
38
|
let t = this.fields[e];
|
|
@@ -164,7 +164,7 @@ var a = {
|
|
|
164
164
|
}
|
|
165
165
|
draw(e) {
|
|
166
166
|
let { field: t, suggestion: n } = e;
|
|
167
|
-
return n ? this.drawn.has(t) ? this.draft.held(t) !== void 0 : (n.origin ?? "decider") !== "decider" || (n.fit ?? "exact") !== "exact" ? !1 : (this.drawn.add(t), this.rate > 0 && this.rate <= 1 && this.random() < this.rate && (this.draft.hold(t, this.rate, {
|
|
167
|
+
return n ? this.drawn.has(t) ? this.draft.held(t) !== void 0 : e.several || (n.origin ?? "decider") !== "decider" || (n.fit ?? "exact") !== "exact" ? !1 : (this.drawn.add(t), this.rate > 0 && this.rate <= 1 && this.random() < this.rate && (this.draft.hold(t, this.rate, {
|
|
168
168
|
...e,
|
|
169
169
|
suggestion: n
|
|
170
170
|
}), !0)) : !1;
|
|
@@ -207,8 +207,12 @@ var l = class extends Error {
|
|
|
207
207
|
draft: n
|
|
208
208
|
});
|
|
209
209
|
}
|
|
210
|
-
fill(e, t, n) {
|
|
211
|
-
return this.post(e, "fill", {
|
|
210
|
+
fill(e, t, n, r) {
|
|
211
|
+
return this.post(e, "fill", r?.length ? {
|
|
212
|
+
values: t,
|
|
213
|
+
text: n,
|
|
214
|
+
attachments: r
|
|
215
|
+
} : {
|
|
212
216
|
values: t,
|
|
213
217
|
text: n
|
|
214
218
|
});
|
|
@@ -11274,11 +11278,11 @@ var zl = 300, $ = class extends Je {
|
|
|
11274
11278
|
composed: !0
|
|
11275
11279
|
})), n;
|
|
11276
11280
|
}
|
|
11277
|
-
async fill(e) {
|
|
11278
|
-
let
|
|
11279
|
-
if (!
|
|
11280
|
-
let
|
|
11281
|
-
|
|
11281
|
+
async fill(e, t) {
|
|
11282
|
+
let n = this.session;
|
|
11283
|
+
if (!n || !this.form) return;
|
|
11284
|
+
let r = await this.client.fill(this.form, this.values(), e, t);
|
|
11285
|
+
n === this.session && (this.fieldStates = n.applyFill(r), this.formdown && (this.formdown.fieldStates = this.fieldStates));
|
|
11282
11286
|
}
|
|
11283
11287
|
async ask() {
|
|
11284
11288
|
let e = this.session;
|
package/dist/client.d.ts
CHANGED
|
@@ -5,6 +5,14 @@ export declare class LowlineError extends Error {
|
|
|
5
5
|
readonly status: number;
|
|
6
6
|
constructor(status: number, message: string);
|
|
7
7
|
}
|
|
8
|
+
/** Something a person showed rather than wrote — a photo, a scan — sent to the host's model with a fill request. */
|
|
9
|
+
export interface Attachment {
|
|
10
|
+
/** Its media type, such as `image/jpeg` or `application/pdf`. */
|
|
11
|
+
mediaType: string;
|
|
12
|
+
/** Its bytes, base64. */
|
|
13
|
+
data: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
}
|
|
8
16
|
/** A threshold chosen on a replay of the settled records, and what the replay saw at it. */
|
|
9
17
|
export interface ThresholdChoice {
|
|
10
18
|
threshold: number;
|
|
@@ -39,8 +47,16 @@ export interface FieldReport {
|
|
|
39
47
|
/** For a free text field, the threshold for one, two, … characters typed (`null` where none was right often enough). */
|
|
40
48
|
typed?: (ThresholdChoice | null)[];
|
|
41
49
|
coarse?: ThresholdChoice;
|
|
50
|
+
/** For a field with a coarse level, the threshold at which its class is suggested from the similar records layer. */
|
|
51
|
+
coarseSimilar?: ThresholdChoice;
|
|
42
52
|
similar?: ThresholdChoice;
|
|
43
53
|
similarOffered: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* For a judgement from outside the records: the score from which it is trusted, chosen from the cases it answered and
|
|
56
|
+
* people settled (its `promise` is the precision to expect of the next answers at or above it); absent while too few
|
|
57
|
+
* cases are settled for one to stand.
|
|
58
|
+
*/
|
|
59
|
+
judgement?: ThresholdChoice;
|
|
44
60
|
promiseOver: number;
|
|
45
61
|
/** How many checks — answers held back while a person wrote the value — are among the records. */
|
|
46
62
|
checks: number;
|
|
@@ -66,8 +82,11 @@ export declare class LowlineClient {
|
|
|
66
82
|
id: string;
|
|
67
83
|
settledAt: string;
|
|
68
84
|
}>;
|
|
69
|
-
/**
|
|
70
|
-
|
|
85
|
+
/**
|
|
86
|
+
* What the host's model makes of `text` and of what the person showed (`attachments`) for the fields of record values
|
|
87
|
+
* still empty — 404 when the host gave no model.
|
|
88
|
+
*/
|
|
89
|
+
fill(form: string, values: Values, text: string, attachments?: Attachment[]): Promise<Proposal[]>;
|
|
71
90
|
/**
|
|
72
91
|
* What the host's model judged for the decided fields of record `id` the records could not answer
|
|
73
92
|
* (`needs-judgement`) — 404 when the host gave no model.
|
package/dist/client.js
CHANGED
|
@@ -27,9 +27,12 @@ export class LowlineClient {
|
|
|
27
27
|
settle(form, id, draft, saved) {
|
|
28
28
|
return this.post(form, 'settle', { id, saved, draft });
|
|
29
29
|
}
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
/**
|
|
31
|
+
* What the host's model makes of `text` and of what the person showed (`attachments`) for the fields of record values
|
|
32
|
+
* still empty — 404 when the host gave no model.
|
|
33
|
+
*/
|
|
34
|
+
fill(form, values, text, attachments) {
|
|
35
|
+
return this.post(form, 'fill', attachments?.length ? { values, text, attachments } : { values, text });
|
|
33
36
|
}
|
|
34
37
|
/**
|
|
35
38
|
* What the host's model judged for the decided fields of record `id` the records could not answer
|
package/dist/draft.d.ts
CHANGED
|
@@ -10,10 +10,14 @@ export interface Suggestion {
|
|
|
10
10
|
}
|
|
11
11
|
/** The layer of the decider an answer came from. */
|
|
12
12
|
export type Layer = 'key' | 'similar' | 'judgement';
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* What the host knows of the answer it shows or holds back, beyond its value: the layer that gave it, what it promised,
|
|
15
|
+
* and — for a judgement from outside the records — the score it gave it on its own scale.
|
|
16
|
+
*/
|
|
14
17
|
export interface Reported {
|
|
15
18
|
layer?: Layer | null;
|
|
16
19
|
promise?: number;
|
|
20
|
+
score?: number;
|
|
17
21
|
}
|
|
18
22
|
interface Track extends Reported {
|
|
19
23
|
shown?: Suggestion;
|
|
@@ -32,7 +36,7 @@ interface Track extends Reported {
|
|
|
32
36
|
*
|
|
33
37
|
* Written as the engine reads it: `{ opened, fields: { field: { shown, declined, held } } }`, and — only what was
|
|
34
38
|
* reported — `opened_at`, `saved_at` (milliseconds on one steady clock), `arrival` (the fields in the order their values
|
|
35
|
-
* arrived), `by` and `batch`, and in a field `layer`, `promise`, `at` and `withheld`.
|
|
39
|
+
* arrived), `by` and `batch`, and in a field `layer`, `promise`, `score`, `at` and `withheld`.
|
|
36
40
|
*/
|
|
37
41
|
export declare class Draft {
|
|
38
42
|
readonly opened: Values;
|
|
@@ -48,7 +52,7 @@ export declare class Draft {
|
|
|
48
52
|
show(field: string, suggestion: Suggestion, reported?: Reported): void;
|
|
49
53
|
/**
|
|
50
54
|
* The field's answer is held back for a check, drawn with `probability`: what the person settles is checked.
|
|
51
|
-
* `withheld` is the answer not shown, with its layer and
|
|
55
|
+
* `withheld` is the answer not shown, with its layer, promise and score, for the record to say what was held back.
|
|
52
56
|
*/
|
|
53
57
|
hold(field: string, probability: number, withheld?: {
|
|
54
58
|
suggestion: Suggestion;
|
package/dist/draft.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Written as the engine reads it: `{ opened, fields: { field: { shown, declined, held } } }`, and — only what was
|
|
8
8
|
* reported — `opened_at`, `saved_at` (milliseconds on one steady clock), `arrival` (the fields in the order their values
|
|
9
|
-
* arrived), `by` and `batch`, and in a field `layer`, `promise`, `at` and `withheld`.
|
|
9
|
+
* arrived), `by` and `batch`, and in a field `layer`, `promise`, `score`, `at` and `withheld`.
|
|
10
10
|
*/
|
|
11
11
|
export class Draft {
|
|
12
12
|
/** A record opened holding `values` — none for a new one. Empty values are left out. */
|
|
@@ -27,7 +27,7 @@ export class Draft {
|
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
29
|
* The field's answer is held back for a check, drawn with `probability`: what the person settles is checked.
|
|
30
|
-
* `withheld` is the answer not shown, with its layer and
|
|
30
|
+
* `withheld` is the answer not shown, with its layer, promise and score, for the record to say what was held back.
|
|
31
31
|
*/
|
|
32
32
|
hold(field, probability, withheld) {
|
|
33
33
|
if (!(probability > 0 && probability <= 1))
|
|
@@ -68,7 +68,7 @@ export class Draft {
|
|
|
68
68
|
inBatch(id) {
|
|
69
69
|
this.batch = id;
|
|
70
70
|
}
|
|
71
|
-
report(track, { layer, promise }) {
|
|
71
|
+
report(track, { layer, promise, score }) {
|
|
72
72
|
if (layer)
|
|
73
73
|
track.layer = layer;
|
|
74
74
|
else
|
|
@@ -77,6 +77,10 @@ export class Draft {
|
|
|
77
77
|
track.promise = promise;
|
|
78
78
|
else
|
|
79
79
|
delete track.promise;
|
|
80
|
+
if (score !== undefined)
|
|
81
|
+
track.score = score;
|
|
82
|
+
else
|
|
83
|
+
delete track.score;
|
|
80
84
|
}
|
|
81
85
|
/** The person turned down the suggestion in view; false, changing nothing, when none was shown. */
|
|
82
86
|
decline(field) {
|
package/dist/headless.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { Draft, valuesOf, type Suggestion, type Value, type Values } from './draft.js';
|
|
2
2
|
export { Session, englishStrings, type Abstain, type Basis, type FieldState, type Proposal, type Round, type Strings } from './session.js';
|
|
3
|
-
export { LowlineClient, LowlineError, type FieldReport, type ThresholdChoice } from './client.js';
|
|
3
|
+
export { LowlineClient, LowlineError, type Attachment, type FieldReport, type ThresholdChoice } from './client.js';
|
package/dist/lowline-form.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
2
|
import '@formdown/ui';
|
|
3
|
+
import { type Attachment } from './client.js';
|
|
3
4
|
import { type Values } from './draft.js';
|
|
4
5
|
import { type Strings } from './session.js';
|
|
5
6
|
/**
|
|
@@ -61,10 +62,11 @@ export declare class LowlineForm extends LitElement {
|
|
|
61
62
|
}>;
|
|
62
63
|
private settleWith;
|
|
63
64
|
/**
|
|
64
|
-
* Fills the record from `text` — what the person wrote
|
|
65
|
-
* value it gives is offered in its field for the person to take. Nothing is put in
|
|
65
|
+
* Fills the record from `text` — what the person wrote — and `attachments` — what they showed: a photo, a scan —
|
|
66
|
+
* through the host's model: each value it gives is offered in its field for the person to take. Nothing is put in
|
|
67
|
+
* on its own.
|
|
66
68
|
*/
|
|
67
|
-
fill(text: string): Promise<void>;
|
|
69
|
+
fill(text: string, attachments?: Attachment[]): Promise<void>;
|
|
68
70
|
/** Asks again what to show for the decided fields still open. */
|
|
69
71
|
ask(): Promise<void>;
|
|
70
72
|
/**
|
package/dist/lowline-form.js
CHANGED
|
@@ -127,14 +127,15 @@ let LowlineForm = class LowlineForm extends LitElement {
|
|
|
127
127
|
return saved;
|
|
128
128
|
}
|
|
129
129
|
/**
|
|
130
|
-
* Fills the record from `text` — what the person wrote
|
|
131
|
-
* value it gives is offered in its field for the person to take. Nothing is put in
|
|
130
|
+
* Fills the record from `text` — what the person wrote — and `attachments` — what they showed: a photo, a scan —
|
|
131
|
+
* through the host's model: each value it gives is offered in its field for the person to take. Nothing is put in
|
|
132
|
+
* on its own.
|
|
132
133
|
*/
|
|
133
|
-
async fill(text) {
|
|
134
|
+
async fill(text, attachments) {
|
|
134
135
|
const session = this.session;
|
|
135
136
|
if (!session || !this.form)
|
|
136
137
|
return;
|
|
137
|
-
const proposals = await this.client.fill(this.form, this.values(), text);
|
|
138
|
+
const proposals = await this.client.fill(this.form, this.values(), text, attachments);
|
|
138
139
|
if (session !== this.session)
|
|
139
140
|
return;
|
|
140
141
|
this.fieldStates = session.applyFill(proposals);
|
package/dist/session.d.ts
CHANGED
|
@@ -27,10 +27,14 @@ export interface Proposal {
|
|
|
27
27
|
together?: string | null;
|
|
28
28
|
/**
|
|
29
29
|
* How often an answer of this kind for this field has been right — the replay's precision at the threshold the
|
|
30
|
-
* suggestion was held to. Absent with no suggestion, for a
|
|
31
|
-
* were chosen.
|
|
30
|
+
* suggestion was held to. Absent with no suggestion, for a value from elsewhere, for a judgement until the score it
|
|
31
|
+
* is trusted from was chosen from the records, and before thresholds were chosen.
|
|
32
32
|
*/
|
|
33
33
|
promise?: number;
|
|
34
|
+
/** For a judgement from outside the records: the score it gave the suggestion, on its own scale. The draft keeps it. */
|
|
35
|
+
score?: number;
|
|
36
|
+
/** Whether the field takes several values: it is settled as a set, which cannot be a check, so none is drawn for it. */
|
|
37
|
+
several?: boolean;
|
|
34
38
|
}
|
|
35
39
|
/** What a field shows, as formdown's `fieldStates` takes it. */
|
|
36
40
|
export interface FieldState {
|
package/dist/session.js
CHANGED
|
@@ -181,7 +181,7 @@ export class Session {
|
|
|
181
181
|
return false;
|
|
182
182
|
if (this.drawn.has(field))
|
|
183
183
|
return this.draft.held(field) !== undefined;
|
|
184
|
-
const checkable = (suggestion.origin ?? 'decider') === 'decider' && (suggestion.fit ?? 'exact') === 'exact';
|
|
184
|
+
const checkable = !proposal.several && (suggestion.origin ?? 'decider') === 'decider' && (suggestion.fit ?? 'exact') === 'exact';
|
|
185
185
|
if (!checkable)
|
|
186
186
|
return false;
|
|
187
187
|
this.drawn.add(field);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iyulab/lowline-form",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "The Lowline form element: a formdown form whose decided fields are suggested from the records people confirmed, talking to a Lowline host's routes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|