deepclause-sdk 0.2.2 → 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 +86 -3
- package/dist/agent.d.ts +17 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +148 -42
- package/dist/agent.js.map +1 -1
- package/dist/cli/config.d.ts +12 -12
- package/dist/cli/repl.d.ts +13 -1
- package/dist/cli/repl.d.ts.map +1 -1
- package/dist/cli/repl.js +177 -5
- package/dist/cli/repl.js.map +1 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +4 -0
- package/dist/cli/run.js.map +1 -1
- package/dist/forms/index.d.ts +3 -0
- package/dist/forms/index.d.ts.map +1 -0
- package/dist/forms/index.js +3 -0
- package/dist/forms/index.js.map +1 -0
- package/dist/forms/registry.d.ts +119 -0
- package/dist/forms/registry.d.ts.map +1 -0
- package/dist/forms/registry.js +256 -0
- package/dist/forms/registry.js.map +1 -0
- package/dist/forms/spec.d.ts +193 -0
- package/dist/forms/spec.d.ts.map +1 -0
- package/dist/forms/spec.js +295 -0
- package/dist/forms/spec.js.map +1 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/prolog/loader.d.ts +18 -0
- package/dist/prolog/loader.d.ts.map +1 -1
- package/dist/prolog/loader.js +26 -1
- package/dist/prolog/loader.js.map +1 -1
- package/dist/prolog-src/deepclause_mi.pl +786 -40
- package/dist/repl/agent.d.ts +11 -0
- package/dist/repl/agent.d.ts.map +1 -1
- package/dist/repl/agent.js +23 -9
- package/dist/repl/agent.js.map +1 -1
- package/dist/repl/form-widget.d.ts +56 -0
- package/dist/repl/form-widget.d.ts.map +1 -0
- package/dist/repl/form-widget.js +289 -0
- package/dist/repl/form-widget.js.map +1 -0
- package/dist/repl/harness-tools.d.ts +4 -1
- package/dist/repl/harness-tools.d.ts.map +1 -1
- package/dist/repl/harness-tools.js +15 -58
- package/dist/repl/harness-tools.js.map +1 -1
- package/dist/repl/history.d.ts +24 -1
- package/dist/repl/history.d.ts.map +1 -1
- package/dist/repl/history.js +76 -8
- package/dist/repl/history.js.map +1 -1
- package/dist/repl/index.d.ts +20 -2
- package/dist/repl/index.d.ts.map +1 -1
- package/dist/repl/index.js +9 -0
- package/dist/repl/index.js.map +1 -1
- package/dist/repl/process-backend.d.ts +2 -2
- package/dist/repl/process-backend.d.ts.map +1 -1
- package/dist/repl/process-executor.d.ts +11 -2
- package/dist/repl/process-executor.d.ts.map +1 -1
- package/dist/repl/process-executor.js +67 -18
- package/dist/repl/process-executor.js.map +1 -1
- package/dist/repl/process-worker.d.ts +35 -4
- package/dist/repl/process-worker.d.ts.map +1 -1
- package/dist/repl/process-worker.js +78 -38
- package/dist/repl/process-worker.js.map +1 -1
- package/dist/repl/processes.d.ts +4 -0
- package/dist/repl/processes.d.ts.map +1 -1
- package/dist/repl/processes.js +20 -0
- package/dist/repl/processes.js.map +1 -1
- package/dist/repl/render.d.ts +17 -0
- package/dist/repl/render.d.ts.map +1 -1
- package/dist/repl/render.js +60 -0
- package/dist/repl/render.js.map +1 -1
- package/dist/repl/session.d.ts +143 -7
- package/dist/repl/session.d.ts.map +1 -1
- package/dist/repl/session.js +317 -20
- package/dist/repl/session.js.map +1 -1
- package/dist/repl/tui/form-view.d.ts +17 -0
- package/dist/repl/tui/form-view.d.ts.map +1 -0
- package/dist/repl/tui/form-view.js +25 -0
- package/dist/repl/tui/form-view.js.map +1 -0
- package/dist/repl/tui/renderer.d.ts +4 -0
- package/dist/repl/tui/renderer.d.ts.map +1 -1
- package/dist/repl/tui/renderer.js +12 -0
- package/dist/repl/tui/renderer.js.map +1 -1
- package/dist/repl/worker-host.d.ts +16 -2
- package/dist/repl/worker-host.d.ts.map +1 -1
- package/dist/repl/worker-host.js +38 -6
- package/dist/repl/worker-host.js.map +1 -1
- package/dist/repl/worker-protocol.d.ts +14 -0
- package/dist/repl/worker-protocol.d.ts.map +1 -1
- package/dist/repl/worker-protocol.js +8 -1
- package/dist/repl/worker-protocol.js.map +1 -1
- package/dist/runner.d.ts +69 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +381 -44
- package/dist/runner.js.map +1 -1
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +12 -0
- package/dist/sdk.js.map +1 -1
- package/dist/system/assets/docs/AGENT_PROMPT.md +452 -18
- package/dist/system/assets/docs/CHAT_PROMPT.md +28 -0
- package/dist/system/assets/docs/DML_AUTHORING.md +8 -4
- package/dist/system/assets/docs/DML_FORMS.md +740 -0
- package/dist/system/assets/docs/DML_REFERENCE.md +239 -4
- package/dist/system/assets/docs/HARNESS_EXAMPLES.md +94 -0
- package/dist/system/assets/index.d.ts +2 -2
- package/dist/system/assets/index.d.ts.map +1 -1
- package/dist/system/assets/index.js +4 -0
- package/dist/system/assets/index.js.map +1 -1
- package/dist/system/environment.d.ts +6 -0
- package/dist/system/environment.d.ts.map +1 -1
- package/dist/system/environment.js +5 -4
- package/dist/system/environment.js.map +1 -1
- package/dist/types.d.ts +48 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -2
- package/src/prolog-src/deepclause_mi.pl +786 -40
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The form registry: the host-owned state a form lives in.
|
|
3
|
+
*
|
|
4
|
+
* One registry per root session. It owns the spec, the values, a monotonic
|
|
5
|
+
* revision, and the waiters. `submit`/`close` (a *UI action*) produce a
|
|
6
|
+
* `FormChange`; `update`/`setIssues` (an *agent edit*) bump the revision for
|
|
7
|
+
* rendering but never wake a waiter — otherwise the agent's own edit would
|
|
8
|
+
* resolve its own `await_form`. See `docs/DML_FORMS.md` §7.
|
|
9
|
+
*/
|
|
10
|
+
import { applyDefaults, isPlainObject, } from './spec.js';
|
|
11
|
+
export class FormRegistry {
|
|
12
|
+
options;
|
|
13
|
+
forms = new Map();
|
|
14
|
+
waiters = new Map();
|
|
15
|
+
lastChange = new Map();
|
|
16
|
+
/** Per-form cursor: the last revision delivered to (or consumed by) a caller. */
|
|
17
|
+
delivered = new Map();
|
|
18
|
+
counter = 0;
|
|
19
|
+
constructor(options = {}) {
|
|
20
|
+
this.options = options;
|
|
21
|
+
}
|
|
22
|
+
/** Open (or replace) a form. Returns its id and revision. */
|
|
23
|
+
open(spec, options = {}) {
|
|
24
|
+
const formId = options.formId ?? spec.id ?? `form_${++this.counter}`;
|
|
25
|
+
const existing = this.forms.get(formId);
|
|
26
|
+
const revision = (existing?.revision ?? 0) + 1;
|
|
27
|
+
const values = applyDefaults(spec, options.values ?? existing?.values ?? {});
|
|
28
|
+
const record = {
|
|
29
|
+
formId,
|
|
30
|
+
spec,
|
|
31
|
+
values,
|
|
32
|
+
issues: [],
|
|
33
|
+
revision,
|
|
34
|
+
openRevision: revision,
|
|
35
|
+
state: 'open',
|
|
36
|
+
source: options.source ?? existing?.source,
|
|
37
|
+
};
|
|
38
|
+
this.forms.set(formId, record);
|
|
39
|
+
this.delivered.set(formId, revision);
|
|
40
|
+
this.emit({ type: 'form', op: 'open', formId, revision, spec, values, issues: [], source: record.source });
|
|
41
|
+
return { formId, revision, values };
|
|
42
|
+
}
|
|
43
|
+
/** Merge-patch a form (agent edit). Bumps the revision; does not wake waiters. */
|
|
44
|
+
update(formId, patch) {
|
|
45
|
+
const record = this.forms.get(formId);
|
|
46
|
+
if (!record)
|
|
47
|
+
return undefined;
|
|
48
|
+
record.values = mergePatch(record.values, patch);
|
|
49
|
+
record.revision += 1;
|
|
50
|
+
this.emit({ type: 'form', op: 'update', formId, revision: record.revision, patch, values: record.values, issues: record.issues });
|
|
51
|
+
return { revision: record.revision, values: record.values };
|
|
52
|
+
}
|
|
53
|
+
/** Attach per-field messages (agent edit). An empty list clears them. */
|
|
54
|
+
setIssues(formId, issues) {
|
|
55
|
+
const record = this.forms.get(formId);
|
|
56
|
+
if (!record)
|
|
57
|
+
return undefined;
|
|
58
|
+
record.issues = issues;
|
|
59
|
+
record.revision += 1;
|
|
60
|
+
this.emit({
|
|
61
|
+
type: 'form',
|
|
62
|
+
op: 'update',
|
|
63
|
+
formId,
|
|
64
|
+
revision: record.revision,
|
|
65
|
+
values: record.values,
|
|
66
|
+
issues,
|
|
67
|
+
});
|
|
68
|
+
return { revision: record.revision };
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* A UI action: record it, wake the waiters, and return the change. This is the
|
|
72
|
+
* only path that produces a change for `wait`.
|
|
73
|
+
*/
|
|
74
|
+
submit(formId, action, values = {}, errors = []) {
|
|
75
|
+
const record = this.forms.get(formId);
|
|
76
|
+
if (!record)
|
|
77
|
+
return undefined;
|
|
78
|
+
const previous = record.values;
|
|
79
|
+
record.values = { ...values };
|
|
80
|
+
record.revision += 1;
|
|
81
|
+
const changed = diffPaths(previous, record.values);
|
|
82
|
+
const change = {
|
|
83
|
+
formId,
|
|
84
|
+
revision: record.revision,
|
|
85
|
+
action,
|
|
86
|
+
values: record.values,
|
|
87
|
+
changed,
|
|
88
|
+
errors,
|
|
89
|
+
};
|
|
90
|
+
record.changed = changed;
|
|
91
|
+
this.lastChange.set(formId, change);
|
|
92
|
+
this.wake(formId, change);
|
|
93
|
+
return change;
|
|
94
|
+
}
|
|
95
|
+
/** Close a form. Pending waiters resolve with `closed`. */
|
|
96
|
+
close(formId, state = 'submitted', reason) {
|
|
97
|
+
const record = this.forms.get(formId);
|
|
98
|
+
if (!record)
|
|
99
|
+
return;
|
|
100
|
+
record.state = state;
|
|
101
|
+
record.revision += 1;
|
|
102
|
+
const change = { formId, revision: record.revision, action: 'closed', values: record.values };
|
|
103
|
+
this.lastChange.set(formId, change);
|
|
104
|
+
this.emit({ type: 'form', op: 'close', formId, revision: record.revision, state, values: record.values, reason });
|
|
105
|
+
this.wake(formId, change);
|
|
106
|
+
}
|
|
107
|
+
/** Resolve every pending waiter (turn abort). */
|
|
108
|
+
cancelPending(action = 'cancelled') {
|
|
109
|
+
for (const [formId, list] of this.waiters) {
|
|
110
|
+
const record = this.forms.get(formId);
|
|
111
|
+
const change = {
|
|
112
|
+
formId,
|
|
113
|
+
revision: record?.revision ?? 0,
|
|
114
|
+
action,
|
|
115
|
+
values: record?.values ?? {},
|
|
116
|
+
};
|
|
117
|
+
for (const waiter of list.splice(0))
|
|
118
|
+
this.settle(waiter, change);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Wait for a UI change. `since` defaults to the form's delivered cursor (set
|
|
123
|
+
* at open, advanced per delivery), so a caller need not track revisions and a
|
|
124
|
+
* submit that raced the wait is still delivered.
|
|
125
|
+
*/
|
|
126
|
+
wait(formId, since, options = {}) {
|
|
127
|
+
const record = this.forms.get(formId);
|
|
128
|
+
if (!record) {
|
|
129
|
+
return Promise.resolve({ formId, revision: 0, action: 'unavailable', values: {} });
|
|
130
|
+
}
|
|
131
|
+
const cursor = since !== undefined && since >= 0 ? since : this.delivered.get(formId) ?? 0;
|
|
132
|
+
const existing = this.lastChange.get(formId);
|
|
133
|
+
if (existing && existing.revision > cursor) {
|
|
134
|
+
this.delivered.set(formId, existing.revision);
|
|
135
|
+
return Promise.resolve(existing);
|
|
136
|
+
}
|
|
137
|
+
if (record.state !== 'open') {
|
|
138
|
+
return Promise.resolve({ formId, revision: record.revision, action: 'closed', values: record.values });
|
|
139
|
+
}
|
|
140
|
+
return new Promise((resolve) => {
|
|
141
|
+
const waiter = { since: cursor, resolve };
|
|
142
|
+
if (options.timeoutMs !== undefined && options.timeoutMs > 0) {
|
|
143
|
+
waiter.timer = setTimeout(() => {
|
|
144
|
+
this.removeWaiter(formId, waiter);
|
|
145
|
+
this.settle(waiter, { formId, revision: record.revision, action: 'timeout', values: record.values });
|
|
146
|
+
}, options.timeoutMs);
|
|
147
|
+
waiter.timer.unref?.();
|
|
148
|
+
}
|
|
149
|
+
if (options.signal) {
|
|
150
|
+
const onAbort = () => {
|
|
151
|
+
this.removeWaiter(formId, waiter);
|
|
152
|
+
this.settle(waiter, { formId, revision: record.revision, action: 'cancelled', values: record.values });
|
|
153
|
+
};
|
|
154
|
+
if (options.signal.aborted) {
|
|
155
|
+
onAbort();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
waiter.onAbort = onAbort;
|
|
159
|
+
waiter.signal = options.signal;
|
|
160
|
+
options.signal.addEventListener('abort', onAbort, { once: true });
|
|
161
|
+
}
|
|
162
|
+
const list = this.waiters.get(formId) ?? [];
|
|
163
|
+
list.push(waiter);
|
|
164
|
+
this.waiters.set(formId, list);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
get(formId) {
|
|
168
|
+
return this.forms.get(formId);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Forms that are open and left with a **change nobody has read**.
|
|
172
|
+
*
|
|
173
|
+
* That is either a form the model put in front of the person and never waited
|
|
174
|
+
* on (no change delivered since it was opened), or one it changed *after* the
|
|
175
|
+
* last delivery — showing errors for a rejected value, patching a computed
|
|
176
|
+
* field — which asks the person for another action nobody is waiting for.
|
|
177
|
+
*
|
|
178
|
+
* A conversational turn uses this so it cannot end with a form the person is
|
|
179
|
+
* still filling in: the submission would have nowhere to go.
|
|
180
|
+
*/
|
|
181
|
+
awaitingForms() {
|
|
182
|
+
return [...this.forms.values()].filter((record) => {
|
|
183
|
+
if (record.state !== 'open')
|
|
184
|
+
return false;
|
|
185
|
+
const delivered = this.delivered.get(record.formId) ?? 0;
|
|
186
|
+
return delivered <= record.openRevision || record.revision > delivered;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
list() {
|
|
190
|
+
return [...this.forms.values()];
|
|
191
|
+
}
|
|
192
|
+
// -------------------------------------------------------------------------
|
|
193
|
+
wake(formId, change) {
|
|
194
|
+
const list = this.waiters.get(formId);
|
|
195
|
+
if (!list)
|
|
196
|
+
return;
|
|
197
|
+
this.delivered.set(formId, change.revision);
|
|
198
|
+
for (const waiter of list.splice(0))
|
|
199
|
+
this.settle(waiter, change);
|
|
200
|
+
}
|
|
201
|
+
settle(waiter, change) {
|
|
202
|
+
if (waiter.timer) {
|
|
203
|
+
clearTimeout(waiter.timer);
|
|
204
|
+
waiter.timer = undefined;
|
|
205
|
+
}
|
|
206
|
+
// Detach the abort hook; a successful wake must not also cancel the waiter.
|
|
207
|
+
// (Calling `onAbort` here resolved every submitted form as `cancelled`.)
|
|
208
|
+
if (waiter.signal && waiter.onAbort) {
|
|
209
|
+
waiter.signal.removeEventListener('abort', waiter.onAbort);
|
|
210
|
+
}
|
|
211
|
+
waiter.onAbort = undefined;
|
|
212
|
+
waiter.resolve(change);
|
|
213
|
+
}
|
|
214
|
+
removeWaiter(formId, waiter) {
|
|
215
|
+
const list = this.waiters.get(formId);
|
|
216
|
+
if (!list)
|
|
217
|
+
return;
|
|
218
|
+
const index = list.indexOf(waiter);
|
|
219
|
+
if (index >= 0)
|
|
220
|
+
list.splice(index, 1);
|
|
221
|
+
}
|
|
222
|
+
emit(event) {
|
|
223
|
+
this.options.onEvent?.(event);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// ---------------------------------------------------------------------------
|
|
227
|
+
// Merge patch (RFC 7386) and a shallow path diff
|
|
228
|
+
// ---------------------------------------------------------------------------
|
|
229
|
+
export function mergePatch(target, patch) {
|
|
230
|
+
if (!isPlainObject(patch))
|
|
231
|
+
return patch;
|
|
232
|
+
const base = isPlainObject(target) ? { ...target } : {};
|
|
233
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
234
|
+
if (value === null)
|
|
235
|
+
delete base[key];
|
|
236
|
+
else
|
|
237
|
+
base[key] = mergePatch(base[key], value);
|
|
238
|
+
}
|
|
239
|
+
return base;
|
|
240
|
+
}
|
|
241
|
+
/** Dotted paths that differ between two value trees. */
|
|
242
|
+
export function diffPaths(before, after, prefix = '') {
|
|
243
|
+
const out = [];
|
|
244
|
+
const keys = [...new Set([...Object.keys(before), ...Object.keys(after)])].sort();
|
|
245
|
+
for (const key of keys) {
|
|
246
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
247
|
+
const a = before[key];
|
|
248
|
+
const b = after[key];
|
|
249
|
+
if (isPlainObject(a) && isPlainObject(b))
|
|
250
|
+
out.push(...diffPaths(a, b, path));
|
|
251
|
+
else if (JSON.stringify(a) !== JSON.stringify(b))
|
|
252
|
+
out.push(path);
|
|
253
|
+
}
|
|
254
|
+
return out;
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/forms/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The form representation: the declarative spec a harness (or a model) produces,
|
|
3
|
+
* the values a UI collects, and the two validators.
|
|
4
|
+
*
|
|
5
|
+
* Pure functions and types — no runtime, no registry, no events. See
|
|
6
|
+
* `docs/DML_FORMS.md` §5.
|
|
7
|
+
*/
|
|
8
|
+
export type Json = string | number | boolean | null | Json[] | {
|
|
9
|
+
[key: string]: Json;
|
|
10
|
+
};
|
|
11
|
+
export type JsonObject = {
|
|
12
|
+
[key: string]: Json;
|
|
13
|
+
};
|
|
14
|
+
/** Presentation hint only; validation never reads it. */
|
|
15
|
+
export type Widget = 'text' | 'textarea' | 'number' | 'slider' | 'select' | 'radio' | 'multiselect' | 'checkbox' | 'switch' | 'date' | 'time' | 'datetime' | 'file' | 'hidden';
|
|
16
|
+
export type FieldType = 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array' | 'null';
|
|
17
|
+
export interface FieldOption {
|
|
18
|
+
value: string;
|
|
19
|
+
title?: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
}
|
|
22
|
+
interface FieldBase {
|
|
23
|
+
/** Unique within its parent. The contract: rules and patches address fields by path. */
|
|
24
|
+
name: string;
|
|
25
|
+
type: FieldType;
|
|
26
|
+
required?: boolean;
|
|
27
|
+
default?: Json;
|
|
28
|
+
title?: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
widget?: Widget;
|
|
31
|
+
}
|
|
32
|
+
export interface StringField extends FieldBase {
|
|
33
|
+
type: 'string';
|
|
34
|
+
format?: 'date' | 'time' | 'datetime' | 'email' | 'uri' | 'media';
|
|
35
|
+
enum?: string[];
|
|
36
|
+
options?: FieldOption[];
|
|
37
|
+
minLength?: number;
|
|
38
|
+
maxLength?: number;
|
|
39
|
+
pattern?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface NumberField extends FieldBase {
|
|
42
|
+
type: 'number' | 'integer';
|
|
43
|
+
minimum?: number;
|
|
44
|
+
maximum?: number;
|
|
45
|
+
multipleOf?: number;
|
|
46
|
+
}
|
|
47
|
+
export interface BooleanField extends FieldBase {
|
|
48
|
+
type: 'boolean';
|
|
49
|
+
}
|
|
50
|
+
export interface ObjectField extends FieldBase {
|
|
51
|
+
type: 'object';
|
|
52
|
+
properties: Field[];
|
|
53
|
+
}
|
|
54
|
+
export interface ArrayField extends FieldBase {
|
|
55
|
+
type: 'array';
|
|
56
|
+
items: Field;
|
|
57
|
+
minItems?: number;
|
|
58
|
+
maxItems?: number;
|
|
59
|
+
}
|
|
60
|
+
export interface NullField extends FieldBase {
|
|
61
|
+
type: 'null';
|
|
62
|
+
}
|
|
63
|
+
export type Field = StringField | NumberField | BooleanField | ObjectField | ArrayField | NullField;
|
|
64
|
+
export interface LayoutBase {
|
|
65
|
+
/** Grid columns this node occupies. */
|
|
66
|
+
span?: number;
|
|
67
|
+
}
|
|
68
|
+
export interface LayoutRow extends LayoutBase {
|
|
69
|
+
kind: 'row';
|
|
70
|
+
children: LayoutNode[];
|
|
71
|
+
gap?: number;
|
|
72
|
+
align?: 'start' | 'center' | 'end' | 'stretch';
|
|
73
|
+
wrap?: boolean;
|
|
74
|
+
}
|
|
75
|
+
export interface LayoutColumn extends LayoutBase {
|
|
76
|
+
kind: 'column';
|
|
77
|
+
children: LayoutNode[];
|
|
78
|
+
gap?: number;
|
|
79
|
+
}
|
|
80
|
+
export interface LayoutGrid extends LayoutBase {
|
|
81
|
+
kind: 'grid';
|
|
82
|
+
columns: number;
|
|
83
|
+
gap?: number;
|
|
84
|
+
children: LayoutNode[];
|
|
85
|
+
}
|
|
86
|
+
export interface LayoutBox extends LayoutBase {
|
|
87
|
+
kind: 'box';
|
|
88
|
+
title?: string;
|
|
89
|
+
description?: string;
|
|
90
|
+
variant?: 'plain' | 'card' | 'fieldset';
|
|
91
|
+
children: LayoutNode[];
|
|
92
|
+
}
|
|
93
|
+
export interface LayoutTabs extends LayoutBase {
|
|
94
|
+
kind: 'tabs';
|
|
95
|
+
tabs: Array<{
|
|
96
|
+
title: string;
|
|
97
|
+
children: LayoutNode[];
|
|
98
|
+
}>;
|
|
99
|
+
}
|
|
100
|
+
export interface LayoutField extends LayoutBase {
|
|
101
|
+
kind: 'field';
|
|
102
|
+
/** Path of a declared field. */
|
|
103
|
+
field: string;
|
|
104
|
+
widget?: Widget;
|
|
105
|
+
label?: string;
|
|
106
|
+
help?: string;
|
|
107
|
+
}
|
|
108
|
+
export interface LayoutText extends LayoutBase {
|
|
109
|
+
kind: 'text';
|
|
110
|
+
text: string;
|
|
111
|
+
variant?: 'body' | 'caption' | 'heading';
|
|
112
|
+
}
|
|
113
|
+
export interface LayoutDivider extends LayoutBase {
|
|
114
|
+
kind: 'divider';
|
|
115
|
+
}
|
|
116
|
+
export interface LayoutSpacer extends LayoutBase {
|
|
117
|
+
kind: 'spacer';
|
|
118
|
+
size?: number;
|
|
119
|
+
}
|
|
120
|
+
export type LayoutNode = LayoutRow | LayoutColumn | LayoutGrid | LayoutBox | LayoutTabs | LayoutField | LayoutText | LayoutDivider | LayoutSpacer;
|
|
121
|
+
export interface FormAction {
|
|
122
|
+
name: string;
|
|
123
|
+
title: string;
|
|
124
|
+
kind?: 'primary' | 'default' | 'danger' | 'link';
|
|
125
|
+
confirm?: string;
|
|
126
|
+
/** Paths to validate before the action is allowed, or `hard`/`all`. */
|
|
127
|
+
validates?: 'all' | 'hard' | string[];
|
|
128
|
+
}
|
|
129
|
+
export interface FormSpec {
|
|
130
|
+
version: 1;
|
|
131
|
+
id?: string;
|
|
132
|
+
title?: string;
|
|
133
|
+
description?: string;
|
|
134
|
+
fields: Field[];
|
|
135
|
+
layout?: LayoutNode[];
|
|
136
|
+
initial?: JsonObject;
|
|
137
|
+
actions?: FormAction[];
|
|
138
|
+
ui?: {
|
|
139
|
+
submitOnEnter?: boolean;
|
|
140
|
+
dense?: boolean;
|
|
141
|
+
};
|
|
142
|
+
meta?: JsonObject;
|
|
143
|
+
}
|
|
144
|
+
/** A per-field message, from the host (shape) or the harness (domain). */
|
|
145
|
+
export interface FormIssue {
|
|
146
|
+
path: string;
|
|
147
|
+
level: 'error' | 'warning';
|
|
148
|
+
message: string;
|
|
149
|
+
}
|
|
150
|
+
/** What a UI sends back when the user acts. */
|
|
151
|
+
export interface FormChange {
|
|
152
|
+
formId: string;
|
|
153
|
+
/** Monotonic; the race-free cursor. */
|
|
154
|
+
revision: number;
|
|
155
|
+
action: string;
|
|
156
|
+
values: JsonObject;
|
|
157
|
+
changed?: string[];
|
|
158
|
+
errors?: FormIssue[];
|
|
159
|
+
}
|
|
160
|
+
export declare const DEFAULT_ACTIONS: FormAction[];
|
|
161
|
+
export declare function actionsOf(spec: FormSpec): FormAction[];
|
|
162
|
+
export interface FieldRef {
|
|
163
|
+
path: string;
|
|
164
|
+
field: Field;
|
|
165
|
+
}
|
|
166
|
+
/** Every field, depth-first, with its dotted path (`a.b`, `items[0].c` is the value form). */
|
|
167
|
+
export declare function walkFields(fields: Field[], prefix?: string): FieldRef[];
|
|
168
|
+
/** The declared fields, keyed by path. */
|
|
169
|
+
export declare function fieldMap(spec: FormSpec): Map<string, Field>;
|
|
170
|
+
/** Resolve defaults into a complete value set (deepest-first). Never mutates input. */
|
|
171
|
+
export declare function applyDefaults(spec: FormSpec, values?: JsonObject): JsonObject;
|
|
172
|
+
export declare function isPlainObject(value: unknown): value is JsonObject;
|
|
173
|
+
/**
|
|
174
|
+
* Accept a spec the way a caller would naturally write one.
|
|
175
|
+
*
|
|
176
|
+
* `version` and a field's `type` are boilerplate: a model asked for "a form with
|
|
177
|
+
* an amount and a reason" should be able to answer `{title: "Refund", fields:
|
|
178
|
+
* [{name: "amount", type: "number"}, {name: "reason"}]}` and have it work.
|
|
179
|
+
* A bare string field is shorthand for a `string` field of that name.
|
|
180
|
+
*
|
|
181
|
+
* This only fills gaps. Anything genuinely broken (no fields, a duplicate or
|
|
182
|
+
* illegal name, a layout that references an unknown field) is still reported by
|
|
183
|
+
* `validateSpec`.
|
|
184
|
+
*/
|
|
185
|
+
export declare function normalizeSpec(raw: unknown): FormSpec;
|
|
186
|
+
/** True when `type` is one this runtime knows. */
|
|
187
|
+
export declare function isFieldType(type: unknown): type is FieldType;
|
|
188
|
+
export declare function validateSpec(spec: FormSpec): FormIssue[];
|
|
189
|
+
export declare function validateValues(spec: FormSpec, values: JsonObject): FormIssue[];
|
|
190
|
+
/** Read a dotted field path out of a value tree. */
|
|
191
|
+
export declare function valueAtPath(values: JsonObject, path: string): Json | undefined;
|
|
192
|
+
export {};
|
|
193
|
+
//# sourceMappingURL=spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/forms/spec.ts"],"names":[],"mappings":"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"}
|